|
| 1 | +import time, h5py, os |
| 2 | +import numpy as np |
| 3 | +from matplotlib import pyplot as plt |
| 4 | +from scipy import constants as cst |
| 5 | +from scipy.signal import hilbert |
| 6 | +from scipy.stats import linregress |
| 7 | + |
| 8 | +import xobjects as xo |
| 9 | +import xtrack as xt |
| 10 | +import xfields as xf |
| 11 | +import xwakes as xw |
| 12 | + |
| 13 | +context = xo.ContextCpu() |
| 14 | + |
| 15 | +energy = 7E3 |
| 16 | +qx = 62.31 |
| 17 | +qy = 60.32 |
| 18 | +momentumCompaction = 3.483575072011584e-04 |
| 19 | +basic_slot_time = 25E-9 |
| 20 | +n_bunch_max = 3000 |
| 21 | +n_bunch = 100 |
| 22 | +bunch_intensity = 5E12 |
| 23 | +RF_voltage = 16.0E6 |
| 24 | +emit_norm = 2.5E-6 |
| 25 | +sigma_z = 0.08 |
| 26 | +selected_bunch = n_bunch-1 |
| 27 | + |
| 28 | +assert n_bunch_max%n_bunch == 0 |
| 29 | +circumference = n_bunch_max * basic_slot_time * cst.c |
| 30 | +bunch_spacing_zeta = circumference/n_bunch |
| 31 | +beta_x = circumference/(2.0*np.pi*qx) |
| 32 | +beta_y = circumference/(2.0*np.pi*qy) |
| 33 | +mass0 = cst.value('proton mass energy equivalent in MeV')*1E-3 |
| 34 | +gamma = energy/mass0 |
| 35 | +RF_freq = 10.0/basic_slot_time |
| 36 | +sigma_x = np.sqrt(emit_norm*beta_x/gamma) |
| 37 | +sigma_px = np.sqrt(emit_norm/beta_x/gamma) |
| 38 | +sigma_y = np.sqrt(emit_norm*beta_y/gamma) |
| 39 | +sigma_py = np.sqrt(emit_norm/beta_y/gamma) |
| 40 | +bucket_length = cst.c/RF_freq |
| 41 | +bucker_center = -1*selected_bunch*bunch_spacing_zeta |
| 42 | +betar = np.sqrt(1 - 1 / gamma ** 2) |
| 43 | +p0 = cst.m_p * betar * gamma * cst.c |
| 44 | +harmonic_number = circumference / bucket_length |
| 45 | +eta = 1/gamma**2-momentumCompaction |
| 46 | +qs = np.sqrt(cst.e * RF_voltage * np.abs(eta) * harmonic_number / (2 * np.pi * betar * cst.c * p0)) |
| 47 | +averageRadius = circumference / (2.0*np.pi) |
| 48 | +sigma_pz = qs*sigma_z/(averageRadius*np.abs(eta)) |
| 49 | +zeta_range=(-3*sigma_z, 3*sigma_z) |
| 50 | +filling_scheme = np.ones(n_bunch,dtype=int) |
| 51 | +omegarev= 2.0*np.pi*cst.c/circumference |
| 52 | + |
| 53 | +n_part = int(2E4) |
| 54 | +n_turns_wake = 10 |
| 55 | +num_slices = 21 |
| 56 | +n_turn = int(1E4) |
| 57 | +coupled_bunch_mode_number = 90 |
| 58 | + |
| 59 | +wf = xw.wit.ComponentClassicThickWall(kind = 'dipole_x', |
| 60 | + layer=xw.wit.Layer(thickness=None,dc_resistivity=1E-8), |
| 61 | + radius=0.02, length = circumference, zero_rel_tol = 0.0) |
| 62 | + |
| 63 | +tune_shift_nx, tune_shift_m0, effective_impedance = xw.wit.sacherer_formula.sacherer_formula( |
| 64 | + qp = 0.0, |
| 65 | + nx_array = np.array([coupled_bunch_mode_number]), |
| 66 | + bunch_intensity = bunch_intensity, |
| 67 | + omegas = qs*omegarev, |
| 68 | + n_bunches = n_bunch, |
| 69 | + omega_rev = omegarev, |
| 70 | + tune=qx, |
| 71 | + gamma=gamma, |
| 72 | + eta = eta, |
| 73 | + bunch_length_seconds = sigma_z*4/cst.c, |
| 74 | + m_max = 0, |
| 75 | + impedance_function = wf.impedance) |
| 76 | + |
| 77 | +particles = xt.Particles( |
| 78 | + _context = context, |
| 79 | + q0 = 1, |
| 80 | + p0c = energy*1E9, |
| 81 | + mass0 = mass0*1E9, |
| 82 | + x = sigma_x*(np.random.randn(n_part)+2), |
| 83 | + px = sigma_px*(np.random.randn(n_part)), |
| 84 | + y = sigma_y*np.random.randn(n_part), |
| 85 | + py = sigma_py*np.random.randn(n_part), |
| 86 | + zeta = sigma_z*np.random.randn(n_part) + bucker_center, |
| 87 | + delta = sigma_pz*np.random.randn(n_part), |
| 88 | + weight = bunch_intensity / n_part |
| 89 | + ) |
| 90 | + |
| 91 | +arc = xt.LineSegmentMap(length=None, qx=qx, qy=qy, |
| 92 | + betx=beta_x, bety=beta_y, |
| 93 | + longitudinal_mode='linear_fixed_rf', |
| 94 | + voltage_rf = RF_voltage, |
| 95 | + frequency_rf = RF_freq, |
| 96 | + lag_rf = 180.0, |
| 97 | + slippage_length = circumference, |
| 98 | + momentum_compaction_factor = momentumCompaction) |
| 99 | + |
| 100 | +wf.configure_for_tracking(zeta_range=zeta_range, |
| 101 | + num_slices=num_slices, |
| 102 | + bunch_spacing_zeta=bunch_spacing_zeta, |
| 103 | + num_turns=n_turns_wake, |
| 104 | + circumference=circumference, |
| 105 | + filling_scheme = filling_scheme, |
| 106 | + bunch_selection = [selected_bunch], |
| 107 | + fake_coupled_bunch_phase_x = 2.0*np.pi*coupled_bunch_mode_number/n_bunch, |
| 108 | + beta_x = beta_x, |
| 109 | + ) |
| 110 | + |
| 111 | +longitudinal_acceptance = xt.LongitudinalLimitRect(min_zeta=bucker_center-bucket_length, max_zeta=bucker_center+bucket_length) |
| 112 | + |
| 113 | +log = xt.Log(mean_x=lambda l,p:p.x.mean()) |
| 114 | + |
| 115 | +line = xt.Line([arc,longitudinal_acceptance,wf]) |
| 116 | +line.build_tracker(_context=context) |
| 117 | +line.track(particles,num_turns=n_turn,log=log) |
| 118 | + |
| 119 | +ampl = np.abs(hilbert(line.log_last_track['mean_x'])) |
| 120 | +turns = np.arange(len(ampl)) |
| 121 | +start_fit = 100 |
| 122 | +end_fit = len(ampl)-100 |
| 123 | +fit = linregress(turns[start_fit:end_fit],np.log(ampl[start_fit:end_fit])) |
| 124 | + |
| 125 | +assert np.isclose(fit.slope,-2.0*np.pi*np.imag(tune_shift_nx[0][0]),rtol=5E-2) |
| 126 | + |
| 127 | + |
0 commit comments