Example #1
0
    def setUp(self):
        self.general_params = Ring(np.ones(self.n_sections) * self.C/self.n_sections,
                                   np.tile(self.momentum_compaction,
                                           (1, self.n_sections)).T,
                                   np.tile(self.sync_momentum,
                                           (self.n_sections, self.n_turns+1)),
                                   self.particle_type, self.n_turns, n_sections=self.n_sections)
        self.RF_sct_par = []
        self.RF_sct_par_cpp = []
        for i in np.arange(self.n_sections)+1:
            self.RF_sct_par.append(RFStation(self.general_params,
                                             [self.harmonic_numbers], [
                                                 self.voltage_program/self.n_sections],
                                             [self.phi_offset], self.n_rf_systems, section_index=i))
            self.RF_sct_par_cpp.append(RFStation(self.general_params,
                                                 [self.harmonic_numbers], [
                                                     self.voltage_program/self.n_sections],
                                                 [self.phi_offset], self.n_rf_systems, section_index=i))

        # DEFINE BEAM------------------------------------------------------------------

        self.beam = Beam(self.general_params,
                         self.n_macroparticles, self.n_particles)
        self.beam_cpp = Beam(self.general_params,
                             self.n_macroparticles, self.n_particles)

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

        number_slices = 500

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

        self.slice_beam_cpp = Profile(self.beam_cpp, CutOptions=cut_options)

        # DEFINE TRACKER---------------------------------------------------------------
        self.longitudinal_tracker = []
        self.longitudinal_tracker_cpp = []
        for i in range(self.n_sections):
            self.longitudinal_tracker.append(RingAndRFTracker(
                self.RF_sct_par[i], self.beam, Profile=self.slice_beam))
            self.longitudinal_tracker_cpp.append(RingAndRFTracker(
                self.RF_sct_par_cpp[i], self.beam_cpp, Profile=self.slice_beam_cpp))

        full_tracker = FullRingAndRF(self.longitudinal_tracker)
        full_tracker_cpp = FullRingAndRF(self.longitudinal_tracker_cpp)

        # BEAM GENERATION--------------------------------------------------------------

        matched_from_distribution_function(self.beam, full_tracker, emittance=self.emittance,
                                           distribution_type=self.distribution_type,
                                           distribution_variable=self.distribution_variable, seed=1000)
        
        matched_from_distribution_function(self.beam_cpp, full_tracker_cpp, emittance=self.emittance,
                                           distribution_type=self.distribution_type,
                                           distribution_variable=self.distribution_variable, seed=1000)

        self.slice_beam.track()
        self.slice_beam_cpp.track()
Example #2
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)
Example #3
0
    def setUp(self):

        initial_time = 0
        final_time = 1E-3

        # Machine and RF parameters
        radius = 25
        gamma_transition = 4.4  # [1]
        C = 2 * np.pi * radius  # [m]
        momentum_compaction = 1 / gamma_transition**2  # [1]
        particle_type = 'proton'

        self.ring = Ring(C, momentum_compaction, \
                                   ([0, 1E-3], [3.13E8, 3.13E8]), Proton())

        self.rf_params = RFStation(self.ring, [1], [1E3], [np.pi], 1)
        self.beam = Beam(self.ring, 1, 0)
        self.profile = Profile(self.beam)

        self.long_tracker = RingAndRFTracker(self.rf_params, self.beam)
        self.full_ring = FullRingAndRF([self.long_tracker])

        self.n_turns = self.ring.n_turns

        self.map_ = [self.full_ring.track, self.profile.track]

        self.trackIt = TrackIteration(self.map_)
    def test_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)
Example #5
0
 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)
Example #6
0
 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)
