예제 #1
0
class TestRfVoltageCalc(unittest.TestCase):
    # Simulation parameters -------------------------------------------------------
    # Bunch parameters
    N_b = 1e9           # Intensity
    N_p = 50000         # Macro-particles
    tau_0 = 0.4e-9          # Initial bunch length, 4 sigma [s]
    # Machine and RF parameters
    C = 26658.883        # Machine circumference [m]
    p_i = 450e9         # Synchronous momentum [eV/c]
    p_f = 460.005e9      # Synchronous momentum, final
    h = 35640            # Harmonic number
    V = 6e6                # RF voltage [V]
    dphi = 0             # Phase modulation/offset
    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

    # Run before every test
    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)

    # Run after every test

    def tearDown(self):
        pass

    def test_rf_voltage_calc_1(self):
        self.long_tracker.rf_voltage_calculation()
        orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(
            self.long_tracker.rf_voltage, orig_rf_voltage, decimal=8)

    def test_rf_voltage_calc_2(self):
        for i in range(100):
            self.long_tracker.rf_voltage_calculation()
            orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(
            self.long_tracker.rf_voltage, orig_rf_voltage, decimal=8)

    def test_rf_voltage_calc_3(self):
        for i in range(100):
            self.profile.track()
            self.long_tracker.track()
            self.long_tracker.rf_voltage_calculation()
            orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(
            self.long_tracker.rf_voltage, orig_rf_voltage, decimal=8)
    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)
예제 #3
0
    def test_vind(self):

        # randomly chose omega_c from allowed range
        np.random.seed(1980)
        factor = np.random.uniform(0.9, 1.1)

        # round results to this digits
        digit_round = 8

        # SPS parameters
        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
        V = 4.5e6  # 200 MHz RF voltage
        phi = 0.  # 200 MHz RF phase

        # Beam and tracking parameters
        N_m = 1e5  # Number of macro-particles for tracking
        N_b = 1.0e11  # Bunch intensity [ppb]
        N_t = 1  # Number of turns to track

        ring = Ring(C, alpha, p_s, Proton(), n_turns=N_t)
        rf = RFStation(ring, h, V, phi)
        beam = Beam(ring, N_m, N_b)
        bigaussian(ring, rf, beam, 3.2e-9 / 4, seed=1234, reinsertion=True)

        n_shift = 5  # how many rf-buckets to shift beam
        beam.dt += n_shift * rf.t_rf[0, 0]
        profile = Profile(beam,
                          CutOptions=CutOptions(
                              cut_left=(n_shift - 1.5) * rf.t_rf[0, 0],
                              cut_right=(n_shift + 1.5) * rf.t_rf[0, 0],
                              n_slices=140))
        profile.track()

        l_cav = 16.082
        v_g = 0.0946
        tau = l_cav / (v_g * c) * (1 + v_g)
        TWC_impedance_source = TravelingWaveCavity(l_cav**2 * 27.1e3 / 8,
                                                   200.222e6, 2 * np.pi * tau)

        # Beam loading by convolution of beam and wake from cavity
        inducedVoltageTWC = InducedVoltageTime(beam, profile,
                                               [TWC_impedance_source])
        induced_voltage = TotalInducedVoltage(beam, profile,
                                              [inducedVoltageTWC])
        induced_voltage.induced_voltage_sum()
        V_ind_impSource = np.around(induced_voltage.induced_voltage,
                                    digit_round)

        # Beam loading via feed-back system
        OTFB_4 = SPSOneTurnFeedback(rf, beam, profile, 4, n_cavities=1)
        OTFB_4.counter = 0  # First turn

        OTFB_4.omega_c = factor * OTFB_4.TWC.omega_r
        # Compute impulse response
        OTFB_4.TWC.impulse_response_beam(OTFB_4.omega_c, profile.bin_centers)

        # Compute induced voltage in (I,Q) coordinates
        OTFB_4.beam_induced_voltage(lpf=False)
        # convert back to time
        V_ind_OTFB \
            = OTFB_4.V_fine_ind_beam.real \
                * np.cos(OTFB_4.omega_c*profile.bin_centers) \
            + OTFB_4.V_fine_ind_beam.imag \
                * np.sin(OTFB_4.omega_c*profile.bin_centers)
        V_ind_OTFB = np.around(V_ind_OTFB, digit_round)

        self.assertListEqual(
            V_ind_impSource.tolist(),
            V_ind_OTFB.tolist(),
            msg="In TravelingWaveCavity test_vind: induced voltages differ")
