Skip to content

Commit db9a031

Browse files
committed
add simulation with e-cloud
1 parent bd38bc0 commit db9a031

File tree

1 file changed

+236
-0
lines changed

1 file changed

+236
-0
lines changed
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
import communication_helpers as ch
2+
import numpy as np
3+
from scipy.constants import c
4+
5+
6+
class Simulation(object):
7+
def __init__(self):
8+
self.N_turns = 128
9+
10+
def init_all(self):
11+
n_slices = 100
12+
z_cut = 2.5e-9*c
13+
14+
self.n_slices = n_slices
15+
self.z_cut = z_cut
16+
17+
n_segments=70
18+
19+
from LHC import LHC
20+
self.machine = LHC(machine_configuration='Injection', n_segments=n_segments, D_x=0.,
21+
RF_at='end_of_transverse')
22+
23+
# We suppose that all the object that cannot be slice parallelized are at the end of the ring
24+
i_end_parallel = len(self.machine.one_turn_map)-1 #only RF is not parallelizable
25+
26+
# split the machine
27+
N_wkrs = self.ring_of_CPUs.N_wkrs
28+
N_elements_per_worker = int(np.floor(float(i_end_parallel)/N_wkrs))
29+
myid = self.ring_of_CPUs.myid
30+
print 'N_elements_per_worker', N_elements_per_worker
31+
if self.ring_of_CPUs.I_am_a_worker:
32+
self.mypart = self.machine.one_turn_map[N_elements_per_worker*myid:N_elements_per_worker*(myid+1)]
33+
print 'I am id=%d and my part is %d long'%(myid, len(self.mypart))
34+
elif self.ring_of_CPUs.I_am_the_master:
35+
self.mypart = self.machine.one_turn_map[N_elements_per_worker*(N_wkrs):i_end_parallel]
36+
self.non_parallel_part = self.machine.one_turn_map[i_end_parallel:]
37+
print 'I am id=%d (master) and my part is %d long'%(myid, len(self.mypart))
38+
39+
40+
# config e-cloud
41+
chamb_type = 'polyg'
42+
x_aper = 2.300000e-02
43+
y_aper = 1.800000e-02
44+
filename_chm = '../pyecloud_config/LHC_chm_ver.mat'
45+
B_multip_per_eV = [1.190000e-12]
46+
B_multip_per_eV = np.array(B_multip_per_eV)
47+
fraction_device = 0.65
48+
intensity = 1.150000e+11
49+
epsn_x = 2.5e-6
50+
epsn_y = 2.5e-6
51+
init_unif_edens_flag = 1
52+
init_unif_edens = 9.000000e+11
53+
N_MP_ele_init = 100000
54+
N_mp_max = N_MP_ele_init*4.
55+
Dh_sc = .2e-3
56+
nel_mp_ref_0 = init_unif_edens*4*x_aper*y_aper/N_MP_ele_init
57+
58+
import PyECLOUD.PyEC4PyHT as PyEC4PyHT
59+
my_new_part = []
60+
self.my_list_eclouds = []
61+
for ele in mypart:
62+
my_new_part.append(ele)
63+
if ele in machine.transverse_map:
64+
ecloud_new = PyEC4PyHT.Ecloud(L_ecloud=machine.circumference/n_segments, slicer=None ,
65+
Dt_ref=10e-12, pyecl_input_folder='../pyecloud_config',
66+
chamb_type = chamb_type,
67+
x_aper=x_aper, y_aper=y_aper,
68+
filename_chm=filename_chm, Dh_sc=Dh_sc,
69+
init_unif_edens_flag=init_unif_edens_flag,
70+
init_unif_edens=init_unif_edens,
71+
N_mp_max=N_mp_max,
72+
nel_mp_ref_0=nel_mp_ref_0,
73+
B_multip=B_multip_per_eV*machine.p0/e*c,
74+
slice_by_slice_mode=True)
75+
my_new_part.append(ecloud_new)
76+
self.my_list_eclouds.append(ecloud_new)
77+
mypart = my_new_part
78+
79+
def init_master(self):
80+
81+
# beam parameters
82+
epsn_x = 2.5e-6
83+
epsn_y = 3.5e-6
84+
sigma_z = 0.05
85+
intensity = 1e11
86+
macroparticlenumber_track = 50000
87+
88+
# initialization bunch
89+
bunch = self.machine.generate_6D_Gaussian_bunch_matched(
90+
macroparticlenumber_track, intensity, epsn_x, epsn_y, sigma_z=sigma_z)
91+
print 'Bunch initialized.'
92+
93+
# initial slicing
94+
from PyHEADTAIL.particles.slicing import UniformBinSlicer
95+
self.slicer = UniformBinSlicer(n_slices = self.n_slices, z_cuts=(-self.z_cut, self.z_cut))
96+
97+
#slice for the first turn
98+
slice_obj_list = bunch.extract_slices(self.slicer)
99+
100+
#prepare to save results
101+
self.beam_x, self.beam_y, self.beam_z = [], [], []
102+
self.sx, self.sy, self.sz = [], [], []
103+
self.epsx, self.epsy, self.epsz = [], [], []
104+
105+
pieces_to_be_treated = slice_obj_list
106+
107+
return pieces_to_be_treated
108+
109+
def init_worker(self):
110+
pass
111+
112+
def treat_piece(self, piece):
113+
for ele in self.mypart:
114+
ele.track(piece)
115+
116+
def finalize_turn_on_master(self, pieces_treated):
117+
118+
# re-merge bunch
119+
bunch = sum(pieces_treated)
120+
121+
#finalize present turn (with non parallel part, e.g. synchrotron motion)
122+
for ele in self.non_parallel_part:
123+
ele.track(bunch)
124+
125+
#csave results
126+
self.beam_x.append(bunch.mean_x())
127+
self.beam_y.append(bunch.mean_y())
128+
self.beam_z.append(bunch.mean_z())
129+
self.sx.append(bunch.sigma_x())
130+
self.sy.append(bunch.sigma_y())
131+
self.sz.append(bunch.sigma_z())
132+
self.epsx.append(bunch.epsn_x()*1e6)
133+
self.epsy.append(bunch.epsn_y()*1e6)
134+
self.epsz.append(bunch.epsn_z())
135+
136+
# prepare next turn (re-slice)
137+
new_pieces_to_be_treated = bunch.extract_slices(self.slicer)
138+
orders_to_pass = ['reset_clouds']
139+
140+
return orders_to_pass, new_pieces_to_be_treated
141+
142+
143+
def execute_orders_from_master(self, orders_from_master):
144+
if 'reset_clouds' in orders_from_master:
145+
for ec in self.my_list_eclouds: ec.finalize_and_reinitialize()
146+
147+
148+
149+
def finalize_simulation(self):
150+
151+
# save results
152+
import myfilemanager as mfm
153+
mfm.save_dict_to_h5('beam_coord.h5',{\
154+
'beam_x':self.beam_x,
155+
'beam_y':self.beam_y,
156+
'beam_z':self.beam_z,
157+
'sx':self.sx,
158+
'sy':self.sy,
159+
'sz':self.sz,
160+
'epsx':self.epsx,
161+
'epsy':self.epsy,
162+
'epsz':self.epsz})
163+
164+
# output plots
165+
if False:
166+
beam_x = self.beam_x
167+
beam_y = self.beam_y
168+
beam_z = self.beam_z
169+
sx = self.sx
170+
sy = self.sy
171+
sz = self.sz
172+
epsx = self.epsx
173+
epsy = self.epsy
174+
epsz = self.epsz
175+
176+
import pylab as plt
177+
178+
plt.figure(2, figsize=(16, 8), tight_layout=True)
179+
plt.subplot(2,3,1)
180+
plt.plot(beam_x)
181+
plt.ylabel('x [m]');plt.xlabel('Turn')
182+
plt.gca().ticklabel_format(style='sci', scilimits=(0,0),axis='y')
183+
plt.subplot(2,3,2)
184+
plt.plot(beam_y)
185+
plt.ylabel('y [m]');plt.xlabel('Turn')
186+
plt.gca().ticklabel_format(style='sci', scilimits=(0,0),axis='y')
187+
plt.subplot(2,3,3)
188+
plt.plot(beam_z)
189+
plt.ylabel('z [m]');plt.xlabel('Turn')
190+
plt.gca().ticklabel_format(style='sci', scilimits=(0,0),axis='y')
191+
plt.subplot(2,3,4)
192+
plt.plot(np.fft.rfftfreq(len(beam_x), d=1.), np.abs(np.fft.rfft(beam_x)))
193+
plt.ylabel('Amplitude');plt.xlabel('Qx')
194+
plt.subplot(2,3,5)
195+
plt.plot(np.fft.rfftfreq(len(beam_y), d=1.), np.abs(np.fft.rfft(beam_y)))
196+
plt.ylabel('Amplitude');plt.xlabel('Qy')
197+
plt.subplot(2,3,6)
198+
plt.plot(np.fft.rfftfreq(len(beam_z), d=1.), np.abs(np.fft.rfft(beam_z)))
199+
plt.xlim(0, 0.1)
200+
plt.ylabel('Amplitude');plt.xlabel('Qz')
201+
202+
fig, axes = plt.subplots(3, figsize=(16, 8), tight_layout=True)
203+
twax = [plt.twinx(ax) for ax in axes]
204+
axes[0].plot(sx)
205+
twax[0].plot(epsx, '-g')
206+
axes[0].set_xlabel('Turns')
207+
axes[0].set_ylabel(r'$\sigma_x$')
208+
twax[0].set_ylabel(r'$\varepsilon_y$')
209+
axes[1].plot(sy)
210+
twax[1].plot(epsy, '-g')
211+
axes[1].set_xlabel('Turns')
212+
axes[1].set_ylabel(r'$\sigma_x$')
213+
twax[1].set_ylabel(r'$\varepsilon_y$')
214+
axes[2].plot(sz)
215+
twax[2].plot(epsz, '-g')
216+
axes[2].set_xlabel('Turns')
217+
axes[2].set_ylabel(r'$\sigma_x$')
218+
twax[2].set_ylabel(r'$\varepsilon_y$')
219+
axes[0].grid()
220+
axes[1].grid()
221+
axes[2].grid()
222+
for ax in list(axes)+list(twax):
223+
ax.ticklabel_format(useOffset=False, style='sci', scilimits=(0,0),axis='y')
224+
plt.show()
225+
226+
def piece_to_buffer(self, piece):
227+
buf = ch.beam_2_buffer(piece)
228+
return buf
229+
230+
def buffer_to_piece(self, buf):
231+
piece = ch.buffer_2_beam(buf)
232+
return piece
233+
234+
235+
236+

0 commit comments

Comments
 (0)