Example #7
0
    def setUp(self):

        C = 2 * np.pi * 1100.009  # Ring circumference [m]
        gamma_t = 18.0  # Gamma at transition
        alpha = 1 / gamma_t**2  # Momentum compaction factor
        p_s = 25.92e9  # Synchronous momentum at injection [eV]

        N_m = 1e5  # Number of macro-particles for tracking
        N_b = 1.0e11  # Bunch intensity [ppb]

        # Set up machine parameters
        self.ring = Ring(C, alpha, p_s, Proton(), n_turns=1)

        # RF-frequency at which to compute beam current
        self.omega = 2 * np.pi * 200.222e6

        # Create Gaussian beam
        self.beam = Beam(self.ring, N_m, N_b)
        self.profile = Profile(self.beam,
                               CutOptions=CutOptions(cut_left=-1.e-9,
                                                     n_slices=100,
                                                     cut_right=6.e-9))
    def setUp(self):
        n_turns = 200
        intensity_pb = 1.2e6  # protons per bunch
        n_macroparticles = int(1e6)  # macropartilces per bunch
        sigma = 0.05e-9  # sigma for gaussian bunch [s]
        self.time_offset = 0.1e-9  # time by which to offset the bunch

        # Ring parameters SPS
        C = 6911.5038  # Machine circumference [m]
        sync_momentum = 25.92e9  # SPS momentum at injection [eV/c]
        gamma_transition = 17.95142852  # Q20 Transition gamma
        momentum_compaction = 1./gamma_transition**2  # Momentum compaction array

        self.ring = Ring(C, momentum_compaction, sync_momentum, Proton(),
                         n_turns=n_turns)

        # RF parameters SPS
        harmonic = 4620  # Harmonic numbers
        voltage = 4.5e6  # [V]
        phi_offsets = 0

        self.rf_station = RFStation(self.ring, harmonic, voltage, phi_offsets)
        t_rf = self.rf_station.t_rf[0, 0]

        # Beam setup
        self.beam = Beam(self.ring, n_macroparticles, intensity_pb)

        bigaussian(self.ring, self.rf_station, self.beam, sigma, seed=1234,
                   reinsertion=True)

        # displace beam to see effect of phase error and phase loop
        self.beam.dt += self.time_offset

        # Profile setup

        self.profile = Profile(self.beam, CutOptions=CutOptions(cut_left=0,
                                                                cut_right=t_rf,
                                                                n_slices=1024))
Example #9
0
    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))
Example #10
0
    def setUp(self):
        # Bunch parameters (dummy)
        N_b = 1e9  # Intensity
        N_p = 50000  # Macro-particles
        # Machine and RF parameters
        C = 26658.883  # Machine circumference [m]
        p_s = 450e9  # Synchronous momentum [eV/c]
        h = 35640  # Harmonic number
        V = 4e6  # RF voltage [V]
        dphi = 0  # Phase modulation/offset
        gamma_t = 53.8  # Transition gamma
        alpha = 1 / gamma_t**2  # First order mom. comp. factor

        # Initialise necessary classes
        ring = Ring(C, alpha, p_s, Particle=Proton(), n_turns=1)
        self.rf = RFStation(ring, [h], [V], [dphi])
        beam = Beam(ring, N_p, N_b)
        self.profile = Profile(beam)

        # Test in open loop, on tune
        self.RFFB = LHCRFFeedback(open_drive=True)
        self.f_c = self.rf.omega_rf[0, 0] / (2 * np.pi)
Example #11
0
 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))
Example #12
0
bunch = Beam(ring, n_particles, N_b)
beam = Beam(ring, n_particles*n_bunches, N_b)
bigaussian(ring, rf, bunch, 0.3e-9, reinsertion=True, seed=seed)
bunch_spacing_buckets = 10

for i in np.arange(n_bunches):
    beam.dt[i*n_particles:(i+1) *
            n_particles] = bunch.dt[0:n_particles] + i*rf.t_rf[0, 0]*10
    beam.dE[i*n_particles:(i+1)*n_particles] = bunch.dE[0:n_particles]