예제 #4
0
class TestSynchRad(unittest.TestCase):
    # SIMULATION PARAMETERS -------------------------------------------------------

    # Beam parameters
    particle_type = Electron()
    n_particles = int(1.7e11)
    n_macroparticles = int(1e5)
    sync_momentum = 175e9  # [eV]

    distribution_type = 'gaussian'
    emittance = 1.0
    distribution_variable = 'Action'

    # Machine and RF parameters
    radius = 15915.49
    gamma_transition = 377.96447
    C = 2 * np.pi * radius  # [m]

    # Tracking details
    n_turns = int(200)

    # Derived parameters
    E_0 = m_e * c**2 / e  # [eV]
    tot_beam_energy = np.sqrt(sync_momentum**2 + E_0**2)  # [eV]
    momentum_compaction = 1 / gamma_transition**2  # [1]

    # Cavities parameters
    n_rf_systems = 1
    harmonic_numbers = 133650
    voltage_program = 10e9
    phi_offset = np.pi

    bucket_length = C / c / harmonic_numbers
    n_sections = 2
    rho = 11e3

    # Run before every testn_turns
    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,
            seed=1000,
            distribution_type=self.distribution_type,
            distribution_variable=self.distribution_variable)

        self.slice_beam.track()
        self.slice_beam_cpp.track()

    # Run after every test

    def tearDown(self):
        pass

    def test_no_quant_exc_10t(self):
        os.environ['OMP_NUM_THREADS'] = '1'
        turns = 10
        atol = 0
        rtol_avg = 1e-7
        rtol_std = 1e-7
        SR = []
        SR_cpp = []

        for i in range(self.n_sections):
            SR.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par[i],
                                     self.beam,
                                     self.rho,
                                     quantum_excitation=False,
                                     python=True))

            SR_cpp.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par_cpp[i],
                                     self.beam_cpp,
                                     self.rho,
                                     quantum_excitation=False,
                                     python=False))
        map_ = []
        for i in range(self.n_sections):
            map_ += [self.longitudinal_tracker[i]] + [SR[i]]
        map_ += [self.slice_beam]

        map_cpp = []
        for i in range(self.n_sections):
            map_cpp += [self.longitudinal_tracker_cpp[i]] + [SR_cpp[i]]
        map_cpp += [self.slice_beam_cpp]

        avg_dt = np.zeros(turns)
        std_dt = np.zeros(turns)
        avg_dE = np.zeros(turns)
        std_dE = np.zeros(turns)

        avg_dt_cpp = np.zeros(turns)
        std_dt_cpp = np.zeros(turns)
        avg_dE_cpp = np.zeros(turns)
        std_dE_cpp = np.zeros(turns)

        for i in range(turns):
            for m in map_:
                m.track()
            for m in map_cpp:
                m.track()
            avg_dt[i] = np.mean(self.beam.dt)
            std_dt[i] = np.std(self.beam.dt)
            avg_dE[i] = np.mean(self.beam.dE)
            std_dE[i] = np.std(self.beam.dE)

            avg_dt_cpp[i] = np.mean(self.beam_cpp.dt)
            std_dt_cpp[i] = np.std(self.beam_cpp.dt)
            avg_dE_cpp[i] = np.mean(self.beam_cpp.dE)
            std_dE_cpp[i] = np.std(self.beam_cpp.dE)

        np.testing.assert_allclose(
            avg_dt,
            avg_dt_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dt arrays not close")
        np.testing.assert_allclose(
            std_dt,
            std_dt_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dt arrays not close")

        np.testing.assert_allclose(
            avg_dE,
            avg_dE_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dE arrays not close")
        np.testing.assert_allclose(
            std_dE,
            std_dE_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dE arrays not close")

    def test_with_quant_exc_10t(self):
        os.environ['OMP_NUM_THREADS'] = '1'
        turns = 10
        atol = 0
        rtol_avg = 1e-2
        rtol_std = 1e-2
        SR = []
        SR_cpp = []

        for i in range(self.n_sections):
            SR.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par[i],
                                     self.beam,
                                     self.rho,
                                     quantum_excitation=True,
                                     python=True))

            SR_cpp.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par_cpp[i],
                                     self.beam_cpp,
                                     self.rho,
                                     quantum_excitation=True,
                                     python=False))
        map_ = []
        for i in range(self.n_sections):
            map_ += [self.longitudinal_tracker[i]] + [SR[i]]
        map_ += [self.slice_beam]

        map_cpp = []
        for i in range(self.n_sections):
            map_cpp += [self.longitudinal_tracker_cpp[i]] + [SR_cpp[i]]
        map_cpp += [self.slice_beam_cpp]

        avg_dt = np.zeros(turns)
        std_dt = np.zeros(turns)
        avg_dE = np.zeros(turns)
        std_dE = np.zeros(turns)

        avg_dt_cpp = np.zeros(turns)
        std_dt_cpp = np.zeros(turns)
        avg_dE_cpp = np.zeros(turns)
        std_dE_cpp = np.zeros(turns)

        for i in range(turns):
            for m in map_:
                m.track()
            for m in map_cpp:
                m.track()
            avg_dt[i] = np.mean(self.beam.dt)
            std_dt[i] = np.std(self.beam.dt)
            avg_dE[i] = np.mean(self.beam.dE)
            std_dE[i] = np.std(self.beam.dE)

            avg_dt_cpp[i] = np.mean(self.beam_cpp.dt)
            std_dt_cpp[i] = np.std(self.beam_cpp.dt)
            avg_dE_cpp[i] = np.mean(self.beam_cpp.dE)
            std_dE_cpp[i] = np.std(self.beam_cpp.dE)

        np.testing.assert_allclose(
            avg_dt,
            avg_dt_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dt arrays not close")
        np.testing.assert_allclose(
            std_dt,
            std_dt_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dt arrays not close")

        np.testing.assert_allclose(
            avg_dE,
            avg_dE_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dE arrays not close")
        np.testing.assert_allclose(
            std_dE,
            std_dE_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dE arrays not close")

    def test_no_quant_exc_100t(self):
        os.environ['OMP_NUM_THREADS'] = '1'
        turns = 100
        atol = 0
        rtol_avg = 1e-7
        rtol_std = 1e-7
        SR = []
        SR_cpp = []

        for i in range(self.n_sections):
            SR.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par[i],
                                     self.beam,
                                     self.rho,
                                     quantum_excitation=False,
                                     python=True))

            SR_cpp.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par_cpp[i],
                                     self.beam_cpp,
                                     self.rho,
                                     quantum_excitation=False,
                                     python=False))
        map_ = []
        for i in range(self.n_sections):
            map_ += [self.longitudinal_tracker[i]] + [SR[i]]
        map_ += [self.slice_beam]

        map_cpp = []
        for i in range(self.n_sections):
            map_cpp += [self.longitudinal_tracker_cpp[i]] + [SR_cpp[i]]
        map_cpp += [self.slice_beam_cpp]

        avg_dt = np.zeros(turns)
        std_dt = np.zeros(turns)
        avg_dE = np.zeros(turns)
        std_dE = np.zeros(turns)

        avg_dt_cpp = np.zeros(turns)
        std_dt_cpp = np.zeros(turns)
        avg_dE_cpp = np.zeros(turns)
        std_dE_cpp = np.zeros(turns)

        for i in range(turns):
            for m in map_:
                m.track()
            for m in map_cpp:
                m.track()
            avg_dt[i] = np.mean(self.beam.dt)
            std_dt[i] = np.std(self.beam.dt)
            avg_dE[i] = np.mean(self.beam.dE)
            std_dE[i] = np.std(self.beam.dE)

            avg_dt_cpp[i] = np.mean(self.beam_cpp.dt)
            std_dt_cpp[i] = np.std(self.beam_cpp.dt)
            avg_dE_cpp[i] = np.mean(self.beam_cpp.dE)
            std_dE_cpp[i] = np.std(self.beam_cpp.dE)

        np.testing.assert_allclose(
            avg_dt,
            avg_dt_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dt arrays not close")
        np.testing.assert_allclose(
            std_dt,
            std_dt_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dt arrays not close")

        np.testing.assert_allclose(
            avg_dE,
            avg_dE_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dE arrays not close")
        np.testing.assert_allclose(
            std_dE,
            std_dE_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dE arrays not close")

    def test_with_quant_exc_100t(self):
        os.environ['OMP_NUM_THREADS'] = '1'
        turns = 100
        atol = 0
        rtol_avg = 1e-2
        rtol_std = 1e-1
        SR = []
        SR_cpp = []

        for i in range(self.n_sections):
            SR.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par[i],
                                     self.beam,
                                     self.rho,
                                     quantum_excitation=True,
                                     python=True))

            SR_cpp.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par_cpp[i],
                                     self.beam_cpp,
                                     self.rho,
                                     quantum_excitation=True,
                                     python=False))
        map_ = []
        for i in range(self.n_sections):
            map_ += [self.longitudinal_tracker[i]] + [SR[i]]
        map_ += [self.slice_beam]

        map_cpp = []
        for i in range(self.n_sections):
            map_cpp += [self.longitudinal_tracker_cpp[i]] + [SR_cpp[i]]
        map_cpp += [self.slice_beam_cpp]

        avg_dt = np.zeros(turns)
        std_dt = np.zeros(turns)
        avg_dE = np.zeros(turns)
        std_dE = np.zeros(turns)

        avg_dt_cpp = np.zeros(turns)
        std_dt_cpp = np.zeros(turns)
        avg_dE_cpp = np.zeros(turns)
        std_dE_cpp = np.zeros(turns)

        for i in range(turns):
            for m in map_:
                m.track()
            for m in map_cpp:
                m.track()
            avg_dt[i] = np.mean(self.beam.dt)
            std_dt[i] = np.std(self.beam.dt)
            avg_dE[i] = np.mean(self.beam.dE)
            std_dE[i] = np.std(self.beam.dE)

            avg_dt_cpp[i] = np.mean(self.beam_cpp.dt)
            std_dt_cpp[i] = np.std(self.beam_cpp.dt)
            avg_dE_cpp[i] = np.mean(self.beam_cpp.dE)
            std_dE_cpp[i] = np.std(self.beam_cpp.dE)

        np.testing.assert_allclose(
            avg_dt,
            avg_dt_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dt arrays not close")
        np.testing.assert_allclose(
            std_dt,
            std_dt_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dt arrays not close")

        np.testing.assert_allclose(
            avg_dE,
            avg_dE_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dE arrays not close")
        np.testing.assert_allclose(
            std_dE,
            std_dE_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dE arrays not close")

    def test_no_quant_exc_10t_parallel(self):
        os.environ['OMP_NUM_THREADS'] = '2'
        turns = 10
        atol = 0
        rtol_avg = 1e-7
        rtol_std = 1e-7
        SR = []
        SR_cpp = []

        for i in range(self.n_sections):
            SR.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par[i],
                                     self.beam,
                                     self.rho,
                                     quantum_excitation=False,
                                     python=True))

            SR_cpp.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par_cpp[i],
                                     self.beam_cpp,
                                     self.rho,
                                     quantum_excitation=False,
                                     python=False))
        map_ = []
        for i in range(self.n_sections):
            map_ += [self.longitudinal_tracker[i]] + [SR[i]]
        map_ += [self.slice_beam]

        map_cpp = []
        for i in range(self.n_sections):
            map_cpp += [self.longitudinal_tracker_cpp[i]] + [SR_cpp[i]]
        map_cpp += [self.slice_beam_cpp]

        avg_dt = np.zeros(turns)
        std_dt = np.zeros(turns)
        avg_dE = np.zeros(turns)
        std_dE = np.zeros(turns)

        avg_dt_cpp = np.zeros(turns)
        std_dt_cpp = np.zeros(turns)
        avg_dE_cpp = np.zeros(turns)
        std_dE_cpp = np.zeros(turns)

        for i in range(turns):
            for m in map_:
                m.track()
            for m in map_cpp:
                m.track()
            avg_dt[i] = np.mean(self.beam.dt)
            std_dt[i] = np.std(self.beam.dt)
            avg_dE[i] = np.mean(self.beam.dE)
            std_dE[i] = np.std(self.beam.dE)

            avg_dt_cpp[i] = np.mean(self.beam_cpp.dt)
            std_dt_cpp[i] = np.std(self.beam_cpp.dt)
            avg_dE_cpp[i] = np.mean(self.beam_cpp.dE)
            std_dE_cpp[i] = np.std(self.beam_cpp.dE)

        np.testing.assert_allclose(
            avg_dt,
            avg_dt_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dt arrays not close")
        np.testing.assert_allclose(
            std_dt,
            std_dt_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dt arrays not close")

        np.testing.assert_allclose(
            avg_dE,
            avg_dE_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dE arrays not close")
        np.testing.assert_allclose(
            std_dE,
            std_dE_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dE arrays not close")

    def test_with_quant_exc_10t_parallel(self):
        os.environ['OMP_NUM_THREADS'] = '2'
        turns = 10
        atol = 0
        rtol_avg = 1e-2
        rtol_std = 1e-2
        SR = []
        SR_cpp = []

        for i in range(self.n_sections):
            SR.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par[i],
                                     self.beam,
                                     self.rho,
                                     quantum_excitation=True,
                                     python=True))

            SR_cpp.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par_cpp[i],
                                     self.beam_cpp,
                                     self.rho,
                                     quantum_excitation=True,
                                     python=False))
        map_ = []
        for i in range(self.n_sections):
            map_ += [self.longitudinal_tracker[i]] + [SR[i]]
        map_ += [self.slice_beam]

        map_cpp = []
        for i in range(self.n_sections):
            map_cpp += [self.longitudinal_tracker_cpp[i]] + [SR_cpp[i]]
        map_cpp += [self.slice_beam_cpp]

        avg_dt = np.zeros(turns)
        std_dt = np.zeros(turns)
        avg_dE = np.zeros(turns)
        std_dE = np.zeros(turns)

        avg_dt_cpp = np.zeros(turns)
        std_dt_cpp = np.zeros(turns)
        avg_dE_cpp = np.zeros(turns)
        std_dE_cpp = np.zeros(turns)

        for i in range(turns):
            for m in map_:
                m.track()
            for m in map_cpp:
                m.track()
            avg_dt[i] = np.mean(self.beam.dt)
            std_dt[i] = np.std(self.beam.dt)
            avg_dE[i] = np.mean(self.beam.dE)
            std_dE[i] = np.std(self.beam.dE)

            avg_dt_cpp[i] = np.mean(self.beam_cpp.dt)
            std_dt_cpp[i] = np.std(self.beam_cpp.dt)
            avg_dE_cpp[i] = np.mean(self.beam_cpp.dE)
            std_dE_cpp[i] = np.std(self.beam_cpp.dE)

        np.testing.assert_allclose(
            avg_dt,
            avg_dt_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dt arrays not close")
        np.testing.assert_allclose(
            std_dt,
            std_dt_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dt arrays not close")

        np.testing.assert_allclose(
            avg_dE,
            avg_dE_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dE arrays not close")
        np.testing.assert_allclose(
            std_dE,
            std_dE_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dE arrays not close")

    def test_no_quant_exc_100t_parallel(self):
        os.environ['OMP_NUM_THREADS'] = '2'
        turns = 100
        atol = 0
        rtol_avg = 1e-7
        rtol_std = 1e-7
        SR = []
        SR_cpp = []

        for i in range(self.n_sections):
            SR.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par[i],
                                     self.beam,
                                     self.rho,
                                     quantum_excitation=False,
                                     python=True))

            SR_cpp.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par_cpp[i],
                                     self.beam_cpp,
                                     self.rho,
                                     quantum_excitation=False,
                                     python=False))
        map_ = []
        for i in range(self.n_sections):
            map_ += [self.longitudinal_tracker[i]] + [SR[i]]
        map_ += [self.slice_beam]

        map_cpp = []
        for i in range(self.n_sections):
            map_cpp += [self.longitudinal_tracker_cpp[i]] + [SR_cpp[i]]
        map_cpp += [self.slice_beam_cpp]

        avg_dt = np.zeros(turns)
        std_dt = np.zeros(turns)
        avg_dE = np.zeros(turns)
        std_dE = np.zeros(turns)

        avg_dt_cpp = np.zeros(turns)
        std_dt_cpp = np.zeros(turns)
        avg_dE_cpp = np.zeros(turns)
        std_dE_cpp = np.zeros(turns)

        for i in range(turns):
            for m in map_:
                m.track()
            for m in map_cpp:
                m.track()
            avg_dt[i] = np.mean(self.beam.dt)
            std_dt[i] = np.std(self.beam.dt)
            avg_dE[i] = np.mean(self.beam.dE)
            std_dE[i] = np.std(self.beam.dE)

            avg_dt_cpp[i] = np.mean(self.beam_cpp.dt)
            std_dt_cpp[i] = np.std(self.beam_cpp.dt)
            avg_dE_cpp[i] = np.mean(self.beam_cpp.dE)
            std_dE_cpp[i] = np.std(self.beam_cpp.dE)

        np.testing.assert_allclose(
            avg_dt,
            avg_dt_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dt arrays not close")
        np.testing.assert_allclose(
            std_dt,
            std_dt_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dt arrays not close")

        np.testing.assert_allclose(
            avg_dE,
            avg_dE_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dE arrays not close")
        np.testing.assert_allclose(
            std_dE,
            std_dE_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dE arrays not close")

    def test_with_quant_exc_100t_parallel(self):
        os.environ['OMP_NUM_THREADS'] = '2'
        turns = 100
        atol = 0
        rtol_avg = 1e-2
        rtol_std = 1e-1
        SR = []
        SR_cpp = []

        for i in range(self.n_sections):
            SR.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par[i],
                                     self.beam,
                                     self.rho,
                                     quantum_excitation=True,
                                     python=True))

            SR_cpp.append(
                SynchrotronRadiation(self.general_params,
                                     self.RF_sct_par_cpp[i],
                                     self.beam_cpp,
                                     self.rho,
                                     quantum_excitation=True,
                                     python=False))
        map_ = []
        for i in range(self.n_sections):
            map_ += [self.longitudinal_tracker[i]] + [SR[i]]
        map_ += [self.slice_beam]

        map_cpp = []
        for i in range(self.n_sections):
            map_cpp += [self.longitudinal_tracker_cpp[i]] + [SR_cpp[i]]
        map_cpp += [self.slice_beam_cpp]

        avg_dt = np.zeros(turns)
        std_dt = np.zeros(turns)
        avg_dE = np.zeros(turns)
        std_dE = np.zeros(turns)

        avg_dt_cpp = np.zeros(turns)
        std_dt_cpp = np.zeros(turns)
        avg_dE_cpp = np.zeros(turns)
        std_dE_cpp = np.zeros(turns)

        for i in range(turns):
            for m in map_:
                m.track()
            for m in map_cpp:
                m.track()
            avg_dt[i] = np.mean(self.beam.dt)
            std_dt[i] = np.std(self.beam.dt)
            avg_dE[i] = np.mean(self.beam.dE)
            std_dE[i] = np.std(self.beam.dE)

            avg_dt_cpp[i] = np.mean(self.beam_cpp.dt)
            std_dt_cpp[i] = np.std(self.beam_cpp.dt)
            avg_dE_cpp[i] = np.mean(self.beam_cpp.dE)
            std_dE_cpp[i] = np.std(self.beam_cpp.dE)

        np.testing.assert_allclose(
            avg_dt,
            avg_dt_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dt arrays not close")
        np.testing.assert_allclose(
            std_dt,
            std_dt_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dt arrays not close")

        np.testing.assert_allclose(
            avg_dE,
            avg_dE_cpp,
            atol=atol,
            rtol=rtol_avg,
            err_msg="Pyhton and C++ avg beam dE arrays not close")
        np.testing.assert_allclose(
            std_dE,
            std_dE_cpp,
            atol=atol,
            rtol=rtol_std,
            err_msg="Pyhton and C++ std beam dE arrays not close")
예제 #5
0
class TestCavityFeedback(unittest.TestCase):

    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)
        
    def test_FB_pre_tracking(self):

        digit_round = 3

        Vind4_mean = np.around(
                np.mean(np.absolute(self.OTFB.OTFB_4.V_coarse_tot))/1e6,
                digit_round)
        Vind4_std = np.around(
                np.std(np.absolute(self.OTFB.OTFB_4.V_coarse_tot))/1e6,
                digit_round)
        Vind4_mean_exp = np.around(1.99886351363, digit_round)
        Vind4_std_exp = np.around(2.148426e-6, digit_round)

        Vind5_mean = np.around(
                np.mean(np.absolute(self.OTFB.OTFB_5.V_coarse_tot))/1e6,
                digit_round)
        Vind5_std = np.around(
                np.std(np.absolute(self.OTFB.OTFB_5.V_coarse_tot))/1e6,
                digit_round)
        Vind5_mean_exp = np.around(2.49906605189, digit_round)
        Vind5_std_exp = np.around(2.221665e-6, digit_round)

        self.assertEqual(Vind4_mean, Vind4_mean_exp,
            msg='In TestCavityFeedback test_FB_pretracking: '
            +'mean value of four-section cavity differs')
        self.assertEqual(Vind4_std, Vind4_std_exp,
            msg='In TestCavityFeedback test_FB_pretracking: standard '
            +'deviation of four-section cavity differs')

        self.assertEqual(Vind5_mean, Vind5_mean_exp,
            msg='In TestCavityFeedback test_FB_pretracking: '
            +'mean value of five-section cavity differs')
        self.assertEqual(Vind5_std, Vind5_std_exp,
            msg='In TestCavityFeedback test_FB_pretracking: standard '+
            'deviation of five-section cavity differs')
        
    def test_FB_pre_tracking_IQ_v1(self):
        digit_round = 2
        
        # interpolate from coarse mesh to fine mesh
        V_fine_tot_4 = np.interp(
                self.profile.bin_centers, self.OTFB.OTFB_4.rf_centers,
                self.OTFB.OTFB_4.V_coarse_ind_gen)
        V_fine_tot_5 = np.interp(
                self.profile.bin_centers, self.OTFB.OTFB_5.rf_centers,
                self.OTFB.OTFB_5.V_coarse_ind_gen)
        
        V_tot_4 = np.around(V_fine_tot_4/1e6, digit_round)
        V_tot_5 = np.around(V_fine_tot_5/1e6, digit_round)
        
        V_sum = np.around(self.OTFB.V_sum/1e6, digit_round)
        
        # expected generator voltage is only in Q
        V_tot_4_exp = 2.0j*np.ones(256)
        V_tot_5_exp = 2.5j*np.ones(256)
        V_sum_exp = 4.5j*np.ones(256)
        
        self.assertListEqual(V_tot_4.tolist(), V_tot_4_exp.tolist(),
            msg='In TestCavityFeedback test_FB_pretracking_IQ: total voltage '
            +'in four-section cavity differs')
        
        self.assertListEqual(V_tot_5.tolist(), V_tot_5_exp.tolist(),
            msg='In TestCavityFeedback test_FB_pretracking_IQ: total voltage '
            +'in five-section cavity differs')
        
        self.assertListEqual(V_sum.tolist(), V_sum_exp.tolist(),
            msg='In TestCavityFeedback test_FB_pretracking_IQ: voltage sum '
            +' differs')
        
    def test_rf_voltage(self):
        
        digit_round = 8
        
        # compute voltage
        self.cavity_tracker.rf_voltage_calculation()

        # compute voltage after OTFB pre-tracking
        self.OTFB_tracker.rf_voltage_calculation()

        # Since there is a systematic offset between the voltages,
        # compare the maxium of the ratio
        max_ratio = np.max(self.cavity_tracker.rf_voltage
                           / self.OTFB_tracker.rf_voltage)
        max_ratio = np.around(max_ratio, digit_round)
        
        max_ratio_exp = np.around(1.0008217052569774, digit_round)
        self.assertAlmostEqual(max_ratio, max_ratio_exp,
                               places=digit_round,
                         msg='In TestCavityFeedback test_rf_voltage: '
                         + 'RF-voltages differ')

    def test_beam_loading(self):

        digit_round = 10
        
        # Compute voltage with beam loading
        self.cavity_tracker.rf_voltage_calculation()
        cavity_tracker_total_voltage = self.cavity_tracker.rf_voltage \
            + self.cavity_tracker.totalInducedVoltage.induced_voltage

        self.OTFB.track()
        self.OTFB_tracker.rf_voltage_calculation()
        OTFB_tracker_total_voltage = self.OTFB_tracker.rf_voltage

        max_ratio = np.around(np.max(cavity_tracker_total_voltage
                                 / OTFB_tracker_total_voltage), digit_round)
        max_ration_exp = np.around(1.0051759770680779, digit_round)

        self.assertEqual(max_ratio, max_ration_exp,
                         msg='In TestCavityFeedback test_beam_loading: '
                         + 'total voltages differ')
        
    def test_Vsum_IQ(self):
        digit_round = 4
        
        self.OTFB.track()
        
        V_sum = np.around(self.OTFB.V_sum/1e6, digit_round)
        
        V_sum_exp = np.around(np.array([-7.40650823e+01+4497812.99202967j,
        -7.40650823e+01+4497812.99202967j, -7.40650823e+01+4497812.99202967j,
        -7.40650823e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650823e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j, -7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j,-7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j,-7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202967j,-7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202967j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -7.40650822e+01+4497812.99202968j,-7.40650822e+01+4497812.99202968j,
        -6.02318851e+01+4497817.94162674j,-1.98390915e+01+4497835.4539936j ,
         1.93158486e+01+4497855.56826354j,4.37055412e+01+4497871.87009121j,
         7.72626261e+01+4497900.35036866j,1.08879867e+02+4497930.96118169j,
         1.36226374e+02+4497965.43834138j,1.83914308e+02+4498039.43198652j,
         2.58060957e+02+4498182.7842137j ,3.46527521e+02+4498400.20917783j,
         4.26706222e+02+4498667.15544146j,4.94661306e+02+4499027.56784064j,
         5.43482338e+02+4499582.92538958j,5.37601327e+02+4500375.11759629j,
         4.18116316e+02+4501483.68340875j,1.06781854e+02+4502992.29896325j,
        -5.18346745e+02+4504994.88486696j,-1.49458714e+03+4507337.42385509j,
        -3.01163886e+03+4510119.3419273j ,-5.32851179e+03+4513546.45481774j,
        -8.74569640e+03+4517649.58201841j,-1.36711235e+04+4522515.97696859j,
        -2.06268308e+04+4528145.57335092j,-3.07188747e+04+4534772.43779405j,
        -4.42705242e+04+4541938.02912512j,-6.14651616e+04+4548954.45228089j,
        -8.23300421e+04+4555211.22162217j,-1.09421551e+05+4560368.34346543j,
        -1.43885886e+05+4563628.1865127j ,-1.85808399e+05+4563383.852869j  ,
        -2.36208282e+05+4558209.23829535j,-2.94836934e+05+4546270.53281669j,
        -3.63317854e+05+4525133.07455768j,-4.41779074e+05+4492246.31582297j,
        -5.28977031e+05+4445197.26263046j,-6.24427353e+05+4380854.18329653j,
        -7.28570463e+05+4294604.34393273j,-8.41413067e+05+4180725.12037253j,
        -9.58666802e+05+4036850.21934613j,-1.07489637e+06+3861588.24443417j,
        -1.18692079e+06+3650150.96222293j,-1.28868132e+06+3402561.33925834j,
        -1.37503355e+06+3113868.12951949j,-1.44047679e+06+2779413.13521708j,
        -1.47644078e+06+2402815.35953829j,-1.47522678e+06+1985042.23744602j,
        -1.42897968e+06+1528424.34271266j,-1.32931255e+06+1034805.30411738j,
        -1.16912937e+06 +511261.80102318j,-9.43345126e+05  -30406.39494472j,
        -6.44543913e+05 -585971.64269612j,-2.67898382e+05-1147041.0353738j ,
         1.87647422e+05-1699739.23544117j,7.19585769e+05-2229855.79356738j,
         1.32653137e+06-2725965.80099238j,2.00691053e+06-3178849.17084715j,
         2.75728744e+06-3578075.86057957j,3.56230981e+06-3910440.14562456j,
         4.40408617e+06-4164575.91355405j,5.28572695e+06-4338227.19020188j,
         6.19719564e+06-4426787.10912655j,7.11277008e+06-4425807.66220696j,
         8.01692653e+06-4335730.38899002j,8.89765817e+06-4159572.80505286j,
         9.74683705e+06-3900763.99853979j,1.05559999e+07-3564480.67012727j,
         1.13018718e+07-3165395.29765105j,1.19781005e+07-2712267.95526922j,
         1.25833208e+07-2214895.26359232j,1.31112101e+07-1685734.89623327j,
         1.35640429e+07-1132761.26804116j,1.39371556e+07 -573495.98893318j,
         1.42323033e+07  -19883.35687916j,1.44559502e+07 +521811.95451886j,
         1.46134106e+07+1043190.45283868j,1.47105373e+07+1534116.02749795j,
         1.47549265e+07+1994083.71851812j,1.47545428e+07+2416602.70892133j,
         1.47166958e+07+2794242.30539414j,1.46493955e+07+3129779.93382244j,
         1.45593030e+07+3424466.23125072j,1.44539743e+07+3677716.51226699j,
         1.43401341e+07+3889644.33404043j,1.42224899e+07+4064982.31004726j,
         1.41063737e+07+4205965.72167177j,1.39946111e+07+4317244.42689922j,
         1.38886184e+07+4403883.23649077j,1.37894739e+07+4469861.27187975j,
         1.36989283e+07+4518194.75268176j,1.36191316e+07+4551305.81768837j,
         1.35495619e+07+4572524.22309931j,1.34903101e+07+4584597.89085099j,
         1.34406305e+07+4589814.4489974j ,1.33976876e+07+4590220.82697034j,
         1.33615022e+07+4587255.76269093j,1.33327026e+07+4582254.09185628j,
         1.33096130e+07+4576070.77968165j,1.32911752e+07+4569436.1321998j ,
         1.32768524e+07+4562928.08977976j,1.32656893e+07+4556810.85976046j,
         1.32570926e+07+4551309.42853408j,1.32504722e+07+4546502.73564931j,
         1.32453253e+07+4542354.45990368j,1.32414716e+07+4539159.11692844j,
         1.32386032e+07+4536873.63706821j,1.32362022e+07+4534949.63932622j,
         1.32341515e+07+4533397.43716764j,1.32323621e+07+4532141.64712087j,
         1.32307439e+07+4531156.20064611j,1.32292493e+07+4530633.17835778j,
         1.32277994e+07+4530492.96280951j,1.32263821e+07+4530446.25647796j,
         1.32249901e+07+4530405.83108728j,1.32236081e+07+4530431.11420123j,
         1.32222495e+07+4530467.44843446j,1.32208432e+07+4530611.48233323j,
         1.32193886e+07+4530847.10244979j,1.32179361e+07+4531084.60180009j,
         1.32164993e+07+4531317.55923836j,1.32150516e+07+4531560.32993118j,
         1.32135685e+07+4531829.29611484j,1.32120853e+07+4532098.20168656j,
         1.32106022e+07+4532367.04664624j,1.32091191e+07+4532635.83099376j,
         1.32076359e+07+4532904.55472902j,1.32061675e+07+4533173.93875581j,
         1.32046990e+07+4533443.26260922j,1.32032158e+07+4533711.80494598j,
         1.32017326e+07+4533980.28666989j,1.32002495e+07+4534248.70778084j,
         1.31987663e+07+4534517.06827872j,1.31972831e+07+4534785.36816343j,
         1.31957999e+07+4535053.60743485j,1.31943167e+07+4535321.78609287j,
         1.31928335e+07+4535589.90413737j,1.31913503e+07+4535857.96156826j,
         1.31898671e+07+4536125.95838542j,1.31883839e+07+4536393.89458873j,
         1.31869007e+07+4536661.77017809j,1.31854174e+07+4536929.58515338j,
         1.31839342e+07+4537197.33951451j,1.31824510e+07+4537465.03326134j,
         1.31809677e+07+4537732.66639378j,1.31794845e+07+4538000.23891172j,
         1.31780012e+07+4538267.75081504j,1.31765179e+07+4538535.20210364j,
         1.31750347e+07+4538802.5927774j ,1.31735514e+07+4539069.92283622j,
         1.31720681e+07+4539337.19227997j,1.31705848e+07+4539604.40110857j,
         1.31691016e+07+4539871.54932188j,1.31676183e+07+4540138.63691982j,
         1.31661350e+07+4540405.66390225j,1.31646517e+07+4540672.63026908j,
         1.31631684e+07+4540939.53602019j,1.31616850e+07+4541206.38115549j,
         1.31602017e+07+4541473.16567484j,1.31587184e+07+4541739.88957815j,
         1.31572351e+07+4542006.55286531j,1.31557517e+07+4542273.1555362j ,
         1.31542684e+07+4542539.69759073j,1.31527850e+07+4542806.17902876j,
         1.31513017e+07+4543072.59985021j,1.31498183e+07+4543338.96005496j,
         1.31483350e+07+4543605.2596429j ,1.31468516e+07+4543871.49861392j,
         1.31453682e+07+4544137.6769679j ,1.31438848e+07+4544403.79470476j,
         1.31424014e+07+4544669.85182436j,1.31409181e+07+4544935.84832662j,
         1.31394347e+07+4545201.7842114j ,1.31379513e+07+4545467.65947862j,
         1.31364679e+07+4545733.47412815j,1.31349844e+07+4545999.22815989j,
         1.31335010e+07+4546264.92157373j,1.31320176e+07+4546530.55436956j,
         1.31305342e+07+4546796.12654728j,1.31290507e+07+4547061.63810677j,
         1.31275673e+07+4547327.08904792j,1.31260839e+07+4547592.47937064j,
         1.31246004e+07+4547857.8090748j ,1.31231170e+07+4548123.0781603j ,
         1.31216335e+07+4548388.28662704j,1.31201500e+07+4548653.4344749j ,
         1.31186666e+07+4548918.52170378j,1.31171831e+07+4549183.54831356j,
         1.31156996e+07+4549448.51430414j,1.31142161e+07+4549713.41967541j,
         1.31127326e+07+4549978.26442727j])/1e6, digit_round)

        self.assertListEqual(V_sum.tolist(), V_sum_exp.tolist(),
            msg='In TestCavityFeedback test_Vsum_IQ: total voltage '
            +'is different from expected values!')
예제 #6
0
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



# Simulation setup ------------------------------------------------------------
ring = Ring(C, alpha, p, Proton(), N_t)
rf = RFStation(ring, [h], [V], [dphi])
beam = Beam(ring, N_p, N_b)
bigaussian(ring, rf, beam, tau_0/4, reinsertion = True, seed=1)
profile = Profile(beam, CutOptions=CutOptions(n_slices=100, cut_left=0, 
                                              cut_right=2.5e-9))
profile.track()                     

# Calculate oscillation amplitude from coordinates
dtmax, bin_centres, histogram = oscillation_amplitude_from_coordinates(ring, 
    rf, beam.dt, beam.dE, Np_histogram = 100)

# Normalise profiles
profile.n_macroparticles /= np.sum(profile.n_macroparticles)
histogram /= np.sum(histogram)

# Plot
plt.plot(profile.bin_centers, profile.n_macroparticles, 'b', 
         label=r'$\lambda(t)$')
plt.plot(bin_centres + 1.25e-9, histogram, 'r', 
         label='$\lambda(t_{\mathsf{max}})$')
plt.plot(profile.bin_centers[51:], profile.n_macroparticles[51:]*2*1.41*\

# DEFINE SLICES----------------------------------------------------------------

number_slices = 500
cut_options = CutOptions(cut_left= 0, cut_right=bucket_length, n_slices=number_slices)
slice_beam = Profile(beam, cut_options)


# Single RF -------------------------------------------------------------------
matched_from_distribution_function(beam, full_tracker, emittance=emittance, 
                                   distribution_type=distribution_type,
                                   distribution_variable=distribution_variable,
                                   main_harmonic_option='lowest_freq', seed=1256)

slice_beam.track()

[sync_freq_distribution_left, sync_freq_distribution_right], \
    [emittance_array_left, emittance_array_right], \
    [delta_time_left, delta_time_right], \
    particleDistributionFreq, synchronous_time = \
                         synchrotron_frequency_distribution(beam, full_tracker)

# Plot of the synchrotron frequency distribution
plt.figure('fs_distribution')
plt.plot(delta_time_left, sync_freq_distribution_left, lw=2, label='Left')
plt.plot(delta_time_right, sync_freq_distribution_right, 'r--', lw=2,
         label='Right')

## Analytical calculation of fs(phi)
gamma = tot_beam_energy / E_0
예제 #8
0
                        tau_0/4, seed=1)
bigaussian(general_params_res, RF_sct_par_res, my_beam_res,
                        tau_0/4, seed=1)

number_slices = 2**8
cut_options = CutOptions(cut_left= 0, cut_right=2*np.pi, n_slices=number_slices, 
                         RFSectionParameters=RF_sct_par, cuts_unit = 'rad')
slice_beam = Profile(my_beam, cut_options, FitOptions(fit_option='gaussian'))
cut_options_freq = CutOptions(cut_left= 0, cut_right=2*np.pi, n_slices=number_slices, 
                         RFSectionParameters=RF_sct_par_freq, cuts_unit = 'rad')
slice_beam_freq = Profile(my_beam_freq, cut_options_freq, FitOptions(fit_option='gaussian'))
cut_options_res = CutOptions(cut_left= 0, cut_right=2*np.pi, n_slices=number_slices, 
                         RFSectionParameters=ring_RF_section_res, cuts_unit = 'rad')
slice_beam_res = Profile(my_beam_res, cut_options_res, FitOptions(fit_option='gaussian'))

slice_beam.track()
slice_beam_freq.track()
slice_beam_res.track()

# MONITOR----------------------------------------------------------------------

bunchmonitor = BunchMonitor(general_params, ring_RF_section, my_beam, 
                            this_directory + '../output_files/EX_05_output_data',
                            Profile=slice_beam, buffer_time=1)

bunchmonitor_freq = BunchMonitor(general_params_freq, ring_RF_section_freq,
                         my_beam_freq, this_directory + '../output_files/EX_05_output_data_freq',
                         Profile=slice_beam_freq, buffer_time=1)
bunchmonitor_res = BunchMonitor(general_params_res, ring_RF_section_res,
                         my_beam_res, this_directory + '../output_files/EX_05_output_data_res',
                         Profile=slice_beam_res, buffer_time=1)
예제 #9
0
class TestRfVoltageCalcWCavityFB(unittest.TestCase):
    # Simulation parameters -------------------------------------------------------
    # Bunch parameters
    N_b = 1e9  # Intensity
    N_p = 50000  # Macro-particles
    tau_0 = 0.4e-9  # Initial bunch length, 4 sigma [s]
    # Machine and RF parameters
    C = 26658.883  # Machine circumference [m]
    p_i = 450e9  # Synchronous momentum [eV/c]
    p_f = 460.005e9  # Synchronous momentum, final
    h = 35640  # Harmonic number
    V = 6e6  # RF voltage [V]
    dphi = 0  # Phase modulation/offset
    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

    # Run before every test
    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)

    # Run after every test

    def tearDown(self):
        pass

    def test_rf_voltage_calc_1(self):
        self.long_tracker.cavityFB = CavityFB(1.1, 1.2)
        self.long_tracker.rf_voltage_calculation()
        orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)

    def test_rf_voltage_calc_2(self):
        self.long_tracker.cavityFB = CavityFB(1.1, 1.2)
        for i in range(100):
            self.long_tracker.rf_voltage_calculation()
            orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)

    def test_rf_voltage_calc_3(self):
        self.long_tracker.cavityFB = CavityFB(1.1, 1.2)
        for i in range(100):
            self.profile.track()
            self.long_tracker.track()
            self.long_tracker.rf_voltage_calculation()
            orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)

    def test_rf_voltage_calc_4(self):
        self.long_tracker.cavityFB = CavityFB(
            np.linspace(1, 1.5, self.profile.n_slices),
            np.linspace(0.1, 0.5, self.profile.n_slices))
        self.long_tracker.rf_voltage_calculation()
        orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)

    def test_rf_voltage_calc_5(self):
        self.long_tracker.cavityFB = CavityFB(
            np.linspace(1, 1.5, self.profile.n_slices),
            np.linspace(0.1, 0.5, self.profile.n_slices))
        for i in range(100):
            self.long_tracker.rf_voltage_calculation()
            orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)

    def test_rf_voltage_calc_6(self):
        self.long_tracker.cavityFB = CavityFB(
            np.linspace(1, 1.5, self.profile.n_slices),
            np.linspace(0.1, 0.5, self.profile.n_slices))
        for i in range(100):
            self.profile.track()
            self.long_tracker.track()
            self.long_tracker.rf_voltage_calculation()
            orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)

    def test_phi_modulation(self):

        timebase = np.linspace(0, 0.2, 10000)
        freq = 2E3
        amp = np.pi
        offset = 0
        harmonic = self.h
        phiMod = PMod(timebase, freq, amp, offset, harmonic)

        self.rf = RFStation(
            self.ring, [self.h], self.V * np.linspace(1, 1.1, self.N_t+1), \
            [self.dphi], phi_modulation = phiMod)

        self.long_tracker = RingAndRFTracker(self.rf,
                                             self.beam,
                                             Profile=self.profile)

        for i in range(self.N_t):
            self.long_tracker.track()
            self.assertEqual( \
                self.long_tracker.phi_rf[:, self.long_tracker.counter[0]-1], \
                self.rf.phi_modulation[0][0][i], msg = \
                """Phi modulation not added correctly in tracker""")
