def test_wake(self): time = np.linspace(-0.1e-6, 0.7e-6, 1000) 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) TWC_impedance_source.wake_calc(time - time[0]) wake_impSource = np.around(TWC_impedance_source.wake / 1e12, 12) TWC_impulse_response = SPS4Section200MHzTWC() # omega_c not need for computation of wake function TWC_impulse_response.impulse_response_beam(2 * np.pi * 200.222e6, time) TWC_impulse_response.impulse_response_gen(2 * np.pi * 200.222e6, time) TWC_impulse_response.compute_wakes(time) wake_impResp = np.around(TWC_impulse_response.W_beam / 1e12, 12) self.assertListEqual( wake_impSource.tolist(), wake_impResp.tolist(), msg="In TestTravelingWaveCavity test_wake: wake fields differ")
def test_wake(self): time = np.linspace(-0.1e-6, 0.7e-6, 1000) 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) TWC_impedance_source.wake_calc(time-time[0]) wake_impSource = np.around(TWC_impedance_source.wake/1e12, 12) TWC_impulse_response = SPS4Section200MHzTWC() # omega_c not need for computation of wake function TWC_impulse_response.impulse_response_beam(2*np.pi*200.222e6, time) TWC_impulse_response.impulse_response_gen(2*np.pi*200.222e6, time) TWC_impulse_response.compute_wakes(time) wake_impResp = np.around(TWC_impulse_response.W_beam/1e12, 12) self.assertListEqual(wake_impSource.tolist(), wake_impResp.tolist(), msg="In TestTravelingWaveCavity test_wake: wake fields differ")
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)
R_shunt_short = L_short**2 * R2 / 8 # shunt impedance [Ohm] damping_time_short = 2 * np.pi * L_short / vg * (1 + 0.0946) n_cav_short = 2 # factor 2 because of two cavities are used for tracking elif cavities == 'future': L_long = 43 * 0.374 # interaction length [m] R_shunt_long = L_long**2 * R2 / 8 # shunt impedance [Ohm] damping_time_long = 2 * np.pi * L_long / vg * (1 + 0.0946) n_cav_long = 2 # factor 2 because of two cavities are used for tracking L_short = 32 * 0.374 # interaction length [m] R_shunt_short = L_short**2 * R2 / 8 # shunt impedance [Ohm] damping_time_short = 2 * np.pi * L_short / vg * (1 + 0.0946) n_cav_short = 4 # factor 4 because of four cavities are used for tracking longCavity = TravelingWaveCavity(n_cav_long * R_shunt_long, fr, damping_time_long) longCavityFreq = InducedVoltageFreq(beam, profile, [longCavity], frequency_step) longCavityIntensity = TotalInducedVoltage(beam, profile, [longCavityFreq]) shortCavity = TravelingWaveCavity(n_cav_short * R_shunt_short, fr, damping_time_short) shortCavityFreq = InducedVoltageFreq(beam, profile, [shortCavity], frequency_step) shortCavityIntensity = TotalInducedVoltage(beam, profile, [shortCavityFreq]) # FB parameters if FB_strength == 'present': FBstrengthLong = 1.05 FBstrengthShort = 0.73 elif FB_strength == 'future':
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")
def reduce_impedance_feedforward_feedback( profile, freqres, impedanceScenario, outdir=None, Gfb=10.0, gff=0.5): # Changed default from Gfb = 7.5 to 10. on 05.Aug.2020 if type(Gfb) is not list: if (Gfb == 0.): Gfblist = [None, None] else: Gfblist = [Gfb, Gfb] else: # It comes already in a list form: # For past/present imp: [4-sec cavs, 5-sec cavs] # For future imp: [3-sec cavs, 4-sec cavs] Gfblist = copy(Gfb) pass if type(gff) is not list: if (gff == 0.): gfflist = [None, None] else: gfflist = [gff, gff] else: # For past/present imp: [4-sec cavs, 5-sec cavs] # For future imp: [3-sec cavs, 4-sec cavs] gfflist = copy(gff) pass ##gfb = # 1/(4.*50)*10. #4.*50. * 0.1 #gfb = 1e-2 #1.5e-2 #0.86e6/2. # 1e-3 # None #1e-6 # with Zr #print(f'impedanceScenario = {impedanceScenario}') print( f'impedanceScenario.scenarioFileName = {impedanceScenario.scenarioFileName}' ) if ('future' in impedanceScenario.scenarioFileName): Gfb3or5sec = Gfblist[0] Gfb4sec = Gfblist[1] print('* Gfb3sec =', Gfb3or5sec, '(Gfb3or5sec)') print('* Gfb4sec =', Gfb4sec) gff3or5sec = gfflist[0] gff4sec = gfflist[1] print('* gff3sec =', gff3or5sec, '(gff3or5sec)') print('* gff4sec =', gff4sec) else: Gfb3or5sec = Gfblist[1] Gfb4sec = Gfblist[0] print('* Gfb5sec =', Gfb3or5sec, '(Gfb3or5sec)') print('* Gfb4sec =', Gfb4sec) gff3or5sec = gfflist[1] gff4sec = gfflist[0] print('* gff5sec =', gff3or5sec, '(gff3or5sec)') print('* gff4sec =', gff4sec) print('') print('Running reduce_impedance_feedforward...\n') # Frequency array freq_res = freqres / 10 #150e3 n_fft = int(1. / (profile.bin_size) / freq_res) print('n_fft =', n_fft) profile.beam_spectrum_freq_generation(n_fft) freq_array = profile.beam_spectrum_freq print( 'freq_array =', freq_array, len(freq_array) ) # it will not be exactly equal than the frequency array to be computed in the profile print('') #quit() # Find the index of the main harmonic cavities in the impedance list using their source file names as keys # (the necessary attenuations (e.g. from FB) and corrections have already been performed upon loading): key3 = 'cavities/200MHz/3sections/TWC200_3sections_dome_MAIN.dat' key4 = 'cavities/200MHz/4sections/TWC200_4sections_dome_MAIN.dat' key5 = 'cavities/200MHz/5sections/TWC200_5sections_dome_MAIN.dat' elID_dict = { } # List of indices of the main cavities to be "erased" and replaced for i in range(len(impedanceScenario.SPSimpList)): filei = impedanceScenario.SPSimpList[i]['file'] if (i < 15 or i == len(impedanceScenario.SPSimpList) - 1): print(i, filei) elif (i == 15): print('...') if (filei == key3): elID_dict['3sections'] = i # i = elIDkey3 if (filei == key4): elID_dict['4sections'] = i # i = elIDkey4 if (filei == key5): elID_dict['5sections'] = i # i = elIDkey5 print('') print('Elements being replaced:') print('elID_dict =', elID_dict) print('') # Parameters for the cavities Z_0 = 50 # Characteristic impedance of the RF chain [Ohm] oneCellLength = 0.374 # Length of one cell [m] = 0.374 m rho = 27.1e3 # Series impedance of the cavity [Ohm/m^2] vg = 0.0946 * c # Group velocity [m/s] elID_list = [] for key in elID_dict.keys(): elID = elID_dict[key] elID_list.append(elID) print('elID =', elID, ' | key =', key, '|', impedanceScenario.table_impedance[elID]['file']) print('') if (key == '4sections'): nsections = 4 ncavities = 2 print('nsections = ', nsections) print('ncavities = ', ncavities) print('') L4sec = oneCellLength * ( nsections * 11 - 0.5 - 0.5 ) # Length of the 4-section 200MHz cavities (43 cells) [m] print('L4sec =', L4sec) print('') fr4sec = impedanceScenario.table_impedance[elID]['fr'][ 0, 0] # Centre frequency of the 4-section 200MHz cavities [Hz] Rsh4sec = impedanceScenario.table_impedance[elID]['Rsh'][ 0, 0] / ncavities # Shunt impedance [Ohm] # = (rho*L4sec**2)/8., the shunt impedance? [Ohm] -> works alpha4sec = impedanceScenario.table_impedance[elID]['alpha'][ 0, 0] # Time factor alpha [s] # = L4sec/vg* 0.5*( (1.-vg/c) + (1.+vg/c)) *2*np.pi, the daming time [s] (average of 1.-vg/c and 1.+vg/c): rho4sec = 8. * Rsh4sec / L4sec**2 print('fr4sec =', fr4sec) print('Rsh4sec =', Rsh4sec / 1e6, 'MOhm') print('alpha4sec =', alpha4sec / 1e-6, 'us') print('rho4sec =', rho4sec / 1e3, 'kOhm/m2') print('rho4sec/rho =', rho4sec / rho) print('') # For comparison: creating TWCs with the parameters derived from the loaded input using BLonD's TWC object: twc4sec = TravelingWaveCavity(Rsh4sec, fr4sec, alpha4sec) twc4sec.imped_calc(freq_array) Ztwc4sec = twc4sec.impedance print('Ztwc4sec =', Ztwc4sec) # ~ Zb4sec print('') # Creating TWCs, characterised by their impedance (Zb); creating RF impedance (Zrf) params0 = [fr4sec, Z_0, rho4sec, L4sec, vg] ReZb4sec = ReZb(freq_array, *params0) Zb4sec = Zb(freq_array, *params0) print('ReZb4sec =', ReZb4sec, '\n', max(np.abs(np.real(ReZb4sec))), max(np.abs(np.imag(ReZb4sec))), max(np.abs(ReZb4sec))) print('Zb4sec =', Zb4sec, '\n', max(np.abs(np.real(Zb4sec))), max(np.abs(np.imag(Zb4sec))), max(np.abs(Zb4sec))) print('') ReZrf4sec = ReZrf(freq_array, *params0) Zrf4sec = Zrf(freq_array, *params0) print('ReZrf4sec =', ReZrf4sec, '\n', max(np.abs(ReZrf4sec))) print('Zrf4sec =', Zrf4sec, '\n', max(np.abs(Zrf4sec))) print('') Zrf4secnew = np.copy(Zb4sec) # FF reduction if (gff4sec is not None): hff4sec = gff4sec / (4. * Z_0) ReHff4sec = hff4sec * ReZrf4sec ImHff4sec = 0. Hff4sec = ReHff4sec + 1j * ImHff4sec Zrf4secnew -= Hff4sec * Zrf4sec print('gff4sec =', gff4sec) print('hff4sec =', hff4sec) print('Hff4sec =', Hff4sec) else: print('No FF') print('Zrf4secnew =', Zrf4secnew, '\n', max(np.abs(np.real(Zrf4secnew))), max(np.abs(np.imag(Zrf4secnew))), max(np.abs(Zrf4secnew))) print('') # FB reduction (acting on top of the FF-reduction, if applicable) #if(gfb is not None): if (Gfb4sec is not None): # gfb4sec = Gfb4sec * ((rho4sec*L4sec**2)/8.) # hfb4sec = gfb4sec / ((rho4sec*L4sec**2)/8.) # Hfb4sec = hfb4sec * ReZb4sec # [1] # #gfb4sec = Gfb4sec * (L4sec*np.sqrt(rho4sec*Z_0/2.)) # #hfb4sec = gfb4sec / (L4sec*np.sqrt(rho4sec*Z_0/2.)) # #Hfb4sec = hfb4sec * ReZrf4sec # [1] # #Zrf4secnew /= 1. + Hfb4sec*Zrf4sec # #Zrf4secnew /= Zb4sec + Hfb4sec*Zrf4sec # Hfb4sec = Gfb4sec / (4.*Z_0) # Zrf4secnew /= 1. + Hfb4sec*Hff4sec*Zrf4sec # #Zrf4secnew /= Zb4sec + Hfb4sec*Hff4sec*Zrf4sec # #Zrf4secnew /= 1. + Hfb4sec*Zrf4secnew # #Zrf4secnew /= Zb4sec + Hfb4sec*Zrf4secnew # print('Gfb4sec =', Gfb4sec) # print('gfb4sec =', gfb4sec) # print('hfb4sec =', hfb4sec) # print('Hfb4sec =', Hfb4sec) Hfb4secZrf = Gfb4sec * ReZb4sec / ((rho4sec * L4sec**2) / 8.) Zrf4secnew /= 1. + Hfb4secZrf print('Hfb4secZrf =', Hfb4secZrf) else: print('No FB') print('Zrf4secnew =', Zrf4secnew, '\n', max(np.abs(np.real(Zrf4secnew))), max(np.abs(np.imag(Zrf4secnew))), max(np.abs(Zrf4secnew))) print('') elif (key == '3sections' or key == '5sections'): if (key == '3sections'): nsections = 3 ncavities = 4 elif (key == '5sections'): nsections = 5 ncavities = 2 print('nsections = ', nsections) print('ncavities = ', ncavities) print('') L3or5sec = oneCellLength * ( nsections * 11 - 0.5 - 0.5 ) # Length of the (3/5)-section cavities (32/54 cells) [m] print('L3or5sec =', L3or5sec) print('') fr3or5sec = impedanceScenario.table_impedance[elID]['fr'][ 0, 0] # Centre frequency of the 200MHz cavities [Hz] Rsh3or5sec = impedanceScenario.table_impedance[elID]['Rsh'][ 0, 0] / ncavities # Shunt impedance [Ohm] # = (rho*L3or5sec**2)/8., the shunt impedance? [Ohm] -> works alpha3or5sec = impedanceScenario.table_impedance[elID]['alpha'][ 0, 0] # Time factor alpha [s] # = L3or5sec/vg* 0.5*( (1.-vg/c) + (1.+vg/c)) *2*np.pi, the daming time [s] (average of 1.-vg/c and 1.+vg/c): rho3or5sec = 8. * Rsh3or5sec / L3or5sec**2 print('fr3or5sec =', fr3or5sec) print('Rsh3or5sec =', Rsh3or5sec / 1e6, 'MOhm') print('alpha3or5sec =', alpha3or5sec / 1e-6, 'us') print('rho3or5sec =', rho3or5sec / 1e3, 'kOhm/m2') print('rho3or5sec/rho =', rho3or5sec / rho) print('') # For comparison: creating TWCs with the parameters derived from the loaded input using BLonD's TWC object: twc3or5sec = TravelingWaveCavity(Rsh3or5sec, fr3or5sec, alpha3or5sec) twc3or5sec.imped_calc(freq_array) Ztwc3or5sec = twc3or5sec.impedance print('Ztwc3or5sec =', Ztwc3or5sec) # ~ Zb3or5sec print('') # Creating TWCs, characterised by their impedance (Zb); creating RF impedance (Zrf) params1 = [fr3or5sec, Z_0, rho3or5sec, L3or5sec, vg] ReZb3or5sec = ReZb(freq_array, *params1) Zb3or5sec = Zb(freq_array, *params1) print('ReZb3or5sec =', ReZb3or5sec, '\n', max(np.abs(np.real(ReZb3or5sec))), max(np.abs(np.imag(ReZb3or5sec))), max(np.abs(ReZb3or5sec))) print('Zb3or5sec =', Zb3or5sec, '\n', max(np.abs(np.real(Zb3or5sec))), max(np.abs(np.imag(Zb3or5sec))), max(np.abs(Zb3or5sec))) print('') ReZrf3or5sec = ReZrf(freq_array, *params1) Zrf3or5sec = Zrf(freq_array, *params1) print('ReZrf3or5sec =', ReZrf3or5sec, '\n', max(np.abs(ReZrf3or5sec))) print('Zrf3or5sec =', Zrf3or5sec, '\n', max(np.abs(Zrf3or5sec))) print('') Zrf3or5secnew = np.copy(Zb3or5sec) # FF reduction if (gff3or5sec is not None): hff3or5sec = gff3or5sec / (4. * Z_0) ReHff3or5sec = hff3or5sec * Zrf3or5sec ImHff3or5sec = 0. Hff3or5sec = ReHff3or5sec + 1j * ImHff3or5sec Zrf3or5secnew -= Hff3or5sec * Zrf3or5sec print('gff3or5sec =', gff3or5sec) print('hff3or5sec =', hff3or5sec) print('Hff3or5sec =', Hff3or5sec) else: print('No FF') print('Zrf3or5secnew =', Zrf3or5secnew, '\n', max(np.abs(np.real(Zrf3or5secnew))), max(np.abs(np.imag(Zrf3or5secnew))), max(np.abs(Zrf3or5secnew))) print('') # FB reduction (acting on top of the FF-reduction, if applicable) #if(gfb is not None): if (Gfb3or5sec is not None): # gfb3or5sec = Gfb3or5sec * ((rho3or5sec*L3or5sec**2)/8.) # hfb3or5sec = gfb3or5sec / ((rho3or5sec*L3or5sec**2)/8.) # Hfb3or5sec = hfb3or5sec * ReZb3or5sec # [1] # #gfb3or5sec = Gfb3or5sec * (L3or5sec*np.sqrt(rho3or5sec*Z_0/2.)) # #hfb3or5sec = gfb3or5sec / (L3or5sec*np.sqrt(rho3or5sec*Z_0/2.)) # #Hfb3or5sec = hfb3or5sec * ReZrf3or5sec # [1] # #Zrf3or5secnew /= 1. + Hfb3or5sec*Zrf3or5sec # #Zrf3or5secnew /= Zb3or5sec + Hfb3or5sec*Zrf3or5sec # Hfb3or5sec = Gfb3or5sec / (4.*Z_0) # Zrf3or5secnew /= 1. + Hfb3or5sec*Hff3or5sec*Zrf3or5sec # #Zrf3or5secnew /= Zb3or5sec + Hfb3or5sec*Hff3or5sec*Zrf3or5sec # #Zrf3or5secnew /= 1. + Hfb3or5sec*Zrf3or5secnew # #Zrf3or5secnew /= Zb3or5sec + Hfb3or5sec*Zrf3or5secnew # print('Gfb3or5sec =', Gfb3or5sec) # print('gfb3or5sec =', gfb3or5sec) # print('hfb3or5sec =', hfb3or5sec) # print('Hfb3or5sec =', Hfb3or5sec) Hfb3or5secZrf = Gfb3or5sec * ReZb3or5sec / ( (rho3or5sec * L3or5sec**2) / 8.) Zrf3or5secnew /= 1. + Hfb3or5secZrf print('Hfb3or5secZrf =', Hfb3or5secZrf) else: print('No FB') print('Zrf3or5secnew =', Zrf3or5secnew, '\n', max(np.abs(np.real(Zrf3or5secnew))), max(np.abs(np.imag(Zrf3or5secnew))), max(np.abs(Zrf3or5secnew))) print('') #quit() ################################ # "Erase" the main harmonic already loaded and replace it by the new one. # Only the contributions in the range [0, 1 GHz] are set to zero (the frequency # as computed above might span higher, e.g 6.41 GHz if using the usual 44 kHz # from SPS input as frequency resolution for i in elID_list: impedanceScenario.damp_R_resonatorOrTWC(i, [ 0, 1e9 ], R_factor=0.) # Deletes elIDkey4 and elIDkey5 if 'present' or 'past' # or elIDkey3 and elIDkey4 if 'future' print('') ## Replace them with the a new object that is the sum of the new cavities: #if('present' in impedanceScenario.scenarioFileName or 'past' in impedanceScenario.scenarioFileName): # 'past' is similar to present with attenuations of -20.0/-20.0 instead of -15.0/None for the 200MHz/800MHz systems (if applicable) # impedanceScenario.importInputTableFromList([freq_array, # np.real(2*Zrfnew4 + 2*Zrfnew5), # np.imag(2*Zrfnew4 + 2*Zrfnew5)], # 'cavities/totalReducedByFeedbackFeedforward') #elif('future' in impedanceScenario.scenarioFileName): # impedanceScenario.importInputTableFromList([freq_array, # np.real(2*Zrfnew4 + 4*Zrfnew3), # np.imag(2*Zrfnew4 + 4*Zrfnew3)], # 'cavities/totalReducedByFeedbackFeedforward') #else: # raise RuntimeError('You must use MODEL= \'present\' or \'future\' to use the reducesImpedanceFeedbackFeedforward function') if outdir is not None: impedanceScenario.importInputTableFromList([ freq_array, np.real(2 * Zrf4secnew + ncavities * Zrf3or5secnew), np.imag(2 * Zrf4secnew + ncavities * Zrf3or5secnew) ], 'cavities/200MHz_total_reducedFF') # plot myncols = 3 mynrows = 3 fig, ax = plt.subplots( nrows=mynrows, ncols=myncols) #, sharex=True,sharey=True) #) #2) #,sharex=True) fig.set_size_inches(1.5 * 4.0 * myncols, 1.5 * 2.0 * mynrows) for nrow in [0, 1]: if ('3sections' in elID_dict.keys()): nsec = '3' elif ('5sections' in elID_dict.keys()): nsec = '5' #print('nrow =', nrow) if (nrow == 0): ZbA = Zb4sec #ZtwcA = Zb4sec ZrfA = Zrf4sec ZrfnewA = Zrf4secnew nsecA = '4' elif (nrow == 1): ZbA = Zb3or5sec #ZtwcA = Zb3or5sec ZrfA = Zrf3or5sec ZrfnewA = Zrf3or5secnew nsecA = nsec print('ZbA =', ZbA, max(np.abs(ZbA))) print('ZrfA =', ZrfA, max(np.abs(ZrfA))) print('ZrfnewA =', ZrfnewA, max(np.abs(ZrfnewA))) print('') #ax[nrow][0].plot(freq_array/1e6, np.real(ZtwcA)/1e6, '-y', label=r'Re($Z_{twc,'+nsecA+r'}$)', alpha=0.5) #ax[nrow][1].plot(freq_array/1e6, np.imag(ZtwcA)/1e6, '-y', label=r'Im($Z_{twc,'+nsecA+r'}$)', alpha=0.5) #ax[nrow][2].plot(freq_array/1e6, np.abs( ZtwcA)/1e6, '-y', label=r'|$Z_{twc,'+nsecA+r'}$|' , alpha=0.5) ax[nrow][0].plot(freq_array / 1e6, np.real(ZbA) / 1e6, '--r', label=r'Re($Z_{b,' + nsecA + r'}$)', alpha=0.5) # = ReZb ax[nrow][1].plot(freq_array / 1e6, np.imag(ZbA) / 1e6, '--r', label=r'Im($Z_{b,' + nsecA + r'}$)', alpha=0.5) # = ImZb ax[nrow][2].plot(freq_array / 1e6, np.abs(ZbA) / 1e6, '--r', label=r'|$Z_{b,' + nsecA + r'}$|', alpha=0.5) # = |Zb| ax[nrow][0].plot(freq_array / 1e6, np.real(ZrfA) / 1e6, '-b', label=r'Re($Z_{rf,' + nsecA + r'}$)', alpha=0.8) # = ReZrf = Zrf ax[nrow][1].plot(freq_array / 1e6, np.imag(ZrfA) / 1e6, '-b', label=r'Im($Z_{rf,' + nsecA + r'}$)', alpha=0.8) # = zero by definition ax[nrow][2].plot(freq_array / 1e6, np.abs(ZrfA) / 1e6, '-b', label=r'|$Z_{rf,' + nsecA + r'}$|', alpha=0.8) # = |Zrf| ax[nrow][0].plot(freq_array / 1e6, np.real(ZrfnewA) / 1e6, ':k', label=r'Re($Z_{rf,' + nsecA + r'}^{new}$)', alpha=1.0) ax[nrow][1].plot(freq_array / 1e6, np.imag(ZrfnewA) / 1e6, ':k', label=r'Im($Z_{rf,' + nsecA + r'}^{new}$)', alpha=1.0) ax[nrow][2].plot(freq_array / 1e6, np.abs(ZrfnewA) / 1e6, ':k', label=r'|$Z_{rf,' + nsecA + r'}^{new}$|', alpha=1.0) #ax[nrow][2].plot(freq_array/1e6, 20*np.log10( np.abs(ZrfnewA)/np.abs(ZbA) )/100., '-g', label=r'20 log( |$Z_{rf,'+nsecA+r'}^{new}|/|Z_{b,'+nsecA+r'}$| ) /100'+f'\n(min = {min(20*np.log10( np.abs(ZrfnewA)/np.abs(ZbA) )):.4f})', alpha=1.0) ##ax[nrow][2].plot(freq_array/1e6, -0.3*np.ones(len(freq_array)), ':', color='#888888') for nrow in [2]: ZbA = Zb4sec #ZtwcA = Zb4sec ZrfA = Zrf4sec ZrfnewA = Zrf4secnew nsecA = '4' ZbB = Zb3or5sec #ZtwcB = Zb3or5sec ZrfB = Zrf3or5sec ZrfnewB = Zrf3or5secnew nsecB = nsec #ax[nrow][0].plot(freq_array/1e6, np.real(2*ZtwcA+ncavities*ZtwcB)/1e6, '-y', label=r'Re($2 Z_{twc,'+nsecB+r'} + '+str(ncavities)+r' Z_{twc,'+nsecB+r'}$)', alpha=0.5) # = ReZtwc #ax[nrow][1].plot(freq_array/1e6, np.imag(2*ZtwcA+ncavities*ZtwcB)/1e6, '-y', label=r'Im($2 Z_{twc,'+nsecB+r'} + '+str(ncavities)+r' Z_{twc,'+nsecB+r'}$)', alpha=0.5) # = ImZtwc #ax[nrow][2].plot(freq_array/1e6, np.abs( 2*ZtwcA+ncavities*ZtwcB)/1e6, '-y', label=r'|$2 Z_{twc,'+nsecB+r'} + '+str(ncavities)+r' Z_{twc,'+nsecB+r'}$|' , alpha=0.5) # = |Ztwc| ax[nrow][0].plot(freq_array / 1e6, np.real(2 * ZbA + ncavities * ZbB) / 1e6, '--r', label=r'Re($2 Z_{b,' + nsecA + r'} + ' + str(ncavities) + r' Z_{b,' + nsecB + r'}$)', alpha=0.5) # = ReZb ax[nrow][1].plot(freq_array / 1e6, np.imag(2 * ZbA + ncavities * ZbB) / 1e6, '--r', label=r'Im($2 Z_{b,' + nsecA + r'} + ' + str(ncavities) + r' Z_{b,' + nsecB + r'}$)', alpha=0.5) # = ImZb ax[nrow][2].plot(freq_array / 1e6, np.abs(2 * ZbA + ncavities * ZbB) / 1e6, '--r', label=r'|$2 Z_{b,' + nsecA + r'} + ' + str(ncavities) + r' Z_{b,' + nsecB + r'}$|', alpha=0.5) # = |Zb| ax[nrow][0].plot(freq_array / 1e6, np.real(2 * ZrfA + ncavities * ZrfB) / 1e6, '-b', label=r'Re($2 Z_{rf,' + nsecA + r'} + ' + str(ncavities) + r' Z_{rf,' + nsecB + r'}$)', alpha=0.8) # = ReZrf = Zrf ax[nrow][1].plot(freq_array / 1e6, np.imag(2 * ZrfA + ncavities * ZrfB) / 1e6, '-b', label=r'Im($2 Z_{rf,' + nsecA + r'} + ' + str(ncavities) + r' Z_{rf,' + nsecB + r'}$)', alpha=0.8) # = zero by definition ax[nrow][2].plot(freq_array / 1e6, np.abs(2 * ZrfA + ncavities * ZrfB) / 1e6, '-b', label=r'|$2 Z_{rf,' + nsecA + r'} + ' + str(ncavities) + r' Z_{rf,' + nsecB + r'}$|', alpha=0.8) # = |Zrf| ax[nrow][0].plot(freq_array / 1e6, np.real(2 * ZrfnewA + ncavities * ZrfnewB) / 1e6, ':k', label=r'Re($2 Z_{rf,' + nsecA + r'}^{new} + ' + str(ncavities) + r' Z_{rf,' + nsecB + r'}^{new}$)', alpha=1.0) ax[nrow][1].plot(freq_array / 1e6, np.imag(2 * ZrfnewA + ncavities * ZrfnewB) / 1e6, ':k', label=r'Im($2 Z_{rf,' + nsecA + r'}^{new} + ' + str(ncavities) + r' Z_{rf,' + nsecB + r'}^{new}$)', alpha=1.0) ax[nrow][2].plot(freq_array / 1e6, np.abs(2 * ZrfnewA + ncavities * ZrfnewB) / 1e6, ':k', label=r'|$2 Z_{rf,' + nsecA + r'}^{new} + ' + str(ncavities) + r' Z_{rf,' + nsecB + r'}^{new}$|', alpha=1.0) ##ax[nrow][2].plot(freq_array/1e6, 10*np.log10(np.abs(2*ZrfnewA + ncavities*ZrfnewB)/np.abs(2*ZbA+ncavities*ZbB))/100., '-g', label=r'log|$2 Z_{rf,'+nsecB+r'}^{new} + '+str(ncavities)+r' Z_{rf,'+nsecB+r'}^{new}$|/|$2 Z_{b,'+nsecB+r'} + '+str(ncavities)+r' Z_{b,'+nsecB+r'}$|/10' , alpha=1.0) ##ax[nrow][2].plot(freq_array/1e6, -0.3*np.ones(len(freq_array)), ':', color='#888888') for i in range(mynrows): ax[i][0].set_ylabel('Impedance (M$\Omega$)') for j in range(myncols): if (i == 0): ax[mynrows - 1][j].set_xlabel('f (MHz)') #if(j==2-1): ax[i][j].legend(frameon=False, loc='upper left') # loc='best') ax[i][j].set_xlim(180, 220) ax[i][j].grid() fig.tight_layout() fig.savefig(outdir + '/plot_reduce_impedance_feedforward_feedback.pdf') print('Saving', outdir + '/plot_reduce_impedance_feedforward_feedback.pdf ...\n') fig.clf()
ax8.set_ylabel("RF current [A]") ax8.legend() logging.info("Peak beam current, meas %.10f A" %(peak_rf_current)) logging.info("Peak beam current, theor %.4f A" %(2*N_b*e/bunch_spacing)) if IMP_RESP == True: # Impulse response of beam- and generator-induced voltage for TWC # Comparison of wake and impulse resonse time = np.linspace(-1e-6, 4.e-6, 10000) TWC_v1 = SPS4Section200MHzTWC() TWC_v1.impulse_response_beam(2*np.pi*f_rf, time) TWC_v1.impulse_response_gen(2*np.pi*f_rf, time) TWC_v1.compute_wakes(time) TWC_v2 = TravelingWaveCavity(0.876e6, f_rf, 2*np.pi*6.207e-7) TWC_v2.wake_calc(time - time[0]) t_beam = time - time[0] t_gen = time - time[0] - 0.5*TWC_v1.tau plt.figure() plt.plot(TWC_v2.time_array, TWC_v2.wake, 'b', marker='.', label='wake, impedances') plt.plot(t_beam, TWC_v1.W_beam, 'r', marker='.', label='cav wake, OTFB') plt.plot(t_beam, TWC_v1.h_beam.real, 'g', marker='.', label='hs_cav, OTFB') plt.plot(t_gen, TWC_v1.W_gen, 'orange', marker='.', label='gen wake, OTFB') plt.plot(t_gen, TWC_v1.h_gen.real, 'purple', marker='.', label='hs_gen, OTFB') plt.xlabel("Time [s]") plt.ylabel("Wake/impulse response [Ohms/s]") plt.legend()
ax8.set_ylabel("RF current [A]") ax8.legend() logging.info("Peak beam current, meas %.10f A" %(peak_rf_current)) logging.info("Peak beam current, theor %.4f A" %(2*N_b*e/bunch_spacing)) if IMP_RESP == True: # Impulse response of beam- and generator-induced voltage for TWC # Comparison of wake and impulse resonse time = np.linspace(-1e-6, 4.e-6, 10000) TWC_v1 = SPS4Section200MHzTWC() TWC_v1.impulse_response_beam(2*np.pi*f_rf, time) TWC_v1.impulse_response_gen(2*np.pi*f_rf, time) TWC_v1.compute_wakes(time) TWC_v2 = TravelingWaveCavity(0.876e6, f_rf, 2*np.pi*6.207e-7) # From impedance sources, params: R_S, frequency_R, a_factor TWC_v2.wake_calc(time - time[0]) t_beam = time - time[0] t_gen = time - time[0] - 0.5*TWC_v1.tau plt.figure() plt.plot(TWC_v2.time_array, TWC_v2.wake, 'b', marker='.', label='wake, impedances') plt.plot(t_beam, TWC_v1.W_beam, 'r', marker='.', label='beam wake, OTFB') plt.plot(t_beam, TWC_v1.h_beam.real, 'g', marker='.', label='hs_beam, OTFB') plt.plot(t_gen, TWC_v1.W_gen, 'orange', marker='.', label='gen wake, OTFB') plt.plot(t_gen, TWC_v1.h_gen.real, 'purple', marker='.', label='hs_gen, OTFB') plt.xlabel("Time [s]") plt.ylabel("Wake/impulse response [Ohms/s]") plt.legend()