# Profile required for PL
cutRange = (n_bunches-1)*25.e-9+3.5e-9
n_slices = np.int(cutRange/0.025e-9 + 1)
n_slices = next_regular(n_slices)
profile = Profile(beam, CutOptions(n_slices=n_slices, cut_left=-0.5e-9,
                                   cut_right=(cutRange-0.5e-9)))
mpiprint("Beam generated, profile set...")
mpiprint("Using %d slices" % n_slices)

# Define emittance BUP feedback
noiseFB = LHCNoiseFB(rf, profile, bl_target)
mpiprint("Phase noise feedback set...")

# Define phase loop and frequency loop gain
PL_gain = 1./(5.*ring.t_rev[0])
SL_gain = PL_gain/10.

# Noise injected in the PL delayed by one turn and opposite sign
config = {'machine': 'LHC', 'PL_gain': PL_gain, 'SL_gain': SL_gain}
PL = BeamFeedback(ring, rf, profile, config, PhaseNoise=LHCnoise,
                  LHCNoiseFB=noiseFB)
Example #13
0
long_tracker = RingAndRFTracker(rf_params, beam)

eta_0_test = rf_params.eta_0  #: *Slippage factor (0th order) for the given RF section*
eta_1_test = rf_params.eta_1  #: *Slippage factor (1st order) for the given RF section*
eta_2_test = rf_params.eta_2  #: *Slippage factor (2nd order) for the given RF section*
alpha_order_test = rf_params.alpha_order

bigaussian(general_params,
           rf_params,
           beam,
           tau_0 / 4,
           reinsertion='on',
           seed=1)

# Need slices for the Gaussian fit
slice_beam = Profile(beam, CutOptions(n_slices=100))

# Define what to save in file
bunchmonitor = BunchMonitor(general_params,
                            rf_params,
                            beam,
                            this_directory +
                            '../output_files/EX_07_output_data',
                            Profile=slice_beam)

format_options = {'dirname': this_directory + '../output_files/EX_07_fig'}
plots = Plot(general_params,
             rf_params,
             beam,
             dt_plt,
             N_t,
beam_dummy = Beam(general_params, 1, N_b)
long_tracker_tot = RingAndRFTracker(rf_params_tot, beam_dummy)

print("General and RF parameters set...")


# Define beam and distribution

bigaussian(general_params, rf_params_tot, beam, tau_0/4, 
                              reinsertion = 'on', seed=1)

print("Beam set and distribution generated...")


# Need slices for the Gaussian fit; slice for the first plot
slice_beam = Profile(beam, CutOptions(n_slices=100),
                 FitOptions(fit_option='gaussian'))       
# Define what to save in file
bunchmonitor = BunchMonitor(general_params, rf_params_tot, beam,
                            this_directory + '../output_files/EX_04_output_data',
                            Profile=slice_beam, buffer_time=1)

# PLOTS
format_options = {'dirname': this_directory + '../output_files/EX_04_fig', 'linestyle': '.'}
plots = Plot(general_params, rf_params_tot, beam, dt_plt, dt_plt, 0, 
             0.0001763*h, -450e6, 450e6, xunit='rad',
             separatrix_plot=True, Profile=slice_beam,
             h5file=this_directory + '../output_files/EX_04_output_data',
             histograms_plot=True, format_options=format_options)

# For testing purposes
test_string = ''
Example #15
0
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

# 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',
Example #16
0
# -----------------------------------------------------------------------------

# Plot settings
plt.rc('axes', labelsize=12, labelweight='normal')
plt.rc('lines', linewidth=1.5, markersize=6)
plt.rc('font', family='sans-serif')
plt.rc('legend', fontsize=12)

# Logger for messages on console & in file
Logger(debug=True)

ring = Ring(C, alpha, p_s, Particle=Proton(), n_turns=1)
rf = RFStation(ring, [h], [V], [dphi])

beam = Beam(ring, N_p, N_b)
profile = Profile(beam, CutOptions(n_slices=100),
                  FitOptions(fit_option='gaussian'))

logging.info(
    'Initialising LHCCavityLoop, tuned to injection (with no beam current)')
logging.info('CLOSED LOOP, no excitation, 1 turn tracking')
CL = LHCCavityLoop(
    rf,
    profile,
    f_c=rf.omega_rf[0, 0] / (2 * np.pi),
    G_gen=1,
    I_gen_offset=0,
    n_cav=8,
    n_pretrack=1,
    Q_L=20000,
    R_over_Q=45,
    tau_loop=650e-9,  #T_s=25e-9,
Example #17
0
ring_RF_section_freq = RingAndRFTracker(RF_sct_par_freq, my_beam_freq)
ring_RF_section_res = RingAndRFTracker(RF_sct_par_res, my_beam_res)

# DEFINE BEAM------------------------------------------------------------------

bigaussian(general_params, RF_sct_par, my_beam, tau_0/4, 
                             seed=1)
bigaussian(general_params_freq, RF_sct_par_freq, my_beam_freq,
                        tau_0/4, seed=1)
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',
Example #18
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")
Example #19
0
    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)
Example #20
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!')
Example #21
0
                       [phi_offset], n_rf_systems)