예제 #10
0
 def test_3(self):
     
     # Set up SPS conditions
     ring = Ring(2*np.pi*1100.009, 1/18**2, 25.92e9, Proton(), 1000)
     RF = RFStation(ring, 4620, 4.5e6, 0)
     beam = Beam(ring, 1e5, 1e11)
     bigaussian(ring, RF, beam, 3.2e-9/4, seed = 1234, reinsertion = True) 
     profile = Profile(beam, CutOptions(cut_left=-1.e-9, cut_right=6.e-9, 
                                        n_slices=100))
     profile.track()
     self.assertEqual(len(beam.dt), np.sum(profile.n_macroparticles), "In" +
         " TestBeamCurrent: particle number mismatch in Beam vs Profile")
     
     # RF current calculation with low-pass filter
     rf_current = rf_beam_current(profile, 2*np.pi*200.222e6, ring.t_rev[0])
     Iref_real = np.array([ -9.4646042539e-12,  -7.9596801534e-10,  
         -2.6993572787e-10,
         2.3790828610e-09,   6.4007063190e-09,   9.5444302650e-09,
         9.6957462918e-09,   6.9944771120e-09,   5.0040512366e-09,
         8.2427583408e-09,   1.6487066238e-08,   2.2178930587e-08,
         1.6497620890e-08,   1.9878201568e-09,  -2.4862807497e-09,
         2.0862096916e-08,   6.6115473293e-08,   1.1218114710e-07,
          1.5428441607e-07,   2.1264254596e-07,   3.1213935713e-07,
          4.6339212948e-07,   6.5039440158e-07,   8.2602190806e-07,
          9.4532001396e-07,   1.0161170159e-06,   1.0795840334e-06,
          1.1306004256e-06,   1.1081141333e-06,   9.7040873320e-07,
          7.1863437325e-07,   3.3833950889e-07,  -2.2273124358e-07,
         -1.0035204008e-06,  -1.9962696992e-06,  -3.1751183137e-06,
         -4.5326227784e-06,  -6.0940850385e-06,  -7.9138578879e-06,
         -9.9867317826e-06,  -1.2114906338e-05,  -1.4055138779e-05,
         -1.5925650405e-05,  -1.8096693885e-05,  -2.0418813156e-05,
         -2.2142865862e-05,  -2.3038234657e-05,  -2.3822481250e-05,
         -2.4891969829e-05,  -2.5543384520e-05,  -2.5196086909e-05,
         -2.4415522211e-05,  -2.3869116251e-05,  -2.3182951665e-05,
         -2.1723128723e-05,  -1.9724625363e-05,  -1.7805112266e-05,
         -1.5981218737e-05,  -1.3906226012e-05,  -1.1635865568e-05,
         -9.5381189596e-06,  -7.7236624815e-06,  -6.0416822483e-06,
         -4.4575806261e-06,  -3.0779237834e-06,  -1.9274519396e-06,
         -9.5699993457e-07,  -1.7840768971e-07,   3.7780452612e-07,
          7.5625231388e-07,   1.0158886027e-06,   1.1538975409e-06,
          1.1677937652e-06,   1.1105424636e-06,   1.0216131672e-06,
          8.8605026541e-07,   7.0783694846e-07,   5.4147914020e-07,
          4.1956457226e-07,   3.2130062098e-07,   2.2762751268e-07,
          1.4923020411e-07,   9.5683463322e-08,   5.8942895620e-08,
          3.0515695233e-08,   1.2444834300e-08,   8.9413517889e-09,
          1.6154761941e-08,   2.3261993674e-08,   2.3057968490e-08,
          1.8354179928e-08,   1.4938991667e-08,   1.2506841004e-08,
          8.1230022648e-09,   3.7428821201e-09,   2.8368110506e-09,
          3.6536247240e-09,   2.8429736524e-09,   1.6640835314e-09,
          2.3960087967e-09])
     I_real = np.around(rf_current.real, 9) # round
     Iref_real = np.around(Iref_real, 9) 
     self.assertSequenceEqual(I_real.tolist(), Iref_real.tolist(),
         msg="In TestRFCurrent test_3, mismatch in real part of RF current")
     Iref_imag = np.array([ -1.3134886055e-11,   1.0898262206e-09,   
         3.9806900984e-10,
         -3.0007980073e-09,  -7.4404909183e-09,  -9.5619658077e-09,
         -7.9029982105e-09,  -4.5153699012e-09,  -2.8337010673e-09,
         -4.0605999910e-09,  -5.7035811935e-09,  -4.9421561822e-09,
         -2.6226262365e-09,  -1.0904425703e-09,   1.5886725829e-10,
          3.6061564044e-09,   1.2213233410e-08,   3.0717134774e-08,
          6.2263860975e-08,   1.0789908935e-07,   1.8547368321e-07,
          3.3758410599e-07,   5.8319210090e-07,   8.7586115583e-07,
          1.1744525681e-06,   1.5330067491e-06,   2.0257108185e-06,
          2.6290348930e-06,   3.3065045701e-06,   4.1218136471e-06,
          5.1059358251e-06,   6.1421308306e-06,   7.1521192647e-06,
          8.2164613957e-06,   9.3474086978e-06,   1.0368027059e-05,
          1.1176114701e-05,   1.1892303251e-05,   1.2600522466e-05,
          1.3142991032e-05,   1.3286611961e-05,   1.2972067098e-05,
          1.2344251145e-05,   1.1561930031e-05,   1.0577353622e-05,
          9.1838382917e-06,   7.3302333455e-06,   5.2367297732e-06,
          3.1309520147e-06,   1.0396785645e-06,  -1.1104442284e-06,
         -3.3300486963e-06,  -5.5129705406e-06,  -7.4742790081e-06,
         -9.1003715719e-06,  -1.0458342224e-05,  -1.1632423668e-05,
         -1.2513736332e-05,  -1.2942309414e-05,  -1.2975831165e-05,
         -1.2799952495e-05,  -1.2469945465e-05,  -1.1941176358e-05,
         -1.1222986380e-05,  -1.0349594257e-05,  -9.3491445482e-06,
         -8.2956327726e-06,  -7.2394219079e-06,  -6.1539590898e-06,
         -5.0802321519e-06,  -4.1512021086e-06,  -3.3868884793e-06,
         -2.6850344653e-06,  -2.0327038471e-06,  -1.5048854341e-06,
         -1.0965986189e-06,  -7.4914749272e-07,  -4.7128817088e-07,
         -2.9595396024e-07,  -1.9387567373e-07,  -1.1597751838e-07,
         -5.5766761837e-08,  -2.3991059778e-08,  -1.1910924971e-08,
         -4.7797889603e-09,   9.0715301612e-11,   1.5744084129e-09,
          2.8217939283e-09,   5.5919203984e-09,   7.7259433940e-09,
          8.5033504655e-09,   9.1509256107e-09,   8.6746085156e-09,
          5.8909590412e-09,   3.5957212556e-09,   4.3347189168e-09,
          5.3331969589e-09,   3.9322184713e-09,   3.3616434953e-09,
          6.5154351819e-09])
     I_imag = np.around(rf_current.imag, 9) # round
     Iref_imag = np.around(Iref_imag, 9)
     self.assertSequenceEqual(I_imag.tolist(), Iref_imag.tolist(),
         msg="In TestRFCurrent test_3, mismatch in imaginary part of RF current")