beam = Beam(general_params, n_macroparticles, n_particles)
ring_RF_section = RingAndRFTracker(RF_sct_par, beam)

bucket_length = 2.0 * np.pi / RF_sct_par.omega_rf[0,0]

# DEFINE BEAM------------------------------------------------------------------

bigaussian(general_params, RF_sct_par, beam, sigma_dt, seed=1)


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

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


# Overwriting the slices by a Gaussian profile (no slicing noise)
slice_beam.n_macroparticles = (n_macroparticles * slice_beam.bin_size /
    (sigma_dt * np.sqrt(2.0 * np.pi)) * np.exp(-0.5 *
    (slice_beam.bin_centers - bucket_length/2.0)**2.0 / sigma_dt**2.0))
                    
# LOAD IMPEDANCE TABLES--------------------------------------------------------

R_S = 5e3
frequency_R = 10e6
Q = 10

resonator = Resonators(R_S, frequency_R, Q)
Example #22
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")
Example #23
0
                                   Proton(), n_turns)
# Cavities parameters
n_rf_systems = 1                                     
harmonic_numbers_1 = 1  # [1]  
voltage_1 = 8000  # [V]  
phi_offset_1 = np.pi   # [rad]
rf_params = RFStation(
    general_params, [harmonic_numbers_1], [voltage_1],
    [phi_offset_1], n_rf_systems,
    omega_rf=[1.00001*2.*np.pi/general_params.t_rev[0]])

my_beam = Beam(general_params, n_macroparticles, n_particles)


cut_options = CutOptions(cut_left= 0, cut_right=2.0*0.9e-6, n_slices=200)
slices_ring = Profile(my_beam, cut_options)



#Phase loop
configuration = {'machine': 'PSB', 'PL_gain': 0., 'RL_gain': [0.,0.],
                 'period': 10.0e-6}
phase_loop = BeamFeedback(general_params, rf_params, slices_ring, configuration)


#Long tracker
long_tracker = RingAndRFTracker(rf_params, my_beam,
                                BeamFeedback=phase_loop)

full_ring = FullRingAndRF([long_tracker])
Example #24
0
                       [phi_offset], n_rf_systems)

beam = Beam(general_params, n_macroparticles, n_particles)
ring_RF_section = RingAndRFTracker(RF_sct_par, beam)

bucket_length = 2.0 * np.pi / RF_sct_par.omega_rf[0, 0]

# DEFINE BEAM------------------------------------------------------------------

bigaussian(general_params, RF_sct_par, beam, sigma_dt, seed=1)

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

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

# Overwriting the slices by a Gaussian profile (no slicing noise)
slice_beam.n_macroparticles = (
    n_macroparticles * slice_beam.bin_size /
    (sigma_dt * np.sqrt(2.0 * np.pi)) * np.exp(
        -0.5 *
        (slice_beam.bin_centers - bucket_length / 2.0)**2.0 / sigma_dt**2.0))

# LOAD IMPEDANCE TABLES--------------------------------------------------------

R_S = 5e3
frequency_R = 10e6
Q = 10
Example #25
0
mpiprint("Setting up the simulation...")

# Define general parameters
ring = Ring(C, alpha, np.linspace(p_i, p_f, n_turns + 1), Proton(), n_turns)

# Define beam and distribution
beam = Beam(ring, n_particles, N_b)

# Define RF station parameters and corresponding tracker
rf = RFStation(ring, [h], [V], [dphi])

bigaussian(ring, rf, beam, tau_0 / 4, reinsertion=True, seed=seed)

# Need slices for the Gaussian fit
# TODO add the gaussian fit
profile = Profile(beam, CutOptions(n_slices=n_slices))
# FitOptions(fit_option='gaussian'))

long_tracker = RingAndRFTracker(rf, beam)

# beam.split_random()
beam.split()

if args['monitor'] > 0 and worker.isMaster:
    if args.get('monitorfile', None):
        filename = args['monitorfile']
    else:
        filename = 'monitorfiles/ex01-t{}-p{}-b{}-sl{}-approx{}-prec{}-r{}-m{}-se{}-w{}'.format(
            n_iterations, n_particles, n_bunches, n_slices, approx,
            args['precision'], n_turns_reduce, args['monitor'], seed,
            worker.workers)
Example #26
0
for bucket in rf_LoCa.buckets:
    turns_SC.append(bucket[0])
    momentum_SC.append(rf_LoCa.buckets[bucket].momentum)
    momentum_spread_SC.append(rf_LoCa.buckets[bucket].bunch_dp_over_p * 2 / 4.)

# Beam
beam = Beam(ring, n_macroparticles, intensity)

# Profile
cut_options = CutOptions(cut_left,
                         cut_right,
                         n_slices_total,
                         cuts_unit='rad',
                         RFSectionParameters=rf_params)
profile = Profile(beam, cut_options)

# 10 MHz cavities are treated separately
impedance10MHzCavities = scenario(
    MODEL=model,
    method_10MHz='/rf_cavities/10MHz/All/Resonators/multi_resonators_h21.txt')
impedance10MHzCavities.importCavities10MHz(
    impedance10MHzCavities.freq_10MHz,
    method=impedance10MHzCavities.method_10MHz,
    RshFactor=impedance10MHzCavities.RshFactor_10MHz,
    QFactor=impedance10MHzCavities.QFactor_10MHz)

# The rest of the impedance model
impedanceRestOfMachine = scenario(
    MODEL=model,
    method_10MHz='/rf_cavities/10MHz/All/Resonators/multi_resonators_h21.txt')
Example #27
0
                                   Proton(), n_turns)

# Cavities parameters
n_rf_systems = 1                                     
harmonic_numbers_1 = 1
voltage_1 = 8000  # [V]  
phi_offset_1 = np.pi   # [rad]
rf_params = RFStation(general_params, [harmonic_numbers_1], [voltage_1],
                      [phi_offset_1], n_rf_systems)

my_beam = Beam(general_params, n_macroparticles, n_particles)


cut_options = CutOptions(cut_left= 0, cut_right=2*np.pi, n_slices=200, 
                         RFSectionParameters=rf_params, cuts_unit = 'rad')
slices_ring = Profile(my_beam, cut_options)

#Phase loop
configuration = {'machine': 'PSB', 'PL_gain': 1./25.e-6, 'period': 10.e-6}
phase_loop = BeamFeedback(general_params, rf_params, slices_ring, configuration)