예제 #11
0
class TestRFCurrent(unittest.TestCase):

    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 test_1(self):

        t = self.profile.bin_centers
        self.profile.n_macroparticles \
            = 2600*np.exp(-(t-2.5e-9)**2 / (2*0.5e-9)**2)

        rf_current = rf_beam_current(self.profile, self.omega,
                                     self.ring.t_rev[0], lpf=False)

        rf_current_real = np.around(rf_current.real, 12)
        rf_current_imag = np.around(rf_current.imag, 12)

        rf_theo_real = 2*self.beam.ratio*self.profile.Beam.Particle.charge*e\
            * 2600*np.exp(-(t-2.5e-9)**2/(2*0.5*1e-9)**2)\
            * np.cos(self.omega*t)
        rf_theo_real = np.around(rf_theo_real, 12)

        rf_theo_imag = 2*self.beam.ratio*self.profile.Beam.Particle.charge*e\
            * 2600*np.exp(-(t-2.5e-9)**2/(2*0.5*1e-9)**2)\
            * np.sin(self.omega*t)
        rf_theo_imag = np.around(rf_theo_imag, 12)

        self.assertListEqual(rf_current_real.tolist(), rf_theo_real.tolist(),
            msg="In TestRfCurrent test_1, mismatch in real part of RF current")
        self.assertListEqual(rf_current_imag.tolist(), rf_theo_imag.tolist(),
            msg="In TestRfCurrent test_1, mismatch in real part of RF current")

    def test_2(self):
        
        RF = RFStation(self.ring, 4620, 4.5e6, 0)

        bigaussian(self.ring, RF, self.beam, 3.2e-9/4, seed = 1234,
                   reinsertion = True)
        self.profile.track()
        
        rf_current = rf_beam_current(self.profile, self.omega,
                                     self.ring.t_rev[0], lpf=False)

        Iref_real = np.array(
                [0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
                 0.00000000e+00, 4.17276535e-13, 4.58438681e-13,
                 2.48023976e-13, 5.29812878e-13, 2.79735891e-13,
                 0.00000000e+00, 1.21117141e-12, 9.32525023e-13,
                 3.16481489e-13, 6.39337176e-13, 0.00000000e+00,
                 0.00000000e+00, 4.08671434e-12, 4.92294314e-12,
                 6.56965575e-12, 1.06279981e-11, 1.36819774e-11,
                 2.16648778e-11, 3.09847740e-11, 3.52971849e-11,
                 4.70378842e-11, 4.53538351e-11, 4.87255679e-11,
                 5.36705228e-11, 5.13609263e-11, 4.32833543e-11,
                 3.41417624e-11, 1.57452091e-11, -1.09005668e-11,
                 -4.60465929e-11, -9.12872553e-11, -1.48257171e-10,
                 -2.08540597e-10, -2.77630608e-10, -3.72157667e-10,
                 -4.56272786e-10, -5.57978710e-10, -6.46554672e-10,
                 -7.48006839e-10, -8.21493943e-10, -9.37522966e-10,
                 -1.03729659e-09, -1.06159943e-09, -1.08434837e-09,
                 -1.15738771e-09, -1.17887328e-09, -1.17146946e-09,
                 -1.10964397e-09, -1.10234198e-09, -1.08852433e-09,
                 -9.85866185e-10, -9.11727492e-10, -8.25604179e-10,
                 -7.34122902e-10, -6.47294094e-10, -5.30372699e-10,
                 -4.40357820e-10, -3.61273445e-10, -2.76871612e-10,
                 -2.02227691e-10, -1.45430219e-10, -8.88675652e-11,
                 -4.28984525e-11, -8.85451321e-12,  1.79026289e-11,
                 3.48384211e-11,  4.50190278e-11, 5.62413467e-11,
                 5.27322593e-11,  4.98163111e-11, 4.83288193e-11,
                 4.18200848e-11,  3.13334266e-11, 2.44082106e-11,
                 2.12572803e-11,  1.37397871e-11, 1.00879346e-11,
                 7.78502206e-12,  4.00790815e-12, 2.51830412e-12,
                 1.91301488e-12,  0.00000000e+00, 9.58518921e-13,
                 3.16123806e-13,  1.24116545e-12, 1.20821671e-12,
                 5.82952178e-13,  8.35917228e-13, 5.27285250e-13,
                 4.93205915e-13,  0.00000000e+00, 2.06937011e-13,
                 1.84618141e-13,  1.60868490e-13, 0.00000000e+00,
                 1.09822742e-13])
        
        I_real = np.around(rf_current.real, 14) # round
        Iref_real = np.around(Iref_real, 14)
        
        self.assertSequenceEqual(I_real.tolist(), Iref_real.tolist(),
            msg="In TestRFCurrent test_2, mismatch in real part of RF current")
        
        Iref_imag = np.array([
                0.00000000e+00,   0.00000000e+00,   0.00000000e+00,
                0.00000000e+00,  -4.86410815e-13,  -4.47827158e-13,
                -2.02886432e-13,  -3.60573852e-13,  -1.56290206e-13,
                0.00000000e+00,  -4.19433613e-13,  -2.33465744e-13,
                -5.01823105e-14,  -4.43075921e-14,   0.00000000e+00,
                0.00000000e+00,   8.07144709e-13,   1.43192280e-12,
                2.55659168e-12,   5.25480064e-12,   8.33669524e-12,
                1.59729353e-11,   2.73609511e-11,   3.71844853e-11,
                5.92134758e-11,   6.87376280e-11,   9.02226570e-11,
                1.24465616e-10,   1.55478762e-10,   1.84035433e-10,
                2.37241518e-10,   2.86677989e-10,   3.28265272e-10,
                3.77882012e-10,   4.29727720e-10,   4.83759029e-10,
                5.13978173e-10,   5.41841031e-10,   5.91537968e-10,
                6.00658643e-10,   6.13928028e-10,   5.96367636e-10,
                5.76920099e-10,   5.25297875e-10,   4.89104065e-10,
                4.29776324e-10,   3.33901906e-10,   2.38690921e-10,
                1.49673305e-10,   4.78223853e-11,  -5.57081558e-11,
                -1.51374774e-10,  -2.50724894e-10,  -3.50731761e-10,
                -4.16547058e-10,  -4.83765618e-10,  -5.36075032e-10,
                -5.74421794e-10,  -6.05459147e-10,  -5.91794283e-10,
                -5.88179055e-10,  -5.83222843e-10,  -5.49774151e-10,
                -5.08571646e-10,  -4.86623358e-10,  -4.33179012e-10,
                -3.73737133e-10,  -3.37622742e-10,  -2.89119788e-10,
                -2.30660798e-10,  -1.85597518e-10,  -1.66348322e-10,
                -1.19981335e-10,  -9.07232680e-11,  -7.21467862e-11,
                -5.18977454e-11,  -3.25510912e-11,  -2.12524272e-11,
                -1.54447488e-11,  -8.24107056e-12,  -4.90052047e-12,
                -2.96720377e-12,  -1.13551262e-12,  -4.79152734e-13,
                -1.91861296e-13,   0.00000000e+00,   7.31481456e-14,
                5.23883203e-14,   3.19951675e-13,   4.27870459e-13,
                2.66236636e-13,   4.74712082e-13,   3.64260145e-13,
                4.09222572e-13,   0.00000000e+00,   2.44654594e-13,
                2.61906356e-13,   2.77128356e-13,   0.00000000e+00,
                3.01027843e-13])
        
        I_imag = np.around(rf_current.imag, 14) # round
        Iref_imag = np.around(Iref_imag, 14)
        
        self.assertSequenceEqual(I_imag.tolist(), Iref_imag.tolist(),
            msg="In TestRFCurrent test_2, mismatch in imaginary part of"
            + " RF current")
    
    # Skip this unit test, since its reference values are obsolete;
    # This test used to be in /unittests/general/test_cavity_feedback.py
    @unittest.skip('Skipping because of obsolete reference values!')
    def test_3(self):
        
        # Set up SPS conditions
        ring = Ring(2*np.pi*1100.009, 1/18**2, 25.92e9, Proton(), 1000)
        RF = RFStation(ring, 4620, 4.5e6, 0)
        beam = Beam(ring, 1e5, 1e11)
        bigaussian(ring, RF, beam, 3.2e-9/4, seed = 1234, reinsertion = True) 
        profile = Profile(beam, CutOptions(cut_left=-1.e-9, cut_right=6.e-9, 
                                           n_slices=100))
        profile.track()
        self.assertEqual(len(beam.dt), np.sum(profile.n_macroparticles), "In" +
            " TestBeamCurrent: particle number mismatch in Beam vs Profile")
        
        # RF current calculation with low-pass filter
        rf_current = rf_beam_current(profile, 2*np.pi*200.222e6, ring.t_rev[0])
        Iref_real = np.array([ -9.4646042539e-12,  -7.9596801534e-10,  
            -2.6993572787e-10,
            2.3790828610e-09,   6.4007063190e-09,   9.5444302650e-09,
            9.6957462918e-09,   6.9944771120e-09,   5.0040512366e-09,
            8.2427583408e-09,   1.6487066238e-08,   2.2178930587e-08,
            1.6497620890e-08,   1.9878201568e-09,  -2.4862807497e-09,
            2.0862096916e-08,   6.6115473293e-08,   1.1218114710e-07,
             1.5428441607e-07,   2.1264254596e-07,   3.1213935713e-07,
             4.6339212948e-07,   6.5039440158e-07,   8.2602190806e-07,
             9.4532001396e-07,   1.0161170159e-06,   1.0795840334e-06,
             1.1306004256e-06,   1.1081141333e-06,   9.7040873320e-07,
             7.1863437325e-07,   3.3833950889e-07,  -2.2273124358e-07,
            -1.0035204008e-06,  -1.9962696992e-06,  -3.1751183137e-06,
            -4.5326227784e-06,  -6.0940850385e-06,  -7.9138578879e-06,
            -9.9867317826e-06,  -1.2114906338e-05,  -1.4055138779e-05,
            -1.5925650405e-05,  -1.8096693885e-05,  -2.0418813156e-05,
            -2.2142865862e-05,  -2.3038234657e-05,  -2.3822481250e-05,
            -2.4891969829e-05,  -2.5543384520e-05,  -2.5196086909e-05,
            -2.4415522211e-05,  -2.3869116251e-05,  -2.3182951665e-05,
            -2.1723128723e-05,  -1.9724625363e-05,  -1.7805112266e-05,
            -1.5981218737e-05,  -1.3906226012e-05,  -1.1635865568e-05,
            -9.5381189596e-06,  -7.7236624815e-06,  -6.0416822483e-06,
            -4.4575806261e-06,  -3.0779237834e-06,  -1.9274519396e-06,
            -9.5699993457e-07,  -1.7840768971e-07,   3.7780452612e-07,
             7.5625231388e-07,   1.0158886027e-06,   1.1538975409e-06,
             1.1677937652e-06,   1.1105424636e-06,   1.0216131672e-06,
             8.8605026541e-07,   7.0783694846e-07,   5.4147914020e-07,
             4.1956457226e-07,   3.2130062098e-07,   2.2762751268e-07,
             1.4923020411e-07,   9.5683463322e-08,   5.8942895620e-08,
             3.0515695233e-08,   1.2444834300e-08,   8.9413517889e-09,
             1.6154761941e-08,   2.3261993674e-08,   2.3057968490e-08,
             1.8354179928e-08,   1.4938991667e-08,   1.2506841004e-08,
             8.1230022648e-09,   3.7428821201e-09,   2.8368110506e-09,
             3.6536247240e-09,   2.8429736524e-09,   1.6640835314e-09,
             2.3960087967e-09])
        I_real = np.around(rf_current.real, 9) # round
        Iref_real = np.around(Iref_real, 9) 
        self.assertSequenceEqual(I_real.tolist(), Iref_real.tolist(),
            msg="In TestRFCurrent test_3, mismatch in real part of RF current")
        Iref_imag = np.array([ -1.3134886055e-11,   1.0898262206e-09,   
            3.9806900984e-10,
            -3.0007980073e-09,  -7.4404909183e-09,  -9.5619658077e-09,
            -7.9029982105e-09,  -4.5153699012e-09,  -2.8337010673e-09,
            -4.0605999910e-09,  -5.7035811935e-09,  -4.9421561822e-09,
            -2.6226262365e-09,  -1.0904425703e-09,   1.5886725829e-10,
             3.6061564044e-09,   1.2213233410e-08,   3.0717134774e-08,
             6.2263860975e-08,   1.0789908935e-07,   1.8547368321e-07,
             3.3758410599e-07,   5.8319210090e-07,   8.7586115583e-07,
             1.1744525681e-06,   1.5330067491e-06,   2.0257108185e-06,
             2.6290348930e-06,   3.3065045701e-06,   4.1218136471e-06,
             5.1059358251e-06,   6.1421308306e-06,   7.1521192647e-06,
             8.2164613957e-06,   9.3474086978e-06,   1.0368027059e-05,
             1.1176114701e-05,   1.1892303251e-05,   1.2600522466e-05,
             1.3142991032e-05,   1.3286611961e-05,   1.2972067098e-05,
             1.2344251145e-05,   1.1561930031e-05,   1.0577353622e-05,
             9.1838382917e-06,   7.3302333455e-06,   5.2367297732e-06,
             3.1309520147e-06,   1.0396785645e-06,  -1.1104442284e-06,
            -3.3300486963e-06,  -5.5129705406e-06,  -7.4742790081e-06,
            -9.1003715719e-06,  -1.0458342224e-05,  -1.1632423668e-05,
            -1.2513736332e-05,  -1.2942309414e-05,  -1.2975831165e-05,
            -1.2799952495e-05,  -1.2469945465e-05,  -1.1941176358e-05,
            -1.1222986380e-05,  -1.0349594257e-05,  -9.3491445482e-06,
            -8.2956327726e-06,  -7.2394219079e-06,  -6.1539590898e-06,
            -5.0802321519e-06,  -4.1512021086e-06,  -3.3868884793e-06,
            -2.6850344653e-06,  -2.0327038471e-06,  -1.5048854341e-06,
            -1.0965986189e-06,  -7.4914749272e-07,  -4.7128817088e-07,
            -2.9595396024e-07,  -1.9387567373e-07,  -1.1597751838e-07,
            -5.5766761837e-08,  -2.3991059778e-08,  -1.1910924971e-08,
            -4.7797889603e-09,   9.0715301612e-11,   1.5744084129e-09,
             2.8217939283e-09,   5.5919203984e-09,   7.7259433940e-09,
             8.5033504655e-09,   9.1509256107e-09,   8.6746085156e-09,
             5.8909590412e-09,   3.5957212556e-09,   4.3347189168e-09,
             5.3331969589e-09,   3.9322184713e-09,   3.3616434953e-09,
             6.5154351819e-09])
        I_imag = np.around(rf_current.imag, 9) # round
        Iref_imag = np.around(Iref_imag, 9)
        self.assertSequenceEqual(I_imag.tolist(), Iref_imag.tolist(),
            msg="In TestRFCurrent test_3, mismatch in imaginary part of RF current")
    def setUp(self, negativeEta=True, acceleration=True, singleRF=True):
        # Defining parameters -------------------------------------------------
        # Bunch parameters
        N_b = 1.e9  # Intensity
        N_p = 100000  # Macro-particles
        tau_0 = 50.e-9  # Initial bunch length, 4 sigma [s]

        # Machine parameters
        C = 1567.5  # Machine circumference [m]
        p_1i = 3.e9  # Synchronous momentum [eV/c]
        p_1f = 30.0e9  # Synchronous momentum, final
        p_2f = 40.e9  # Synchronous momentum [eV/c]
        p_2i = 60.e9  # Synchronous momentum, final
        gamma_t = 31.6  # Transition gamma
        alpha_1 = -1. / gamma_t / gamma_t  # First order mom. comp. factor
        alpha_2 = 1. / gamma_t / gamma_t  # First order mom. comp. factor

        # RF parameters
        h = [9, 18]  # Harmonic number
        V = [1800.e3, 110.e3]  # RF voltage [V]
        phi_1 = [np.pi + 1., np.pi / 6 + 2.]  # Phase modulation/offset
        phi_2 = [1., np.pi / 6 + 2.]  # Phase modulation/offset
        N_t = 43857

        # Defining classes ----------------------------------------------------
        # Define general parameters
        if (negativeEta == True):

            if acceleration == True:
                # eta < 0, acceleration
                general_params = Ring(C, alpha_1,
                                      np.linspace(p_1i, p_1f, N_t + 1),
                                      Proton(), N_t)
            elif acceleration == False:
                # eta < 0, deceleration
                general_params = Ring(C, alpha_1,
                                      np.linspace(p_1f, p_1i, N_t + 1),
                                      Proton(), N_t)

            if singleRF == True:
                rf_params = RFStation(general_params,
                                      9,
                                      1.8e6,
                                      np.pi + 1.,
                                      n_rf=1)
            elif singleRF == False:
                rf_params = RFStation(general_params, h, V, phi_1, n_rf=2)
                rf_params.phi_s = calculate_phi_s(
                    rf_params,
                    Particle=general_params.Particle,
                    accelerating_systems='all')

        elif (negativeEta == False):

            if acceleration == True:
                # eta > 0, acceleration
                general_params = Ring(C, alpha_2,
                                      np.linspace(p_2i, p_2f, N_t + 1),
                                      Proton(), N_t)
            elif acceleration == False:
                # eta > 0, deceleration
                general_params = Ring(C, alpha_2,
                                      np.linspace(p_2f, p_2i, N_t + 1),
                                      Proton(), N_t)

            if singleRF == True:
                rf_params = RFStation(general_params, 9, 1.8e6, 1., n_rf=1)
            elif singleRF == False:
                rf_params = RFStation(general_params, h, V, phi_2, n_rf=2)
                rf_params.phi_s = calculate_phi_s(
                    rf_params,
                    Particle=general_params.Particle,
                    accelerating_systems='all')

        # Define beam and distribution
        beam = Beam(general_params, N_p, N_b)
        bigaussian(general_params, rf_params, beam, tau_0 / 4, seed=1234)
        #print(np.mean(beam.dt))
        slices = Profile(
            beam, CutOptions(cut_left=0.e-9, cut_right=600.e-9, n_slices=1000))
        slices.track()
        configuration = {
            'machine': 'LHC',
            'PL_gain': 0.1 * general_params.t_rev[0]
        }
        PL = BeamFeedback(general_params, rf_params, slices, configuration)
        PL.beam_phase()

        # Quantities to be compared
        self.phi_s = rf_params.phi_s[0]
        self.phi_b = PL.phi_beam
        self.phi_rf = rf_params.phi_rf[0, 0]
        self.dE_sep = separatrix(general_params, rf_params,
                                 [-5.e-7, -3.e-7, 1.e-7, 3.e-7, 7.e-7, 9.e-7])
예제 #13
0
    def test_3(self):

        # Set up SPS conditions
        ring = Ring(2 * np.pi * 1100.009, 1 / 18**2, 25.92e9, Proton(), 1000)
        RF = RFStation(ring, 4620, 4.5e6, 0)
        beam = Beam(ring, 1e5, 1e11)
        bigaussian(ring, RF, beam, 3.2e-9 / 4, seed=1234, reinsertion=True)
        profile = Profile(
            beam, CutOptions(cut_left=-1.e-9, cut_right=6.e-9, n_slices=100))
        profile.track()
        self.assertEqual(
            len(beam.dt), np.sum(profile.n_macroparticles), "In" +
            " TestBeamCurrent: particle number mismatch in Beam vs Profile")

        # RF current calculation with low-pass filter
        rf_current = rf_beam_current(profile, 2 * np.pi * 200.222e6,
                                     ring.t_rev[0])
        Iref_real = np.array([
            -9.4646042539e-12, -7.9596801534e-10, -2.6993572787e-10,
            2.3790828610e-09, 6.4007063190e-09, 9.5444302650e-09,
            9.6957462918e-09, 6.9944771120e-09, 5.0040512366e-09,
            8.2427583408e-09, 1.6487066238e-08, 2.2178930587e-08,
            1.6497620890e-08, 1.9878201568e-09, -2.4862807497e-09,
            2.0862096916e-08, 6.6115473293e-08, 1.1218114710e-07,
            1.5428441607e-07, 2.1264254596e-07, 3.1213935713e-07,
            4.6339212948e-07, 6.5039440158e-07, 8.2602190806e-07,
            9.4532001396e-07, 1.0161170159e-06, 1.0795840334e-06,
            1.1306004256e-06, 1.1081141333e-06, 9.7040873320e-07,
            7.1863437325e-07, 3.3833950889e-07, -2.2273124358e-07,
            -1.0035204008e-06, -1.9962696992e-06, -3.1751183137e-06,
            -4.5326227784e-06, -6.0940850385e-06, -7.9138578879e-06,
            -9.9867317826e-06, -1.2114906338e-05, -1.4055138779e-05,
            -1.5925650405e-05, -1.8096693885e-05, -2.0418813156e-05,
            -2.2142865862e-05, -2.3038234657e-05, -2.3822481250e-05,
            -2.4891969829e-05, -2.5543384520e-05, -2.5196086909e-05,
            -2.4415522211e-05, -2.3869116251e-05, -2.3182951665e-05,
            -2.1723128723e-05, -1.9724625363e-05, -1.7805112266e-05,
            -1.5981218737e-05, -1.3906226012e-05, -1.1635865568e-05,
            -9.5381189596e-06, -7.7236624815e-06, -6.0416822483e-06,
            -4.4575806261e-06, -3.0779237834e-06, -1.9274519396e-06,
            -9.5699993457e-07, -1.7840768971e-07, 3.7780452612e-07,
            7.5625231388e-07, 1.0158886027e-06, 1.1538975409e-06,
            1.1677937652e-06, 1.1105424636e-06, 1.0216131672e-06,
            8.8605026541e-07, 7.0783694846e-07, 5.4147914020e-07,
            4.1956457226e-07, 3.2130062098e-07, 2.2762751268e-07,
            1.4923020411e-07, 9.5683463322e-08, 5.8942895620e-08,
            3.0515695233e-08, 1.2444834300e-08, 8.9413517889e-09,
            1.6154761941e-08, 2.3261993674e-08, 2.3057968490e-08,
            1.8354179928e-08, 1.4938991667e-08, 1.2506841004e-08,
            8.1230022648e-09, 3.7428821201e-09, 2.8368110506e-09,
            3.6536247240e-09, 2.8429736524e-09, 1.6640835314e-09,
            2.3960087967e-09
        ])
        I_real = np.around(rf_current.real, 9)  # round
        Iref_real = np.around(Iref_real, 9)
        self.assertSequenceEqual(
            I_real.tolist(),
            Iref_real.tolist(),
            msg="In TestRFCurrent test_3, mismatch in real part of RF current")
        Iref_imag = np.array([
            -1.3134886055e-11, 1.0898262206e-09, 3.9806900984e-10,
            -3.0007980073e-09, -7.4404909183e-09, -9.5619658077e-09,
            -7.9029982105e-09, -4.5153699012e-09, -2.8337010673e-09,
            -4.0605999910e-09, -5.7035811935e-09, -4.9421561822e-09,
            -2.6226262365e-09, -1.0904425703e-09, 1.5886725829e-10,
            3.6061564044e-09, 1.2213233410e-08, 3.0717134774e-08,
            6.2263860975e-08, 1.0789908935e-07, 1.8547368321e-07,
            3.3758410599e-07, 5.8319210090e-07, 8.7586115583e-07,
            1.1744525681e-06, 1.5330067491e-06, 2.0257108185e-06,
            2.6290348930e-06, 3.3065045701e-06, 4.1218136471e-06,
            5.1059358251e-06, 6.1421308306e-06, 7.1521192647e-06,
            8.2164613957e-06, 9.3474086978e-06, 1.0368027059e-05,
            1.1176114701e-05, 1.1892303251e-05, 1.2600522466e-05,
            1.3142991032e-05, 1.3286611961e-05, 1.2972067098e-05,
            1.2344251145e-05, 1.1561930031e-05, 1.0577353622e-05,
            9.1838382917e-06, 7.3302333455e-06, 5.2367297732e-06,
            3.1309520147e-06, 1.0396785645e-06, -1.1104442284e-06,
            -3.3300486963e-06, -5.5129705406e-06, -7.4742790081e-06,
            -9.1003715719e-06, -1.0458342224e-05, -1.1632423668e-05,
            -1.2513736332e-05, -1.2942309414e-05, -1.2975831165e-05,
            -1.2799952495e-05, -1.2469945465e-05, -1.1941176358e-05,
            -1.1222986380e-05, -1.0349594257e-05, -9.3491445482e-06,
            -8.2956327726e-06, -7.2394219079e-06, -6.1539590898e-06,
            -5.0802321519e-06, -4.1512021086e-06, -3.3868884793e-06,
            -2.6850344653e-06, -2.0327038471e-06, -1.5048854341e-06,
            -1.0965986189e-06, -7.4914749272e-07, -4.7128817088e-07,
            -2.9595396024e-07, -1.9387567373e-07, -1.1597751838e-07,
            -5.5766761837e-08, -2.3991059778e-08, -1.1910924971e-08,
            -4.7797889603e-09, 9.0715301612e-11, 1.5744084129e-09,
            2.8217939283e-09, 5.5919203984e-09, 7.7259433940e-09,
            8.5033504655e-09, 9.1509256107e-09, 8.6746085156e-09,
            5.8909590412e-09, 3.5957212556e-09, 4.3347189168e-09,
            5.3331969589e-09, 3.9322184713e-09, 3.3616434953e-09,
            6.5154351819e-09
        ])
        I_imag = np.around(rf_current.imag, 9)  # round
        Iref_imag = np.around(Iref_imag, 9)
        self.assertSequenceEqual(
            I_imag.tolist(),
            Iref_imag.tolist(),
            msg=
            "In TestRFCurrent test_3, mismatch in imaginary part of RF current"
        )