#Long tracker
long_tracker = RingAndRFTracker(rf_params, my_beam, periodicity='Off',
                                BeamFeedback=phase_loop)

full_ring = FullRingAndRF([long_tracker])


distribution_type = 'gaussian'
bunch_length = 200.0e-9
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



# 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}})$')
bucket_length = 2.0 * np.pi / RF_sct_par.omega_rf[0,0]

# DEFINE BEAM------------------------------------------------------------------

beam = Beam(general_params, n_macroparticles, n_particles)

# DEFINE TRACKER---------------------------------------------------------------
longitudinal_tracker = RingAndRFTracker(RF_sct_par,beam)
full_tracker = FullRingAndRF([longitudinal_tracker])


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

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)
Example #30
0
general_params = Ring(C, momentum_compaction, sync_momentum, Proton(), n_turns)

RF_sct_par = RFStation(general_params, [harmonic_numbers], [voltage_program],
                       [phi_offset], n_rf_systems)

my_beam = Beam(general_params, n_macroparticles, n_particles)

ring_RF_section = RingAndRFTracker(RF_sct_par, my_beam)

# DEFINE BEAM------------------------------------------------------------------
bigaussian(general_params, RF_sct_par, my_beam, sigma_dt, seed=1)

# DEFINE SLICES----------------------------------------------------------------
slice_beam = Profile(
    my_beam,
    CutOptions(cut_left=-5.72984173562e-7,
               cut_right=5.72984173562e-7,
               n_slices=100))

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

bunchmonitor = BunchMonitor(general_params,
                            RF_sct_par,
                            my_beam,
                            this_directory +
                            '../output_files/EX_02_output_data',
                            buffer_time=1)

# LOAD IMPEDANCE TABLES--------------------------------------------------------

var = str(kin_beam_energy / 1e9)
Example #31
0
profile_margin = 20 * t_rf

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

cut_left = t_batch_begin - profile_margin
cut_right = t_batch_end + profile_margin

# number of rf-buckets of the beam
# + rf-buckets before the beam + rf-buckets after the beam
n_slices = n_bins_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)))

profile = Profile(beam,
                  CutOptions=CutOptions(cut_left=cut_left,
                                        cut_right=cut_right,
                                        n_slices=n_slices))

mpiprint('Profile set!')

# SPS --- Impedance and induced voltage ------------------------------
mpiprint('Setting up impedance')

frequency_step = nFrev * ring.f_rev[0]

if SPS_IMPEDANCE == True:

    if impedance_model_str == 'present':
        number_vvsa = 28
        number_vvsb = 36
        shield_vvsa = False
Example #32
0
    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)
Example #33
0
n_turns = 2000

general_params = Ring(C, alpha, 310891054.809, Proton(), n_turns)

# Cavities parameters
n_rf_systems = 1
harmonic_numbers_1 = 1
voltage_1 = 8000  # [V]
phi_offset_1 = np.pi  # [rad]
rf_params = RFStation(general_params, [harmonic_numbers_1], [voltage_1],
                      [phi_offset_1], n_rf_systems)

my_beam = Beam(general_params, n_macroparticles, n_particles)

cut_options = CutOptions(cut_left=0, cut_right=2.0 * 0.9e-6, n_slices=200)
slices_ring = Profile(my_beam, cut_options)

#Phase loop
#configuration = {'machine': 'PSB', 'PL_gain': 0., 'RL_gain': [34.8,16391],
#                 'PL_period': 10.e-6, 'RL_period': 7}
configuration = {
    'machine': 'PSB',
    'PL_gain': 0,
    'RL_gain': [1.e7, 1.e11],
    'period': 10.e-6
}
phase_loop = BeamFeedback(general_params, rf_params, slices_ring,
                          configuration)

#Long tracker
long_tracker = RingAndRFTracker(rf_params, my_beam, BeamFeedback=phase_loop)
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
        rtol = 1e-4         # relative tolerance
        atol = 0              # absolute tolerance
        # 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 = difference / np.max(difference)
        # 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 = difference_exp/np.max(difference_exp)
        np.testing.assert_allclose(difference_exp, difference,
                                   rtol=rtol, atol=atol,
                                   err_msg='In TestBeamFeedback test_SPS_RL: difference between simulated and analytic result different than expected')
Example #35
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"')
Example #36
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")
RF_sct_par = RFStation(general_params, [harmonic_numbers], [voltage_program],
                       [phi_offset], n_rf_systems)

beam = Beam(general_params, n_macroparticles, n_particles)
ring_RF_section = RingAndRFTracker(RF_sct_par, beam)

full_tracker = FullRingAndRF([ring_RF_section])

fs = RF_sct_par.omega_s0[0]/2/np.pi    

bucket_length = 2.0 * np.pi / RF_sct_par.omega_rf[0,0]

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

number_slices = 3000
slice_beam = Profile(beam, CutOptions(cut_left=0, 
                    cut_right=21*bucket_length, n_slices=number_slices))
                
# LOAD IMPEDANCE TABLES -------------------------------------------------------

R_S = 5e8
frequency_R = 2*RF_sct_par.omega_rf[0,0] / 2.0 / np.pi
Q = 10000

print('Im Z/n = '+str(R_S / (RF_sct_par.t_rev[0] * frequency_R * Q)))

resonator = Resonators(R_S, frequency_R, Q)


# INDUCED VOLTAGE FROM IMPEDANCE ----------------------------------------------

imp_list = [resonator]
Example #38
0
    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()
Example #39
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.mean(np.absolute(self.OTFB.OTFB_4.V_coarse_tot))/1e6
        Vind4_std = np.std(np.absolute(self.OTFB.OTFB_4.V_coarse_tot))/1e6
        Vind4_mean_exp = 1.99886351363
        Vind4_std_exp = 2.148426e-6

        Vind5_mean = np.mean(np.absolute(self.OTFB.OTFB_5.V_coarse_tot))/1e6

        Vind5_std = np.std(np.absolute(self.OTFB.OTFB_5.V_coarse_tot))/1e6

        Vind5_mean_exp = 2.49906605189
        Vind5_std_exp = 2.221665e-6

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

        self.assertAlmostEqual(Vind5_mean, Vind5_mean_exp,
                               places=digit_round,
                               msg='In TestCavityFeedback test_FB_pretracking: ' +
                               'mean value of five-section cavity differs')
        self.assertAlmostEqual(Vind5_std, Vind5_std_exp,
                               places=digit_round,
                               msg='In TestCavityFeedback test_FB_pretracking: standard '
                               + 'deviation of five-section cavity differs')

    def test_FB_pre_tracking_IQ_v1(self):
        rtol = 1e-3         # relative tolerance
        atol = 0            # absolute tolerance
        # 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 = V_fine_tot_4/1e6
        V_tot_5 = V_fine_tot_5/1e6

        V_sum = self.OTFB.V_sum/1e6

        # 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)

        np.testing.assert_allclose(V_tot_4, V_tot_4_exp,
                                   rtol=rtol, atol=atol,
                                   err_msg='In TestCavityFeedback test_FB_pretracking_IQ: total voltage ' +
                                   'in four-section cavity differs')

        np.testing.assert_allclose(V_tot_5, V_tot_5_exp,
                                   rtol=rtol, atol=atol,
                                   err_msg='In TestCavityFeedback test_FB_pretracking_IQ: total voltage ' +
                                   'in five-section cavity differs')

        np.testing.assert_allclose(V_sum, V_sum_exp,
                                   rtol=rtol, atol=atol,
                                   err_msg='In TestCavityFeedback test_FB_pretracking_IQ: voltage sum ' +
                                   ' differs')

    def test_rf_voltage(self):

        digit_round = 9

        # 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 = max_ratio

        max_ratio_exp = 1.0008217052569774
        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 = 9

        # 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.max(cavity_tracker_total_voltage /
                           OTFB_tracker_total_voltage)
        max_ration_exp = 1.0051759770680779

        self.assertAlmostEqual(max_ratio, max_ration_exp, places=digit_round,
                               msg='In TestCavityFeedback test_beam_loading: '
                               + 'total voltages differ')

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

        self.OTFB.track()

        V_sum = self.OTFB.V_sum/1e6

        V_sum_exp = 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

        np.testing.assert_allclose(V_sum_exp, V_sum,
                                   rtol=rtol, atol=atol,
                                   err_msg='In TestCavityFeedback test_Vsum_IQ: total voltage ' +
                                   'is different from expected values!')