예제 #14
0
class TestRFCurrent(unittest.TestCase):
    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 test_1(self):

        t = self.profile.bin_centers
        self.profile.n_macroparticles \
            = 2600*np.exp(-(t-2.5e-9)**2 / (2*0.5e-9)**2)

        rf_current = rf_beam_current(self.profile,
                                     self.omega,
                                     self.ring.t_rev[0],
                                     lpf=False)

        rf_current_real = np.around(rf_current.real, 12)
        rf_current_imag = np.around(rf_current.imag, 12)

        rf_theo_real = 2*self.beam.ratio*self.profile.Beam.Particle.charge*e\
            * 2600*np.exp(-(t-2.5e-9)**2/(2*0.5*1e-9)**2)\
            * np.cos(self.omega*t)
        rf_theo_real = np.around(rf_theo_real, 12)

        rf_theo_imag = 2*self.beam.ratio*self.profile.Beam.Particle.charge*e\
            * 2600*np.exp(-(t-2.5e-9)**2/(2*0.5*1e-9)**2)\
            * np.sin(self.omega*t)
        rf_theo_imag = np.around(rf_theo_imag, 12)

        self.assertListEqual(
            rf_current_real.tolist(),
            rf_theo_real.tolist(),
            msg="In TestRfCurrent test_1, mismatch in real part of RF current")
        self.assertListEqual(
            rf_current_imag.tolist(),
            rf_theo_imag.tolist(),
            msg="In TestRfCurrent test_1, mismatch in real part of RF current")

    def test_2(self):

        RF = RFStation(self.ring, 4620, 4.5e6, 0)

        bigaussian(self.ring,
                   RF,
                   self.beam,
                   3.2e-9 / 4,
                   seed=1234,
                   reinsertion=True)
        self.profile.track()

        rf_current = rf_beam_current(self.profile,
                                     self.omega,
                                     self.ring.t_rev[0],
                                     lpf=False)

        Iref_real = np.array([
            0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
            4.17276535e-13, 4.58438681e-13, 2.48023976e-13, 5.29812878e-13,
            2.79735891e-13, 0.00000000e+00, 1.21117141e-12, 9.32525023e-13,
            3.16481489e-13, 6.39337176e-13, 0.00000000e+00, 0.00000000e+00,
            4.08671434e-12, 4.92294314e-12, 6.56965575e-12, 1.06279981e-11,
            1.36819774e-11, 2.16648778e-11, 3.09847740e-11, 3.52971849e-11,
            4.70378842e-11, 4.53538351e-11, 4.87255679e-11, 5.36705228e-11,
            5.13609263e-11, 4.32833543e-11, 3.41417624e-11, 1.57452091e-11,
            -1.09005668e-11, -4.60465929e-11, -9.12872553e-11, -1.48257171e-10,
            -2.08540597e-10, -2.77630608e-10, -3.72157667e-10, -4.56272786e-10,
            -5.57978710e-10, -6.46554672e-10, -7.48006839e-10, -8.21493943e-10,
            -9.37522966e-10, -1.03729659e-09, -1.06159943e-09, -1.08434837e-09,
            -1.15738771e-09, -1.17887328e-09, -1.17146946e-09, -1.10964397e-09,
            -1.10234198e-09, -1.08852433e-09, -9.85866185e-10, -9.11727492e-10,
            -8.25604179e-10, -7.34122902e-10, -6.47294094e-10, -5.30372699e-10,
            -4.40357820e-10, -3.61273445e-10, -2.76871612e-10, -2.02227691e-10,
            -1.45430219e-10, -8.88675652e-11, -4.28984525e-11, -8.85451321e-12,
            1.79026289e-11, 3.48384211e-11, 4.50190278e-11, 5.62413467e-11,
            5.27322593e-11, 4.98163111e-11, 4.83288193e-11, 4.18200848e-11,
            3.13334266e-11, 2.44082106e-11, 2.12572803e-11, 1.37397871e-11,
            1.00879346e-11, 7.78502206e-12, 4.00790815e-12, 2.51830412e-12,
            1.91301488e-12, 0.00000000e+00, 9.58518921e-13, 3.16123806e-13,
            1.24116545e-12, 1.20821671e-12, 5.82952178e-13, 8.35917228e-13,
            5.27285250e-13, 4.93205915e-13, 0.00000000e+00, 2.06937011e-13,
            1.84618141e-13, 1.60868490e-13, 0.00000000e+00, 1.09822742e-13
        ])

        I_real = np.around(rf_current.real, 14)  # round
        Iref_real = np.around(Iref_real, 14)

        self.assertSequenceEqual(
            I_real.tolist(),
            Iref_real.tolist(),
            msg="In TestRFCurrent test_2, mismatch in real part of RF current")

        Iref_imag = np.array([
            0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
            -4.86410815e-13, -4.47827158e-13, -2.02886432e-13, -3.60573852e-13,
            -1.56290206e-13, 0.00000000e+00, -4.19433613e-13, -2.33465744e-13,
            -5.01823105e-14, -4.43075921e-14, 0.00000000e+00, 0.00000000e+00,
            8.07144709e-13, 1.43192280e-12, 2.55659168e-12, 5.25480064e-12,
            8.33669524e-12, 1.59729353e-11, 2.73609511e-11, 3.71844853e-11,
            5.92134758e-11, 6.87376280e-11, 9.02226570e-11, 1.24465616e-10,
            1.55478762e-10, 1.84035433e-10, 2.37241518e-10, 2.86677989e-10,
            3.28265272e-10, 3.77882012e-10, 4.29727720e-10, 4.83759029e-10,
            5.13978173e-10, 5.41841031e-10, 5.91537968e-10, 6.00658643e-10,
            6.13928028e-10, 5.96367636e-10, 5.76920099e-10, 5.25297875e-10,
            4.89104065e-10, 4.29776324e-10, 3.33901906e-10, 2.38690921e-10,
            1.49673305e-10, 4.78223853e-11, -5.57081558e-11, -1.51374774e-10,
            -2.50724894e-10, -3.50731761e-10, -4.16547058e-10, -4.83765618e-10,
            -5.36075032e-10, -5.74421794e-10, -6.05459147e-10, -5.91794283e-10,
            -5.88179055e-10, -5.83222843e-10, -5.49774151e-10, -5.08571646e-10,
            -4.86623358e-10, -4.33179012e-10, -3.73737133e-10, -3.37622742e-10,
            -2.89119788e-10, -2.30660798e-10, -1.85597518e-10, -1.66348322e-10,
            -1.19981335e-10, -9.07232680e-11, -7.21467862e-11, -5.18977454e-11,
            -3.25510912e-11, -2.12524272e-11, -1.54447488e-11, -8.24107056e-12,
            -4.90052047e-12, -2.96720377e-12, -1.13551262e-12, -4.79152734e-13,
            -1.91861296e-13, 0.00000000e+00, 7.31481456e-14, 5.23883203e-14,
            3.19951675e-13, 4.27870459e-13, 2.66236636e-13, 4.74712082e-13,
            3.64260145e-13, 4.09222572e-13, 0.00000000e+00, 2.44654594e-13,
            2.61906356e-13, 2.77128356e-13, 0.00000000e+00, 3.01027843e-13
        ])

        I_imag = np.around(rf_current.imag, 14)  # round
        Iref_imag = np.around(Iref_imag, 14)

        self.assertSequenceEqual(
            I_imag.tolist(),
            Iref_imag.tolist(),
            msg="In TestRFCurrent test_2, mismatch in imaginary part of" +
            " RF current")

    # Skip this unit test, since its reference values are obsolete;
    # This test used to be in /unittests/general/test_cavity_feedback.py
    @unittest.skip('Skipping because of obsolete reference values!')
    def test_3(self):

        # Set up SPS conditions
        ring = Ring(2 * np.pi * 1100.009, 1 / 18**2, 25.92e9, Proton(), 1000)
        RF = RFStation(ring, 4620, 4.5e6, 0)
        beam = Beam(ring, 1e5, 1e11)
        bigaussian(ring, RF, beam, 3.2e-9 / 4, seed=1234, reinsertion=True)
        profile = Profile(
            beam, CutOptions(cut_left=-1.e-9, cut_right=6.e-9, n_slices=100))
        profile.track()
        self.assertEqual(
            len(beam.dt), np.sum(profile.n_macroparticles), "In" +
            " TestBeamCurrent: particle number mismatch in Beam vs Profile")

        # RF current calculation with low-pass filter
        rf_current = rf_beam_current(profile, 2 * np.pi * 200.222e6,
                                     ring.t_rev[0])
        Iref_real = np.array([
            -9.4646042539e-12, -7.9596801534e-10, -2.6993572787e-10,
            2.3790828610e-09, 6.4007063190e-09, 9.5444302650e-09,
            9.6957462918e-09, 6.9944771120e-09, 5.0040512366e-09,
            8.2427583408e-09, 1.6487066238e-08, 2.2178930587e-08,
            1.6497620890e-08, 1.9878201568e-09, -2.4862807497e-09,
            2.0862096916e-08, 6.6115473293e-08, 1.1218114710e-07,
            1.5428441607e-07, 2.1264254596e-07, 3.1213935713e-07,
            4.6339212948e-07, 6.5039440158e-07, 8.2602190806e-07,
            9.4532001396e-07, 1.0161170159e-06, 1.0795840334e-06,
            1.1306004256e-06, 1.1081141333e-06, 9.7040873320e-07,
            7.1863437325e-07, 3.3833950889e-07, -2.2273124358e-07,
            -1.0035204008e-06, -1.9962696992e-06, -3.1751183137e-06,
            -4.5326227784e-06, -6.0940850385e-06, -7.9138578879e-06,
            -9.9867317826e-06, -1.2114906338e-05, -1.4055138779e-05,
            -1.5925650405e-05, -1.8096693885e-05, -2.0418813156e-05,
            -2.2142865862e-05, -2.3038234657e-05, -2.3822481250e-05,
            -2.4891969829e-05, -2.5543384520e-05, -2.5196086909e-05,
            -2.4415522211e-05, -2.3869116251e-05, -2.3182951665e-05,
            -2.1723128723e-05, -1.9724625363e-05, -1.7805112266e-05,
            -1.5981218737e-05, -1.3906226012e-05, -1.1635865568e-05,
            -9.5381189596e-06, -7.7236624815e-06, -6.0416822483e-06,
            -4.4575806261e-06, -3.0779237834e-06, -1.9274519396e-06,
            -9.5699993457e-07, -1.7840768971e-07, 3.7780452612e-07,
            7.5625231388e-07, 1.0158886027e-06, 1.1538975409e-06,
            1.1677937652e-06, 1.1105424636e-06, 1.0216131672e-06,
            8.8605026541e-07, 7.0783694846e-07, 5.4147914020e-07,
            4.1956457226e-07, 3.2130062098e-07, 2.2762751268e-07,
            1.4923020411e-07, 9.5683463322e-08, 5.8942895620e-08,
            3.0515695233e-08, 1.2444834300e-08, 8.9413517889e-09,
            1.6154761941e-08, 2.3261993674e-08, 2.3057968490e-08,
            1.8354179928e-08, 1.4938991667e-08, 1.2506841004e-08,
            8.1230022648e-09, 3.7428821201e-09, 2.8368110506e-09,
            3.6536247240e-09, 2.8429736524e-09, 1.6640835314e-09,
            2.3960087967e-09
        ])
        I_real = np.around(rf_current.real, 9)  # round
        Iref_real = np.around(Iref_real, 9)
        self.assertSequenceEqual(
            I_real.tolist(),
            Iref_real.tolist(),
            msg="In TestRFCurrent test_3, mismatch in real part of RF current")
        Iref_imag = np.array([
            -1.3134886055e-11, 1.0898262206e-09, 3.9806900984e-10,
            -3.0007980073e-09, -7.4404909183e-09, -9.5619658077e-09,
            -7.9029982105e-09, -4.5153699012e-09, -2.8337010673e-09,
            -4.0605999910e-09, -5.7035811935e-09, -4.9421561822e-09,
            -2.6226262365e-09, -1.0904425703e-09, 1.5886725829e-10,
            3.6061564044e-09, 1.2213233410e-08, 3.0717134774e-08,
            6.2263860975e-08, 1.0789908935e-07, 1.8547368321e-07,
            3.3758410599e-07, 5.8319210090e-07, 8.7586115583e-07,
            1.1744525681e-06, 1.5330067491e-06, 2.0257108185e-06,
            2.6290348930e-06, 3.3065045701e-06, 4.1218136471e-06,
            5.1059358251e-06, 6.1421308306e-06, 7.1521192647e-06,
            8.2164613957e-06, 9.3474086978e-06, 1.0368027059e-05,
            1.1176114701e-05, 1.1892303251e-05, 1.2600522466e-05,
            1.3142991032e-05, 1.3286611961e-05, 1.2972067098e-05,
            1.2344251145e-05, 1.1561930031e-05, 1.0577353622e-05,
            9.1838382917e-06, 7.3302333455e-06, 5.2367297732e-06,
            3.1309520147e-06, 1.0396785645e-06, -1.1104442284e-06,
            -3.3300486963e-06, -5.5129705406e-06, -7.4742790081e-06,
            -9.1003715719e-06, -1.0458342224e-05, -1.1632423668e-05,
            -1.2513736332e-05, -1.2942309414e-05, -1.2975831165e-05,
            -1.2799952495e-05, -1.2469945465e-05, -1.1941176358e-05,
            -1.1222986380e-05, -1.0349594257e-05, -9.3491445482e-06,
            -8.2956327726e-06, -7.2394219079e-06, -6.1539590898e-06,
            -5.0802321519e-06, -4.1512021086e-06, -3.3868884793e-06,
            -2.6850344653e-06, -2.0327038471e-06, -1.5048854341e-06,
            -1.0965986189e-06, -7.4914749272e-07, -4.7128817088e-07,
            -2.9595396024e-07, -1.9387567373e-07, -1.1597751838e-07,
            -5.5766761837e-08, -2.3991059778e-08, -1.1910924971e-08,
            -4.7797889603e-09, 9.0715301612e-11, 1.5744084129e-09,
            2.8217939283e-09, 5.5919203984e-09, 7.7259433940e-09,
            8.5033504655e-09, 9.1509256107e-09, 8.6746085156e-09,
            5.8909590412e-09, 3.5957212556e-09, 4.3347189168e-09,
            5.3331969589e-09, 3.9322184713e-09, 3.3616434953e-09,
            6.5154351819e-09
        ])
        I_imag = np.around(rf_current.imag, 9)  # round
        Iref_imag = np.around(Iref_imag, 9)
        self.assertSequenceEqual(
            I_imag.tolist(),
            Iref_imag.tolist(),
            msg=
            "In TestRFCurrent test_3, mismatch in imaginary part of RF current"
        )
예제 #15
0
class testProfileClass(unittest.TestCase):

    # Run before every test
    def setUp(self):
        """
        Slicing of the same Gaussian profile using four distinct settings to
        test different features.
        """

        np.random.seed(1984)

        intensity_pb = 1.0e11
        sigma = 0.2e-9  # Gauss sigma, [s]

        n_macroparticles_pb = int(1e4)
        n_bunches = 2

        # --- Ring and RF ----------------------------------------------
        intensity = n_bunches * intensity_pb  # total intensity SPS
        n_turns = 1
        # Ring parameters SPS
        circumference = 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

        ring = Ring(circumference,
                    momentum_compaction,
                    sync_momentum,
                    Proton(),
                    n_turns=n_turns)

        # RF parameters SPS
        harmonic_number = 4620  # harmonic number
        voltage = 3.5e6  # [V]
        phi_offsets = 0

        self.rf_station = RFStation(ring,
                                    harmonic_number,
                                    voltage,
                                    phi_offsets,
                                    n_rf=1)
        t_rf = self.rf_station.t_rf[0, 0]

        bunch_spacing = 5  # RF buckets

        n_macroparticles = n_bunches * n_macroparticles_pb
        self.beam = Beam(ring, n_macroparticles, intensity)

        for bunch in range(n_bunches):

            bunchBeam = Beam(ring, n_macroparticles_pb, intensity_pb)
            bigaussian(ring,
                       self.rf_station,
                       bunchBeam,
                       sigma,
                       reinsertion=True,
                       seed=1984 + bunch)

            self.beam.dt[bunch*n_macroparticles_pb : (bunch+1)*n_macroparticles_pb] \
                = bunchBeam.dt + bunch*bunch_spacing * t_rf
            self.beam.dE[bunch * n_macroparticles_pb:(bunch + 1) *
                         n_macroparticles_pb] = bunchBeam.dE

        self.filling_pattern = np.zeros(bunch_spacing * (n_bunches - 1) + 1)
        self.filling_pattern[::bunch_spacing] = 1

        # uniform profile

        profile_margin = 0 * t_rf

        t_batch_begin = 0 * t_rf
        t_batch_end = (bunch_spacing * (n_bunches - 1) + 1) * t_rf

        self.n_slices_rf = 32  # number of slices per RF-bucket

        cut_left = t_batch_begin - profile_margin
        cut_right = t_batch_end + profile_margin

        # number of rf-buckets of the self.beam
        # + rf-buckets before the self.beam + rf-buckets after the self.beam
        n_slices = self.n_slices_rf * (
            bunch_spacing * (n_bunches - 1) + 1 +
            int(np.round((t_batch_begin - cut_left) / t_rf)) +
            int(np.round((cut_right - t_batch_end) / t_rf)))

        self.uniform_profile = Profile(self.beam,
                                       CutOptions=CutOptions(
                                           cut_left=cut_left,
                                           n_slices=n_slices,
                                           cut_right=cut_right))
        self.uniform_profile.track()

    def test_WrongTrackingFunction(self):
        with self.assertRaises(RuntimeError):
            SparseSlices(self.rf_station,
                         self.beam,
                         self.n_slices_rf,
                         self.filling_pattern,
                         tracker='something horribly wrong')

        nonuniform_profile = SparseSlices(self.rf_station, self.beam,
                                          self.n_slices_rf,
                                          self.filling_pattern)

        self.assertEqual(nonuniform_profile.bin_centers_array.shape,
                         (2, self.n_slices_rf),
                         msg='Wrong shape of bin_centers_array!')

    def test_onebyone(self):
        rtol = 1e-6  # relative tolerance
        atol = 0  # absolute tolerance

        nonuniform_profile = SparseSlices(self.rf_station,
                                          self.beam,
                                          self.n_slices_rf,
                                          self.filling_pattern,
                                          tracker='onebyone',
                                          direct_slicing=True)

        for bunch in range(2):
            indexes = (self.uniform_profile.bin_centers>nonuniform_profile.cut_left_array[bunch])\
                * (self.uniform_profile.bin_centers<nonuniform_profile.cut_right_array[bunch])

            np.testing.assert_allclose(
                self.uniform_profile.bin_centers[indexes],
                nonuniform_profile.bin_centers_array[bunch],
                rtol=rtol,
                atol=atol,
                err_msg=f'Bins for bunch {bunch} do not agree ' +
                'for tracker="onebyone"')

            np.testing.assert_allclose(
                self.uniform_profile.n_macroparticles[indexes],
                nonuniform_profile.n_macroparticles_array[bunch],
                rtol=rtol,
                atol=atol,
                err_msg=f'Profiles for bunch {bunch} do not agree ' +
                'for tracker="onebyone"')

    def test_Ctracker(self):
        rtol = 1e-6  # relative tolerance
        atol = 0  # absolute tolerance

        nonuniform_profile = SparseSlices(self.rf_station,
                                          self.beam,
                                          self.n_slices_rf,
                                          self.filling_pattern,
                                          tracker='C',
                                          direct_slicing=True)

        for bunch in range(2):
            indexes = (self.uniform_profile.bin_centers>nonuniform_profile.cut_left_array[bunch])\
                * (self.uniform_profile.bin_centers<nonuniform_profile.cut_right_array[bunch])

            np.testing.assert_allclose(
                self.uniform_profile.bin_centers[indexes],
                nonuniform_profile.bin_centers_array[bunch],
                rtol=rtol,
                atol=atol,
                err_msg=f'Bins for bunch {bunch} do not agree ' +
                'for tracker="C"')

            np.testing.assert_allclose(
                self.uniform_profile.n_macroparticles[indexes],
                nonuniform_profile.n_macroparticles_array[bunch],
                rtol=rtol,
                atol=atol,
                err_msg=f'Profiles for bunch {bunch} do not agree ' +
                'for tracker="C"')
예제 #16
0
    def test_vind(self):

        # randomly chose omega_c from allowed range
        np.random.seed(1980)
        factor = np.random.uniform(0.9, 1.1)

        # round results to this digits
        digit_round = 8

        # SPS parameters
        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
        V = 4.5e6                   # 200 MHz RF voltage
        phi = 0.                    # 200 MHz RF phase

        # Beam and tracking parameters
        N_m = 1e5                   # Number of macro-particles for tracking
        N_b = 1.0e11                 # Bunch intensity [ppb]
        N_t = 1                  # Number of turns to track

        ring = Ring(C, alpha, p_s, Proton(), n_turns=N_t)
        rf = RFStation(ring, h, V, phi)
        beam = Beam(ring, N_m, N_b)
        bigaussian(ring, rf, beam, 3.2e-9/4, seed=1234, reinsertion=True)

        n_shift = 5     # how many rf-buckets to shift beam
        beam.dt += n_shift * rf.t_rf[0,0]
        profile = Profile(beam, CutOptions=
                          CutOptions(cut_left=(n_shift-1.5)*rf.t_rf[0,0],
                                     cut_right=(n_shift+1.5)*rf.t_rf[0,0],
                                     n_slices=140))
        profile.track()

        l_cav = 16.082
        v_g = 0.0946
        tau = l_cav/(v_g*c)*(1 + v_g)
        TWC_impedance_source = TravelingWaveCavity(l_cav**2 * 27.1e3 / 8,
                                                   200.222e6, 2*np.pi*tau)

        # Beam loading by convolution of beam and wake from cavity
        inducedVoltageTWC = InducedVoltageTime(beam, profile,
                                               [TWC_impedance_source])
        induced_voltage = TotalInducedVoltage(beam, profile,
                                              [inducedVoltageTWC])
        induced_voltage.induced_voltage_sum()
        V_ind_impSource = np.around(induced_voltage.induced_voltage,
                                    digit_round)

        # Beam loading via feed-back system
        OTFB_4 = SPSOneTurnFeedback(rf, beam, profile, 4, n_cavities=1)
        OTFB_4.counter = 0  # First turn

        OTFB_4.omega_c = factor * OTFB_4.TWC.omega_r
        # Compute impulse response
        OTFB_4.TWC.impulse_response_beam(OTFB_4.omega_c, profile.bin_centers)

        # Compute induced voltage in (I,Q) coordinates
        OTFB_4.beam_induced_voltage(lpf=False)
        # convert back to time
        V_ind_OTFB \
            = OTFB_4.V_fine_ind_beam.real \
                * np.cos(OTFB_4.omega_c*profile.bin_centers) \
            + OTFB_4.V_fine_ind_beam.imag \
                * np.sin(OTFB_4.omega_c*profile.bin_centers)
        V_ind_OTFB = np.around(V_ind_OTFB, digit_round)

        self.assertListEqual(V_ind_impSource.tolist(), V_ind_OTFB.tolist(),
            msg="In TravelingWaveCavity test_vind: induced voltages differ")
예제 #17
0
class TestRfVoltageCalc(unittest.TestCase):
    # Simulation parameters -------------------------------------------------------
    # Bunch parameters
    N_b = 1e9  # Intensity
    N_p = 50000  # Macro-particles
    tau_0 = 0.4e-9  # Initial bunch length, 4 sigma [s]
    # Machine and RF parameters
    C = 26658.883  # Machine circumference [m]
    p_i = 450e9  # Synchronous momentum [eV/c]
    p_f = 460.005e9  # Synchronous momentum, final
    h = 35640  # Harmonic number
    V = 6e6  # RF voltage [V]
    dphi = 0  # Phase modulation/offset
    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

    # Run before every test
    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)

    # Run after every test

    def tearDown(self):
        pass

    def test_rf_voltage_calc_1(self):
        self.long_tracker.rf_voltage_calculation()
        orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)

    def test_rf_voltage_calc_2(self):
        for i in range(100):
            self.long_tracker.rf_voltage_calculation()
            orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)

    def test_rf_voltage_calc_3(self):
        for i in range(100):
            self.profile.track()
            self.long_tracker.track()
            self.long_tracker.rf_voltage_calculation()
            orig_rf_voltage = orig_rf_volt_comp(self.long_tracker)
        np.testing.assert_almost_equal(self.long_tracker.rf_voltage,
                                       orig_rf_voltage,
                                       decimal=8)
예제 #18
0
                                BeamFeedback=phase_loop)

full_ring = FullRingAndRF([long_tracker])


distribution_type = 'gaussian'
bunch_length = 200.0e-9
distribution_variable = 'Action'

matched_from_distribution_function(my_beam, full_ring, 
                                   bunch_length=bunch_length,
                                   distribution_type=distribution_type, 
                                   distribution_variable=distribution_variable, seed=1222)
                                   
my_beam.dE += 90.0e3
slices_ring.track()

#Monitor
bunch_monitor = BunchMonitor(general_params, rf_params, my_beam,
                             this_directory + '../output_files/EX_08_output_data',
                             Profile=slices_ring, PhaseLoop=phase_loop)


#Plots
format_options = {'dirname': this_directory + '../output_files/EX_08_fig'}
plots = Plot(general_params, rf_params, my_beam, 50, n_turns, 0.0, 2*np.pi,
             -1e6, 1e6, xunit='rad', separatrix_plot=True, Profile=slices_ring,
             format_options=format_options,
             h5file=this_directory + '../output_files/EX_08_output_data', PhaseLoop=phase_loop)