Example #40
0
# Single bunch
bunch = Beam(ring, N_m, N_b)
bigaussian(ring, rf, bunch, 3.2e-9 / 4, seed=1234, reinsertion=True)
logging.info("Bunch spacing %.3e s", rf.t_rf[0, 0] * bunch_spacing)

# Create beam
beam = Beam(ring, n_bunches * N_m, n_bunches * N_b)
for i in range(n_bunches):
    beam.dt[int(i *
                N_m):int((i + 1) *
                         N_m)] = bunch.dt + i * rf.t_rf[0, 0] * bunch_spacing
    beam.dE[int(i * N_m):int((i + 1) * N_m)] = bunch.dE

profile = Profile(beam,
                  CutOptions=CutOptions(cut_left=0.e-9,
                                        cut_right=rf.t_rev[0],
                                        n_slices=46200))
profile.track()
logging.debug("Beam q/m ratio %.3e", profile.Beam.ratio)

OTFB = SPSCavityFeedback(rf,
                         beam,
                         profile,
                         G_llrf=5,
                         G_tx=0.5,
                         a_comb=15 / 16,
                         turns=N_pretrack,
                         post_LS2=False,
                         Commissioning=CavityFeedbackCommissioning(
                             debug=True, open_FF=True))
Example #41
0
for i in range(108, 156):
    beam.dt[i * N_m:(i + 1) *
            N_m] = bunch.dt[0:N_m] + i * buckets + 48 * buckets
    beam.dE[i * N_m:(i + 1) * N_m] = bunch.dE[0:N_m]
for i in range(156, 500):
    beam.dt[i * N_m:(i + 1) *
            N_m] = bunch.dt[0:N_m] + i * buckets + 200 * buckets
    beam.dE[i * N_m:(i + 1) * N_m] = bunch.dE[0:N_m]

tot_buckets = (NB + 32 + 40 + 48 + 200) * 10
logging.debug('Maximum of beam coordinates %.4e s', np.max(beam.dt))
logging.info('Number of buckets considered %d', tot_buckets)
logging.debug('Profile cut set at %.4e s', tot_buckets * rf.t_rf[0, 0])
profile = Profile(
    beam,
    CutOptions(n_slices=int(100 * tot_buckets),
               cut_left=0,
               cut_right=tot_buckets * rf.t_rf[0, 0]))
profile.track()
plt.figure('Bunch profile')
plt.plot(profile.bin_centers * 1e9, profile.n_macroparticles)
plt.xlabel('Bin centers [ns]')
plt.ylabel('Macroparticles [1]')
plt.show()

logging.info(
    'Initialising LHCCavityLoop, tuned to injection (with no beam current)')
logging.info('CLOSED LOOP, no excitation, 1 turn tracking')

# DUMMY TO CALCULATE PEAK BEAM CURRENT
CL = LHCCavityLoop(rf,
Example #42
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")
bigaussian(general_params, RF_sct_par, my_beam, tau_0 / 4, seed=1)
bigaussian(general_params_freq,
           RF_sct_par_freq,
           my_beam_freq,
           tau_0 / 4,
           seed=1)
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'))
Example #44
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')