# Accelerator map
예제 #19
0
    def test_beam_fine_coarse(self):

        # Test beam impulse response and induced voltage
        # Compare on coarse and fine grid

        # Create a batch of 100 equal, short bunches at HL-LHC intensity
        ring = Ring(2*np.pi*1100.009, 1/18**2, 25.92e9, Particle=Proton())
        rf = RFStation(ring, [4620], [4.5e6], [0], n_rf=1)
        bunches = 100
        N_m = int(1e5)
        N_b = 2.3e11
        beam = Beam(ring, N_m, N_b)
        bigaussian(ring, rf, beam, 1.8e-9/4, seed=1234, reinsertion=True)
        beam2 = Beam(ring, bunches*N_m, bunches*N_b)
        bunch_spacing = 5 * rf.t_rf[0, 0]
        buckets = 5 * bunches
        for i in range(bunches):
            beam2.dt[i * N_m:(i + 1) * N_m] = beam.dt + i * bunch_spacing
            beam2.dE[i * N_m:(i + 1) * N_m] = beam.dE
        profile2 = Profile(beam2, CutOptions=CutOptions(cut_left=0,
            cut_right=bunches*bunch_spacing,n_slices=1000*buckets))
        profile2.track()

        # Calculate impulse response and induced voltage
        OTFB = SPSOneTurnFeedback(rf, beam2, profile2, 3, n_cavities=1,
            Commissioning=CavityFeedbackCommissioning(open_FF=True))
        OTFB.TWC.impulse_response_beam(OTFB.omega_c, OTFB.profile.bin_centers,
                                       OTFB.rf_centers)
        OTFB.beam_induced_voltage(lpf=False)
        imp_fine_meas = (OTFB.TWC.h_beam[::1000])[:100]
        imp_coarse_meas = OTFB.TWC.h_beam_coarse[:100]

        imp_fine_ref = np.array([1.0504062083e+12+0.0000000000e+00j,
            2.0781004955e+12+2.7183115978e+09j,
            2.0553850965e+12+5.3772054987e+09j,
            2.0326663360e+12+7.9766773057e+09j,
            2.0099443306e+12+1.0516722825e+10j,
            1.9872191969e+12+1.2997338066e+10j,
            1.9644910516e+12+1.5418519242e+10j,
            1.9417600113e+12+1.7780262770e+10j,
            1.9190261924e+12+2.0082565269e+10j,
            1.8962897118e+12+2.2325423561e+10j,
            1.8735506859e+12+2.4508834674e+10j,
            1.8508092314e+12+2.6632795838e+10j,
            1.8280654649e+12+2.8697304485e+10j,
            1.8053195030e+12+3.0702358252e+10j,
            1.7825714624e+12+3.2647954978e+10j,
            1.7598214597e+12+3.4534092708e+10j,
            1.7370696115e+12+3.6360769688e+10j,
            1.7143160345e+12+3.8127984368e+10j,
            1.6915608452e+12+3.9835735402e+10j,
            1.6688041604e+12+4.1484021645e+10j,
            1.6460460966e+12+4.3072842159e+10j,
            1.6232867705e+12+4.4602196207e+10j,
            1.6005262987e+12+4.6072083256e+10j,
            1.5777647978e+12+4.7482502976e+10j,
            1.5550023845e+12+4.8833455241e+10j,
            1.5322391754e+12+5.0124940128e+10j,
            1.5094752871e+12+5.1356957918e+10j,
            1.4867108362e+12+5.2529509093e+10j,
            1.4639459395e+12+5.3642594342e+10j,
            1.4411807134e+12+5.4696214555e+10j,
            1.4184152746e+12+5.5690370826e+10j,
            1.3956497397e+12+5.6625064451e+10j,
            1.3728842254e+12+5.7500296932e+10j,
            1.3501188481e+12+5.8316069972e+10j,
            1.3273537246e+12+5.9072385477e+10j,
            1.3045889714e+12+5.9769245560e+10j,
            1.2818247051e+12+6.0406652532e+10j,
            1.2590610424e+12+6.0984608912e+10j,
            1.2362980996e+12+6.1503117419e+10j,
            1.2135359936e+12+6.1962180977e+10j,
            1.1907748407e+12+6.2361802713e+10j,
            1.1680147576e+12+6.2701985956e+10j,
            1.1452558608e+12+6.2982734240e+10j,
            1.1224982669e+12+6.3204051301e+10j,
            1.0997420924e+12+6.3365941080e+10j,
            1.0769874538e+12+6.3468407718e+10j,
            1.0542344676e+12+6.3511455561e+10j,
            1.0314832504e+12+6.3495089159e+10j,
            1.0087339187e+12+6.3419313265e+10j,
            9.8598658892e+11+6.3284132832e+10j,
            9.6324137757e+11+6.3089553021e+10j,
            9.4049840113e+11+6.2835579191e+10j,
            9.1775777605e+11+6.2522216909e+10j,
            8.9501961879e+11+6.2149471941e+10j,
            8.7228404579e+11+6.1717350259e+10j,
            8.4955117347e+11+6.1225858036e+10j,
            8.2682111826e+11+6.0675001648e+10j,
            8.0409399656e+11+6.0064787676e+10j,
            7.8136992476e+11+5.9395222903e+10j,
            7.5864901923e+11+5.8666314312e+10j,
            7.3593139635e+11+5.7878069094e+10j,
            7.1321717247e+11+5.7030494640e+10j,
            6.9050646392e+11+5.6123598543e+10j,
            6.6779938704e+11+5.5157388601e+10j,
            6.4509605813e+11+5.4131872814e+10j,
            6.2239659348e+11+5.3047059384e+10j,
            5.9970110939e+11+5.1902956716e+10j,
            5.7700972210e+11+5.0699573420e+10j,
            5.5432254788e+11+4.9436918305e+10j,
            5.3163970295e+11+4.8115000386e+10j,
            5.0896130353e+11+4.6733828878e+10j,
            4.8628746583e+11+4.5293413201e+10j,
            4.6361830601e+11+4.3793762975e+10j,
            4.4095394026e+11+4.2234888026e+10j,
            4.1829448472e+11+4.0616798379e+10j,
            3.9564005551e+11+3.8939504264e+10j,
            3.7299076875e+11+3.7203016111e+10j,
            3.5034674052e+11+3.5407344556e+10j,
            3.2770808692e+11+3.3552500435e+10j,
            3.0507492397e+11+3.1638494786e+10j,
            2.8244736773e+11+2.9665338851e+10j,
            2.5982553421e+11+2.7633044074e+10j,
            2.3720953939e+11+2.5541622099e+10j,
            2.1459949925e+11+2.3391084776e+10j,
            1.9199552975e+11+2.1181444154e+10j,
            1.6939774681e+11+1.8912712486e+10j,
            1.4680626634e+11+1.6584902227e+10j,
            1.2422120423e+11+1.4198026033e+10j,
            1.0164267634e+11+1.1752096764e+10j,
            7.9070798521e+10+9.2471274799e+09j,
            5.6505686581e+10+6.6831314440e+09j,
            3.3947456317e+10+4.0601221211e+09j,
            1.1396223503e+10+1.3781131781e+09j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j])

        imp_coarse_ref = np.array([1.0504062083e+12+0.0000000000e+00j,
            2.0781004955e+12+2.7183115978e+09j,
            2.0553850965e+12+5.3772054987e+09j,
            2.0326663360e+12+7.9766773057e+09j,
            2.0099443306e+12+1.0516722825e+10j,
            1.9872191969e+12+1.2997338066e+10j,
            1.9644910516e+12+1.5418519242e+10j,
            1.9417600113e+12+1.7780262770e+10j,
            1.9190261924e+12+2.0082565269e+10j,
            1.8962897118e+12+2.2325423561e+10j,
            1.8735506859e+12+2.4508834674e+10j,
            1.8508092314e+12+2.6632795838e+10j,
            1.8280654649e+12+2.8697304485e+10j,
            1.8053195030e+12+3.0702358252e+10j,
            1.7825714624e+12+3.2647954978e+10j,
            1.7598214597e+12+3.4534092708e+10j,
            1.7370696115e+12+3.6360769688e+10j,
            1.7143160345e+12+3.8127984368e+10j,
            1.6915608452e+12+3.9835735402e+10j,
            1.6688041604e+12+4.1484021645e+10j,
            1.6460460966e+12+4.3072842159e+10j,
            1.6232867705e+12+4.4602196207e+10j,
            1.6005262987e+12+4.6072083256e+10j,
            1.5777647978e+12+4.7482502976e+10j,
            1.5550023845e+12+4.8833455241e+10j,
            1.5322391754e+12+5.0124940128e+10j,
            1.5094752871e+12+5.1356957918e+10j,
            1.4867108362e+12+5.2529509093e+10j,
            1.4639459395e+12+5.3642594342e+10j,
            1.4411807134e+12+5.4696214555e+10j,
            1.4184152746e+12+5.5690370826e+10j,
            1.3956497397e+12+5.6625064451e+10j,
            1.3728842254e+12+5.7500296932e+10j,
            1.3501188481e+12+5.8316069972e+10j,
            1.3273537246e+12+5.9072385477e+10j,
            1.3045889714e+12+5.9769245560e+10j,
            1.2818247051e+12+6.0406652532e+10j,
            1.2590610424e+12+6.0984608912e+10j,
            1.2362980996e+12+6.1503117419e+10j,
            1.2135359936e+12+6.1962180977e+10j,
            1.1907748407e+12+6.2361802713e+10j,
            1.1680147576e+12+6.2701985956e+10j,
            1.1452558608e+12+6.2982734240e+10j,
            1.1224982669e+12+6.3204051301e+10j,
            1.0997420924e+12+6.3365941080e+10j,
            1.0769874538e+12+6.3468407718e+10j,
            1.0542344676e+12+6.3511455561e+10j,
            1.0314832504e+12+6.3495089159e+10j,
            1.0087339187e+12+6.3419313265e+10j,
            9.8598658892e+11+6.3284132832e+10j,
            9.6324137757e+11+6.3089553021e+10j,
            9.4049840113e+11+6.2835579191e+10j,
            9.1775777605e+11+6.2522216909e+10j,
            8.9501961879e+11+6.2149471941e+10j,
            8.7228404579e+11+6.1717350259e+10j,
            8.4955117347e+11+6.1225858036e+10j,
            8.2682111826e+11+6.0675001648e+10j,
            8.0409399656e+11+6.0064787676e+10j,
            7.8136992476e+11+5.9395222903e+10j,
            7.5864901923e+11+5.8666314312e+10j,
            7.3593139635e+11+5.7878069094e+10j,
            7.1321717247e+11+5.7030494640e+10j,
            6.9050646392e+11+5.6123598543e+10j,
            6.6779938704e+11+5.5157388601e+10j,
            6.4509605813e+11+5.4131872814e+10j,
            6.2239659348e+11+5.3047059384e+10j,
            5.9970110939e+11+5.1902956716e+10j,
            5.7700972210e+11+5.0699573420e+10j,
            5.5432254788e+11+4.9436918305e+10j,
            5.3163970295e+11+4.8115000386e+10j,
            5.0896130353e+11+4.6733828878e+10j,
            4.8628746583e+11+4.5293413201e+10j,
            4.6361830601e+11+4.3793762975e+10j,
            4.4095394026e+11+4.2234888026e+10j,
            4.1829448472e+11+4.0616798379e+10j,
            3.9564005551e+11+3.8939504264e+10j,
            3.7299076875e+11+3.7203016111e+10j,
            3.5034674052e+11+3.5407344556e+10j,
            3.2770808692e+11+3.3552500435e+10j,
            3.0507492397e+11+3.1638494786e+10j,
            2.8244736773e+11+2.9665338851e+10j,
            2.5982553421e+11+2.7633044074e+10j,
            2.3720953939e+11+2.5541622099e+10j,
            2.1459949925e+11+2.3391084776e+10j,
            1.9199552975e+11+2.1181444154e+10j,
            1.6939774681e+11+1.8912712486e+10j,
            1.4680626634e+11+1.6584902227e+10j,
            1.2422120423e+11+1.4198026033e+10j,
            1.0164267634e+11+1.1752096764e+10j,
            7.9070798521e+10+9.2471274799e+09j,
            5.6505686581e+10+6.6831314440e+09j,
            3.3947456317e+10+4.0601221211e+09j,
            1.1396223503e+10+1.3781131781e+09j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j,
            0.0000000000e+00+0.0000000000e+00j])

        np.testing.assert_allclose(imp_fine_meas[:-7], imp_fine_ref[:-7], rtol=1e-8,
            atol=0, err_msg="In TestTravelingWaveCavity test_beam_fine_coarse,"
                            "mismatch in beam impulse response on fine grid")
        np.testing.assert_allclose(imp_coarse_meas[:-7], imp_coarse_ref[:-7], rtol=1e-8,
            atol=0, err_msg="In TestTravelingWaveCavity test_beam_fine_coarse,"
                            "mismatch in beam impulse response on coarse grid")

        Vind_fine_meas = (OTFB.V_fine_ind_beam[::1000])[:100]
        Vind_coarse_meas = OTFB.V_coarse_ind_beam[:100]

        Vind_fine_ref = np.array([-3.0517578125e-11+2.0599365234e-10j,
            1.3119591242e+05+2.5059688582e+02j,
            1.2976951147e+05+4.1841300342e+02j,
            1.2834289840e+05+5.8249788025e+02j,
            1.2691608056e+05+7.4285125172e+02j,
            1.2548906524e+05+8.9947286604e+02j,
            2.5525777220e+05+1.3029593700e+03j,
            2.5240398296e+05+1.6199328833e+03j,
            2.4954980612e+05+1.9294427198e+03j,
            2.4669525631e+05+2.2314884143e+03j,
            2.4384034818e+05+2.5260695271e+03j,
            3.7218100878e+05+3.0637825296e+03j,
            3.6789902698e+05+3.5112493792e+03j,
            3.6361651869e+05+3.9475192402e+03j,
            3.5933350586e+05+4.3725915103e+03j,
            3.5505001047e+05+4.7864656258e+03j,
            4.8196196690e+05+5.4397379469e+03j,
            4.7625117134e+05+5.9990303323e+03j,
            4.7053974700e+05+6.5433918605e+03j,
            4.6482772318e+05+7.0728218563e+03j,
            4.5911512918e+05+7.5873196955e+03j,
            5.8459790670e+05+8.3374816909e+03j,
            5.7745785924e+05+8.9899296666e+03j,
            5.7031711736e+05+9.6237126791e+03j,
            5.6317571767e+05+1.0238830044e+04j,
            5.5603369679e+05+1.0835281141e+04j,
            6.8008700374e+05+1.1663662299e+04j,
            6.7151744935e+05+1.2390595370e+04j,
            6.6294717151e+05+1.3095129455e+04j,
            6.5437621413e+05+1.3777263922e+04j,
            6.4580462118e+05+1.4436998220e+04j,
            7.6842834898e+05+1.5324928756e+04j,
            7.5842921570e+05+1.6107677477e+04j,
            7.4842936654e+05+1.6864293588e+04j,
            7.3842885274e+05+1.7594776578e+04j,
            7.2842772557e+05+1.8299126023e+04j,
            8.4962194870e+05+1.9227938478e+04j,
            8.3819334760e+05+2.0047836046e+04j,
            8.2676407480e+05+2.0837868101e+04j,
            8.1533418885e+05+2.1598034313e+04j,
            8.0390374836e+05+2.2328334456e+04j,
            9.2366872430e+05+2.3279365291e+04j,
            9.1081094946e+05+2.4117749141e+04j,
            8.9795258369e+05+2.4922535614e+04j,
            8.8509369287e+05+2.5693724627e+04j,
            8.7223434290e+05+2.6431316212e+04j,
            9.9057051210e+05+2.7385907402e+04j,
            9.7628404055e+05+2.8224120805e+04j,
            9.6199709542e+05+2.9025006325e+04j,
            9.4770974992e+05+2.9788564189e+04j,
            9.3342207725e+05+3.0514794752e+04j,
            1.0503300630e+06+3.1454295383e+04j,
            1.0346155547e+06+3.2273689037e+04j,
            1.0189007267e+06+3.3052025980e+04j,
            1.0031856595e+06+3.3789306812e+04j,
            9.8747043377e+05+3.4485532275e+04j,
            1.1029510423e+06+3.5391300137e+04j,
            1.0858093399e+06+3.6173233764e+04j,
            1.0686675083e+06+3.6910383847e+04j,
            1.0515256353e+06+3.7602751424e+04j,
            1.0343838088e+06+3.8250337687e+04j,
            1.1484380290e+06+3.9103740866e+04j,
            1.1298701579e+06+3.9829584804e+04j,
            1.1113023846e+06+4.0506920680e+04j,
            1.0927348043e+06+4.1135750033e+04j,
            1.0741675120e+06+4.1716074567e+04j,
            1.1867965154e+06+4.2498493041e+04j,
            1.1668036837e+06+4.3149629836e+04j,
            1.1468112133e+06+4.3748536684e+04j,
            1.1268192067e+06+4.4295215687e+04j,
            1.1068277662e+06+4.4789669129e+04j,
            1.2180329068e+06+4.5482496357e+04j,
            1.1966165050e+06+4.6040322356e+04j,
            1.1752007645e+06+4.6542199472e+04j,
            1.1537857950e+06+4.6988130437e+04j,
            1.1323717063e+06+4.7378118176e+04j,
            1.2421545205e+06+4.7962762689e+04j,
            1.2193161215e+06+4.8408689628e+04j,
            1.1964787202e+06+4.8794952019e+04j,
            1.1736424337e+06+4.9121553285e+04j,
            1.1508073790e+06+4.9388497055e+04j,
            1.2591695854e+06+4.9846384046e+04j,
            1.2349109442e+06+5.0161840642e+04j,
            1.2106536737e+06+5.0413920610e+04j,
            1.1863978981e+06+5.0602628129e+04j,
            1.1621437417e+06+5.0727967597e+04j,
            1.2690872411e+06+5.1040540511e+04j,
            1.2434102950e+06+5.1206974048e+04j,
            1.2177351287e+06+5.1306322781e+04j,
            1.1920618739e+06+5.1338591709e+04j,
            1.1663906621e+06+5.1303786060e+04j,
            1.2719175372e+06+5.1452508178e+04j,
            1.2448244051e+06+5.1451386094e+04j,
            1.2177768552e+06+5.1349872757e+04j,
            1.1920618739e+06+5.1338591709e+04j,
            1.1663906621e+06+5.1303786060e+04j,
            1.2719175372e+06+5.1452508178e+04j,
            1.2448244051e+06+5.1451386094e+04j,
            1.2177768552e+06+5.1349872757e+04j,
            1.1920618739e+06+5.1338591709e+04j])

        Vind_coarse_ref = np.array([65950.402941899 +4.6204946754e+01j,
            130474.7043137922+2.6208172207e+02j,
            129048.3869868867+4.2802282083e+02j,
            127621.8612230706+5.9023291883e+02j,
            126195.13434267  +7.4871175790e+02j,
            190718.6166082232+9.4966403938e+02j,
            253815.81082876  +1.3165564125e+03j,
            250962.2071966935+1.6297811521e+03j,
            248108.2232953706+1.9355427270e+03j,
            245253.8737668068+2.2338406848e+03j,
            308349.5761954412+2.5708795450e+03j,
            370018.8407123919+3.0701257882e+03j,
            365737.1648323309+3.5119715333e+03j,
            361454.9734610094+3.9426211057e+03j,
            357172.2885629754+4.3620739225e+03j,
            418839.5350453047+4.8165343856e+03j,
            479080.2303618401+5.4294688706e+03j,
            473369.8793500392+5.9812694041e+03j,
            467658.9142384843+6.5181402322e+03j,
            461947.3643145755+7.0400807053e+03j,
            522185.6618082431+7.5932951716e+03j,
            580997.3314961634+8.3012499653e+03j,
            573857.8855385883+8.9443370849e+03j,
            566717.7634868335+9.5687607609e+03j,
            559577.0019509497+1.0174520341e+04j,
            618386.0404834162+1.0807820183e+04j,
            675768.4111833326+1.1592126644e+04j,
            667199.6335332314+1.2307831758e+04j,
            658630.1544065415+1.3001139804e+04j,
            650060.0177352416+1.3672050190e+04j,
            707439.6703935305+1.4366767349e+04j,
            763392.6518020012+1.5208757723e+04j,
            753394.4887644283+1.5978413447e+04j,
            743395.635475215 +1.6721938911e+04j,
            733396.1431870223+1.7439333649e+04j,
            789346.4660944196+1.8176802229e+04j,
            843870.1509380381+1.9057811247e+04j,
            832442.7318413376+1.9862752998e+04j,
            821014.6703180319+2.0637832050e+04j,
            809586.0249396971+2.1383048124e+04j,
            864107.2572194036+2.2144605992e+04j,
            917201.9212158447+2.3045972461e+04j,
            904345.5583700862+2.3867540055e+04j,
            891488.6375129672+2.4655513581e+04j,
            878631.2245326925+2.5409893014e+04j,
            931723.7882584379+2.6176883388e+04j,
            983389.8900644641+2.7079951792e+04j,
            969105.0787068398+2.7899491038e+04j,
            954819.8303308268+2.8681706237e+04j,
            940534.2181384464+2.9426597680e+04j,
            992198.7182720678+3.0180370731e+04j,
            1042436.8994184991+3.1066492820e+04j,
            1026724.3176456908+3.1865357114e+04j,
            1011011.4564100985+3.2623169090e+04j,
            995298.3962242305+3.3339929421e+04j,
            1045535.6205402148+3.4061843863e+04j,
            1094346.7053538668+3.4912380250e+04j,
            1077207.2140413758+3.5671932169e+04j,
            1060067.6373666434+3.6386705528e+04j,
            1042928.0631488134+3.7056701442e+04j,
            1091738.982145815 +3.7728126125e+04j,
            1139123.977658412 +3.8524447879e+04j,
            1120558.6203668672+3.9226060775e+04j,
            1101993.4083382622+3.9879171214e+04j,
            1083428.4366940013+4.0483780818e+04j,
            1130814.2034933397+4.1086096322e+04j,
            1176774.2993374085+4.1809586562e+04j,
            1156784.3022058595+4.2434646152e+04j,
            1136794.717464163 +4.3007482052e+04j,
            1116805.6475310936+4.3528096457e+04j,
            1162767.5977622345+4.4042696684e+04j,
            1207304.1660539836+4.4674752165e+04j,
            1185890.9376801767+4.5204658125e+04j,
            1164478.425299364 +4.5678622145e+04j,
            1143066.738622277 +4.6096647054e+04j,
            1187606.39029531  +4.6504940818e+04j,
            1230720.9855045064+4.7026973527e+04j,
            1207886.116812161 +4.7443141080e+04j,
            1185052.3041640767+4.7799651744e+04j,
            1162219.6645570078+4.8096509044e+04j,
            1205338.7179221238+4.8379921659e+04j,
            1247033.0767289733+4.8773360403e+04j,
            1222778.3408220657+4.9057221909e+04j,
            1198525.0374281076+4.9277715194e+04j,
            1174273.2908234247+4.9434844546e+04j,
            1215973.628217406 +4.9574819417e+04j,
            1256249.6693564458+4.9821111408e+04j,
            1230577.0213605044+4.9954117952e+04j,
            1204906.2187303253+5.0020048879e+04j,
            1179237.3930148352+5.0018909302e+04j,
            1219521.0786945666+4.9996909510e+04j,
            1258380.9027855818+5.0077521955e+04j,
            1231292.4796760113+5.0041144933e+04j,
            1204906.2187303249+5.0020048879e+04j,
            1179237.3930148345+5.0018909302e+04j,
            1219521.0786945664+4.9996909510e+04j,
            1258380.9027855818+5.0077521955e+04j,
            1231292.4796760113+5.0041144933e+04j,
            1204906.2187303246+5.0020048879e+04j,
            1179237.3930148345+5.0018909302e+04j])

        np.testing.assert_allclose(Vind_fine_meas, Vind_fine_ref, rtol=1e-8,
            atol=1e-9, err_msg="In TestTravelingWaveCavity test_beam_fine_coarse,"
                            "mismatch in beam-induced voltage on fine grid")
        np.testing.assert_allclose(Vind_coarse_meas, Vind_coarse_ref, rtol=1e-8,
            atol=0, err_msg="In TestTravelingWaveCavity test_beam_fine_coarse,"
                            "mismatch in beam-induced voltage on coarse grid")
class TestRFCurrent(unittest.TestCase):
    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)
        self.rf = RFStation(self.ring, 4620, 4.5e6, 0)

        # 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=-1e-9,
                                                     cut_right=6e-9,
                                                     n_slices=100))

    # Test charge distribution with analytic functions
    # Compare with theoretical value
    def test_1(self):

        t = self.profile.bin_centers
        self.profile.n_macroparticles \
            = 2600*np.exp(-(t-2.5e-9)**2 / (2*0.5e-9)**2)

        rf_current = rf_beam_current(self.profile,
                                     self.omega,
                                     self.ring.t_rev[0],
                                     lpf=False)

        rf_current_real = np.around(rf_current.real, 12)
        rf_current_imag = np.around(rf_current.imag, 12)

        rf_theo_real = 2*self.beam.ratio*self.profile.Beam.Particle.charge*e\
            * 2600*np.exp(-(t-2.5e-9)**2/(2*0.5*1e-9)**2)\
            * np.cos(self.omega*t)
        rf_theo_real = np.around(rf_theo_real, 12)

        rf_theo_imag = 2*self.beam.ratio*self.profile.Beam.Particle.charge*e\
            * 2600*np.exp(-(t-2.5e-9)**2/(2*0.5*1e-9)**2)\
            * np.sin(self.omega*t)
        rf_theo_imag = np.around(rf_theo_imag, 12)

        self.assertListEqual(
            rf_current_real.tolist(),
            rf_theo_real.tolist(),
            msg="In TestRfCurrent test_1, mismatch in real part of RF current")
        self.assertListEqual(
            rf_current_imag.tolist(),
            rf_theo_imag.tolist(),
            msg="In TestRfCurrent test_1, mismatch in real part of RF current")

    # Test charge distribution of a bigaussian profile, without LPF
    # Compare to simulation data
    def test_2(self):

        bigaussian(self.ring,
                   self.rf,
                   self.beam,
                   3.2e-9 / 4,
                   seed=1234,
                   reinsertion=True)
        self.profile.track()

        rf_current = rf_beam_current(self.profile,
                                     self.omega,
                                     self.ring.t_rev[0],
                                     lpf=False)

        Iref_real = np.array([
            0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
            4.17276535e-13, 4.58438681e-13, 2.48023976e-13, 5.29812878e-13,
            2.79735891e-13, 0.00000000e+00, 1.21117141e-12, 9.32525023e-13,
            3.16481489e-13, 6.39337176e-13, 0.00000000e+00, 0.00000000e+00,
            4.08671434e-12, 4.92294314e-12, 6.56965575e-12, 1.06279981e-11,
            1.36819774e-11, 2.16648778e-11, 3.09847740e-11, 3.52971849e-11,
            4.70378842e-11, 4.53538351e-11, 4.87255679e-11, 5.36705228e-11,
            5.13609263e-11, 4.32833543e-11, 3.41417624e-11, 1.57452091e-11,
            -1.09005668e-11, -4.60465929e-11, -9.12872553e-11, -1.48257171e-10,
            -2.08540597e-10, -2.77630608e-10, -3.72157667e-10, -4.56272786e-10,
            -5.57978710e-10, -6.46554672e-10, -7.48006839e-10, -8.21493943e-10,
            -9.37522966e-10, -1.03729659e-09, -1.06159943e-09, -1.08434837e-09,
            -1.15738771e-09, -1.17887328e-09, -1.17146946e-09, -1.10964397e-09,
            -1.10234198e-09, -1.08852433e-09, -9.85866185e-10, -9.11727492e-10,
            -8.25604179e-10, -7.34122902e-10, -6.47294094e-10, -5.30372699e-10,
            -4.40357820e-10, -3.61273445e-10, -2.76871612e-10, -2.02227691e-10,
            -1.45430219e-10, -8.88675652e-11, -4.28984525e-11, -8.85451321e-12,
            1.79026289e-11, 3.48384211e-11, 4.50190278e-11, 5.62413467e-11,
            5.27322593e-11, 4.98163111e-11, 4.83288193e-11, 4.18200848e-11,
            3.13334266e-11, 2.44082106e-11, 2.12572803e-11, 1.37397871e-11,
            1.00879346e-11, 7.78502206e-12, 4.00790815e-12, 2.51830412e-12,
            1.91301488e-12, 0.00000000e+00, 9.58518921e-13, 3.16123806e-13,
            1.24116545e-12, 1.20821671e-12, 5.82952178e-13, 8.35917228e-13,
            5.27285250e-13, 4.93205915e-13, 0.00000000e+00, 2.06937011e-13,
            1.84618141e-13, 1.60868490e-13, 0.00000000e+00, 1.09822742e-13
        ])

        I_real = np.around(rf_current.real, 14)  # round
        Iref_real = np.around(Iref_real, 14)

        self.assertSequenceEqual(
            I_real.tolist(),
            Iref_real.tolist(),
            msg="In TestRFCurrent test_2, mismatch in real part of RF current")

        Iref_imag = np.array([
            0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00,
            -4.86410815e-13, -4.47827158e-13, -2.02886432e-13, -3.60573852e-13,
            -1.56290206e-13, 0.00000000e+00, -4.19433613e-13, -2.33465744e-13,
            -5.01823105e-14, -4.43075921e-14, 0.00000000e+00, 0.00000000e+00,
            8.07144709e-13, 1.43192280e-12, 2.55659168e-12, 5.25480064e-12,
            8.33669524e-12, 1.59729353e-11, 2.73609511e-11, 3.71844853e-11,
            5.92134758e-11, 6.87376280e-11, 9.02226570e-11, 1.24465616e-10,
            1.55478762e-10, 1.84035433e-10, 2.37241518e-10, 2.86677989e-10,
            3.28265272e-10, 3.77882012e-10, 4.29727720e-10, 4.83759029e-10,
            5.13978173e-10, 5.41841031e-10, 5.91537968e-10, 6.00658643e-10,
            6.13928028e-10, 5.96367636e-10, 5.76920099e-10, 5.25297875e-10,
            4.89104065e-10, 4.29776324e-10, 3.33901906e-10, 2.38690921e-10,
            1.49673305e-10, 4.78223853e-11, -5.57081558e-11, -1.51374774e-10,
            -2.50724894e-10, -3.50731761e-10, -4.16547058e-10, -4.83765618e-10,
            -5.36075032e-10, -5.74421794e-10, -6.05459147e-10, -5.91794283e-10,
            -5.88179055e-10, -5.83222843e-10, -5.49774151e-10, -5.08571646e-10,
            -4.86623358e-10, -4.33179012e-10, -3.73737133e-10, -3.37622742e-10,
            -2.89119788e-10, -2.30660798e-10, -1.85597518e-10, -1.66348322e-10,
            -1.19981335e-10, -9.07232680e-11, -7.21467862e-11, -5.18977454e-11,
            -3.25510912e-11, -2.12524272e-11, -1.54447488e-11, -8.24107056e-12,
            -4.90052047e-12, -2.96720377e-12, -1.13551262e-12, -4.79152734e-13,
            -1.91861296e-13, 0.00000000e+00, 7.31481456e-14, 5.23883203e-14,
            3.19951675e-13, 4.27870459e-13, 2.66236636e-13, 4.74712082e-13,
            3.64260145e-13, 4.09222572e-13, 0.00000000e+00, 2.44654594e-13,
            2.61906356e-13, 2.77128356e-13, 0.00000000e+00, 3.01027843e-13
        ])

        I_imag = np.around(rf_current.imag, 14)  # round
        Iref_imag = np.around(Iref_imag, 14)

        self.assertSequenceEqual(
            I_imag.tolist(),
            Iref_imag.tolist(),
            msg="In TestRFCurrent test_2, mismatch in imaginary part of" +
            " RF current")

    # Test charge distribution of a bigaussian profile, with LPF
    # Compare to simulation data
    def test_3(self):

        bigaussian(self.ring,
                   self.rf,
                   self.beam,
                   3.2e-9 / 4,
                   seed=1234,
                   reinsertion=True)
        self.profile.track()
        self.assertEqual(
            len(self.beam.dt), np.sum(self.profile.n_macroparticles), "In" +
            " TestBeamCurrent: particle number mismatch in Beam vs Profile")

        # RF current calculation with low-pass filter
        rf_current = rf_beam_current(self.profile,
                                     self.omega,
                                     self.ring.t_rev[0],
                                     lpf=True)

        Iref_real = np.array([
            -7.1511909689e-12, -7.1512708858e-12, -7.1513482919e-12,
            -7.1514232388e-12, -7.1514957777e-12, -7.1515659593e-12,
            -7.1516338342e-12, -7.1516994523e-12, -7.1517628634e-12,
            -7.1518241168e-12, -7.1518832613e-12, -7.1519403454e-12,
            -7.1519954170e-12, -7.1520485239e-12, -7.1520997131e-12,
            -7.1521490313e-12, -7.1521965247e-12, -7.1522422392e-12,
            -7.1522862199e-12, -7.1523285117e-12, -7.1523691587e-12,
            -7.1524082048e-12, -7.1524456933e-12, -7.1524816668e-12,
            -7.1525161676e-12, -7.1525492372e-12, -7.1525809169e-12,
            -7.1526112471e-12, -7.1526402679e-12, -7.1526680187e-12,
            -7.1526945383e-12, -7.1527198650e-12, -7.1527440365e-12,
            -7.1527670898e-12, -7.1527890615e-12, -7.1528099874e-12,
            -7.1528299028e-12, -7.1528488424e-12, -7.1528668402e-12,
            -7.1528839295e-12, -7.1529001433e-12, -7.1529155136e-12,
            -7.1529300719e-12, -7.1529438491e-12, -7.1529568755e-12,
            -7.1529691807e-12, -7.1529807935e-12, -7.1529917422e-12,
            -7.1530020545e-12, -7.1530117574e-12, -7.1530208772e-12,
            -7.1530294395e-12, -7.1530374694e-12, -7.1530449913e-12,
            -7.1530520287e-12, -7.1530586049e-12, -7.1530647421e-12,
            -7.1530704621e-12, -7.1530757860e-12, -7.1530807343e-12,
            -7.1530853267e-12, -7.1530895824e-12, -7.1530935199e-12,
            -7.1530971572e-12, -7.1531005114e-12, -7.1531035991e-12,
            -7.1531064365e-12, -7.1531090389e-12, -7.1531114211e-12,
            -7.1531135972e-12, -7.1531155809e-12, -7.1531173853e-12,
            -7.1531190226e-12, -7.1531205049e-12, -7.1531218433e-12,
            -7.1531230488e-12, -7.1531241314e-12, -7.1531251010e-12,
            -7.1531259666e-12, -7.1531267370e-12, -7.1531274203e-12,
            -7.1531280242e-12, -7.1531285560e-12, -7.1531290223e-12,
            -7.1531294297e-12, -7.1531297839e-12, -7.1531300904e-12,
            -7.1531303544e-12, -7.1531305805e-12, -7.1531307730e-12,
            -7.1531309360e-12, -7.1531310731e-12, -7.1531311875e-12,
            -7.1531312824e-12, -7.1531313603e-12, -7.1531314238e-12,
            -7.1531314750e-12, -7.1531315159e-12, -7.1531315482e-12,
            -7.1531315733e-12
        ])
        np.testing.assert_allclose(
            rf_current.real,
            Iref_real,
            rtol=1e-6,
            atol=0,
            err_msg=
            "In TestRFCurrent test_3, mismatch in real part of RF current")

        Iref_imag = np.array([
            -2.1797211489e-12, -2.1796772456e-12, -2.1796347792e-12,
            -2.1795937182e-12, -2.1795540314e-12, -2.1795156879e-12,
            -2.1794786570e-12, -2.1794429085e-12, -2.1794084122e-12,
            -2.1793751384e-12, -2.1793430575e-12, -2.1793121404e-12,
            -2.1792823581e-12, -2.1792536822e-12, -2.1792260843e-12,
            -2.1791995365e-12, -2.1791740112e-12, -2.1791494811e-12,
            -2.1791259193e-12, -2.1791032992e-12, -2.1790815944e-12,
            -2.1790607792e-12, -2.1790408280e-12, -2.1790217154e-12,
            -2.1790034169e-12, -2.1789859077e-12, -2.1789691639e-12,
            -2.1789531618e-12, -2.1789378779e-12, -2.1789232894e-12,
            -2.1789093736e-12, -2.1788961083e-12, -2.1788834718e-12,
            -2.1788714425e-12, -2.1788599995e-12, -2.1788491222e-12,
            -2.1788387903e-12, -2.1788289840e-12, -2.1788196838e-12,
            -2.1788108708e-12, -2.1788025262e-12, -2.1787946320e-12,
            -2.1787871702e-12, -2.1787801236e-12, -2.1787734750e-12,
            -2.1787672079e-12, -2.1787613061e-12, -2.1787557538e-12,
            -2.1787505357e-12, -2.1787456369e-12, -2.1787410427e-12,
            -2.1787367390e-12, -2.1787327121e-12, -2.1787289486e-12,
            -2.1787254356e-12, -2.1787221605e-12, -2.1787191111e-12,
            -2.1787162758e-12, -2.1787136430e-12, -2.1787112020e-12,
            -2.1787089419e-12, -2.1787068527e-12, -2.1787049244e-12,
            -2.1787031475e-12, -2.1787015131e-12, -2.1787000122e-12,
            -2.1786986365e-12, -2.1786973779e-12, -2.1786962288e-12,
            -2.1786951818e-12, -2.1786942299e-12, -2.1786933662e-12,
            -2.1786925846e-12, -2.1786918789e-12, -2.1786912433e-12,
            -2.1786906724e-12, -2.1786901610e-12, -2.1786897043e-12,
            -2.1786892977e-12, -2.1786889367e-12, -2.1786886175e-12,
            -2.1786883361e-12, -2.1786880890e-12, -2.1786878729e-12,
            -2.1786876847e-12, -2.1786875215e-12, -2.1786873806e-12,
            -2.1786872597e-12, -2.1786871564e-12, -2.1786870686e-12,
            -2.1786869946e-12, -2.1786869325e-12, -2.1786868808e-12,
            -2.1786868381e-12, -2.1786868031e-12, -2.1786867746e-12,
            -2.1786867517e-12, -2.1786867335e-12, -2.1786867192e-12,
            -2.1786867081e-12
        ])
        np.testing.assert_allclose(
            rf_current.imag,
            Iref_imag,
            rtol=1e-6,
            atol=0,
            err_msg=
            "In TestRFCurrent test_3, mismatch in imaginary part of RF current"
        )

    # Test RF beam current on coarse grid integrated from fine grid
    # Compare to simulation data for peak RF current
    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)
예제 #21
0
class TestBeamFeedback(unittest.TestCase):

    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 test_SPS_RL(self):
        
        PL_gain = 1000  # gain of phase loop
        round_digit = 5  # to how many digits round the result
        
        # Phase loop setup
        
        phase_loop = BeamFeedback(self.ring, self.rf_station, self.profile,
                                  {'machine':'SPS_RL', 'PL_gain':PL_gain})
        
        # Tracker setup
        section_tracker = RingAndRFTracker(
            self.rf_station, self.beam, Profile=self.profile,
            BeamFeedback=phase_loop, interpolation=False)
        tracker = FullRingAndRF([section_tracker])
        
        # average beam position
        beamAvgPos = np.zeros(self.ring.n_turns)
        
        n_turns = self.ring.n_turns
        for turn in range(n_turns):
            beamAvgPos[turn] = np.mean(self.beam.dt)
            self.profile.track()
            tracker.track()
        
        # difference between beam position and synchronuous position 
        # (assuming no beam loading)
        delta_tau = beamAvgPos - (np.pi - self.rf_station.phi_rf[0,:-1])\
            / self.rf_station.omega_rf[0,:-1]
                
        # initial position for analytic solution
        init_pos = self.time_offset
        
        omega_eff = cmath.sqrt(-PL_gain**2 + 4*self.rf_station.omega_s0[0]**2)
        time = np.arange(n_turns) * self.ring.t_rev[0]
        # initial derivative for analytic solution;
        # defined such that analytical solution at turn 1 agrees with numerical
        # solution
        init_slope = 0.5 * (delta_tau[1] * omega_eff * np.exp(0.5*PL_gain*time[1])\
               / np.sin(0.5*omega_eff*time[1]) - delta_tau[0]\
               *(PL_gain+omega_eff/np.tan(0.5*omega_eff*time[1])) ).real
        
        delta_tau_analytic = init_pos * np.exp(-0.5*PL_gain*time)
        delta_tau_analytic *= np.cos(0.5*time*omega_eff).real\
            + (PL_gain+2*init_slope/init_pos)\
            * (np.sin(0.5*time*omega_eff)/omega_eff).real
        
        difference = delta_tau - delta_tau_analytic
        # normalize result
        difference = np.around(difference/np.max(difference), round_digit)
        
        # expected difference
        difference_exp = np.array([
        -1.56306635e-05, -1.55605315e-05,  -2.10224435e-05, -3.18525050e-05,
        -4.74014489e-05, -6.70584402e-05, -9.01307422e-05, -1.15823959e-04,
        -1.43290487e-04, -1.71572162e-04,  -1.99820151e-04,  -2.27071730e-04,
        -2.52331681e-04,  -2.74668126e-04,  -2.93165304e-04, -3.06972913e-04,
        -3.15442474e-04,  -3.17857324e-04, -3.13794970e-04,  -3.02786089e-04,
        -2.84680298e-04, -2.59322215e-04,  -2.26874004e-04,  -1.87452375e-04,
        -1.41293604e-04,  -8.89863575e-05,  -3.08865701e-05, 3.22411495e-05,
        9.97408029e-05,   1.70914181e-04, 2.44766912e-04, 3.20596833e-04,
        3.97403451e-04, 4.74233283e-04,   5.50189125e-04, 6.24368453e-04,
        6.95836553e-04,   7.63737143e-04,   8.27069057e-04, 8.84995559e-04,
        9.36770723e-04,   9.81561780e-04, 1.01869959e-03,   1.04738842e-03,
        1.06711062e-03, 1.07736961e-03,   1.07778386e-03,   1.06805613e-03,
        1.04797776e-03,   1.01747638e-03,   9.76519221e-04, 9.25420191e-04,
        8.64415092e-04,   7.93844624e-04, 7.14396030e-04, 6.26549187e-04,   
        5.31154439e-04, 4.28985322e-04,   3.21198916e-04,   2.08550190e-04,
        9.21607082e-05,  -2.68249728e-05,  -1.47278123e-04, -2.67890543e-04,
        -3.87642210e-04,  -5.05244473e-04, -6.19660328e-04,  -7.29670300e-04,
        -8.34272846e-04, -9.32388033e-04,  -1.02301036e-03,  -1.10520861e-03,
        -1.17824066e-03,  -1.24119243e-03,  -1.29350096e-03, -1.33458128e-03,
        -1.36388379e-03,  -1.38105465e-03, -1.38595634e-03,  -1.37832214e-03,
        -1.35829791e-03, -1.32588558e-03,  -1.28146000e-03,  -1.22518721e-03,
        -1.15769141e-03,  -1.07943574e-03,  -9.91143310e-04, -8.93671637e-04,
        -7.87961546e-04,  -6.74866999e-04, -5.55444011e-04,  -4.30919368e-04,
        -3.02270469e-04, -1.70824836e-04,  -3.77396109e-05,   9.56816273e-05,
         2.28299979e-04,   3.58842001e-04,   4.86074690e-04, 6.08875045e-04,
         7.26090501e-04,   8.36677390e-04, 9.39639556e-04,   1.03407702e-03,
         1.11906014e-03, 1.19386315e-03,   1.25779004e-03,   1.31037519e-03,
         1.35108872e-03,   1.37958003e-03,   1.39570542e-03, 1.39927441e-03,
         1.39033118e-03,   1.36892681e-03, 1.33533475e-03,   1.28987173e-03,
         1.23311389e-03, 1.16551418e-03,   1.08773037e-03,   1.00059786e-03,
         9.04879918e-04,   8.01551710e-04,   6.91575582e-04, 5.75952750e-04,
         4.55756793e-04,   3.32302985e-04, 2.06487043e-04,   7.95882588e-05,
         -4.72208138e-05, -1.72823958e-04,  -2.96101535e-04,  -4.15925168e-04,
        -5.31250383e-04,  -6.41017819e-04,  -7.44349685e-04, -8.40276057e-04,
        -9.28032591e-04,  -1.00688055e-03, -1.07610640e-03,  -1.13518206e-03,
        -1.18370702e-03, -1.22129557e-03,  -1.24764964e-03,  -1.26264035e-03,
        -1.26627364e-03,  -1.25857717e-03,  -1.23964021e-03,
        -1.20980891e-03,  -1.16944284e-03,  -1.11887385e-03,
        -1.05870668e-03,  -9.89617769e-04,  -9.12311681e-04,
        -8.27560752e-04,  -7.36170045e-04,  -6.39042153e-04,
        -5.37114997e-04,  -4.31247869e-04,  -3.22637131e-04,
        -2.12194968e-04,  -1.00869243e-04,   1.03136916e-05,
         1.20241207e-04,   2.27979265e-04,   3.32675130e-04,
         4.33323979e-04,   5.29105666e-04,   6.19142445e-04,
         7.02728753e-04,   7.79114404e-04,   8.47787258e-04,
         9.08216047e-04,   9.59821724e-04,   1.00228122e-03,
         1.03538392e-03,   1.05880009e-03,   1.07260841e-03,
         1.07662550e-03,   1.07093155e-03,   1.05577003e-03,
         1.03129797e-03,   9.97904596e-04,   9.55975595e-04,
         9.05955028e-04,   8.48396342e-04,   7.83925297e-04,
         7.13242537e-04,   6.36896396e-04,   5.55809454e-04,
         4.70697276e-04,   3.82464668e-04,   2.91766220e-04,
         1.99564879e-04,   1.06707654e-04,   1.40463177e-05,
        -7.76333806e-05,  -1.67470574e-04,  -2.54708122e-04,
        -3.38623857e-04,  -4.18484684e-04])
        difference_exp = np.around(difference_exp/np.max(difference_exp),
                                   round_digit)
        
        self.assertListEqual(difference.tolist(), difference_exp.tolist(),
            msg='In TestBeamFeedback test_SPS_RL: '
            +'difference between simulated and analytic result different than'
            +'expected')