Skip to content

Commit b251bda

Browse files
committed
Merge branch 'develop'
2 parents b5f3c06 + e115d31 commit b251bda

90 files changed

Lines changed: 2485 additions & 1075 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ test_multipole
3434
*.beamc
3535
*.bak
3636
*.out
37+
Pyecltest_angle3D_electron1.mat
38+
Pyecltest_angle3D_electron2.mat
39+
Pyecltest_angle3D_electron3.mat

002_change_version_number.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
with open(filename) as fid:
1010
content=fid.read()
1111
if 'giovanni.iadarola@cern.ch' in content:
12-
content=content.replace('PyECLOUD Version 6.7.2', 'PyECLOUD Version 6.7.2')
12+
content=content.replace('PyECLOUD Version 7.0.0', 'PyECLOUD Version 7.0.0')
1313
with open(filename,'w') as fid:
1414
fid.write(content)
1515

003_change_preamble.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#
2121
# This file is part of the code:
2222
#
23-
# PyECLOUD Version 6.7.2
23+
# PyECLOUD Version 7.0.0
2424
#
2525
#
2626
# Main author: Giovanni IADAROLA

MP_system.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#
88
# This file is part of the code:
99
#
10-
# PyECLOUD Version 6.7.2
10+
# PyECLOUD Version 7.0.0
1111
#
1212
#
1313
# Main author: Giovanni IADAROLA

PyEC4PyHT.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#
88
# This file is part of the code:
99
#
10-
# PyECLOUD Version 6.7.2
10+
# PyECLOUD Version 7.0.0
1111
#
1212
#
1313
# Main author: Giovanni IADAROLA
@@ -63,9 +63,9 @@ class MP_light(object):
6363

6464
class Ecloud(object):
6565
def __init__(self, L_ecloud, slicer, Dt_ref, pyecl_input_folder='./', flag_clean_slices=False,
66-
slice_by_slice_mode=False, space_charge_obj=None, MP_e_mass=m_e, MP_e_charge=-e, **kwargs):
66+
slice_by_slice_mode=False, space_charge_obj=None, **kwargs):
6767

68-
print 'PyECLOUD Version 6.7.2'
68+
print 'PyECLOUD Version 7.0.0'
6969

7070
# These git commands return the hash and the branch of the specified git directory.
7171
path_to_git = os.path.dirname(os.path.abspath(__file__)) +'/.git'
@@ -96,20 +96,13 @@ def __init__(self, L_ecloud, slicer, Dt_ref, pyecl_input_folder='./', flag_clean
9696

9797
(
9898
beamtim,
99-
MP_e,
100-
dynamics,
101-
impact_man,
102-
pyeclsaver,
103-
gas_ion_flag,
104-
resgasion,
105-
t_ion,
10699
spacech_ele,
107100
t_sc_ON,
108-
photoem_flag,
109-
phemiss,
110101
flag_presence_sec_beams,
111102
sec_beams_list,
112-
config_dict
103+
config_dict,
104+
flag_multiple_clouds,
105+
cloud_list
113106
) = init.read_input_files_and_init_components(pyecl_input_folder=pyecl_input_folder, skip_beam=True,
114107
skip_pyeclsaver=True, skip_spacech_ele=(space_charge_obj is not None),
115108
ignore_kwargs=extra_allowed_kwargs, **kwargs)
@@ -156,11 +149,29 @@ def __init__(self, L_ecloud, slicer, Dt_ref, pyecl_input_folder='./', flag_clean
156149

157150
spacech_ele.flag_decimate = False
158151

152+
if flag_multiple_clouds:
153+
raise ValueError('Multiple clouds not yet implemented in PyEC4PyHT!')
154+
else:
155+
cloud = cloud_list[0]
156+
157+
MP_e = cloud.MP_e
158+
dynamics = cloud.dynamics
159+
impact_man = cloud.impact_man
160+
pyeclsaver = cloud.pyeclsaver
161+
gas_ion_flag = cloud.gas_ion_flag
162+
resgasion = cloud.resgasion
163+
t_ion = cloud.t_ion
164+
photoem_flag = cloud.photoem_flag
165+
phemiss = cloud.phemiss
166+
159167
self.MP_e = MP_e
160168
self.dynamics = dynamics
161169
self.impact_man = impact_man
162170
self.spacech_ele = spacech_ele
163171

172+
self.gas_ion_flag = gas_ion_flag
173+
self.resgasion = resgasion
174+
164175
self.save_ele_distributions_last_track = False
165176
self.save_ele_potential_and_field = False
166177
self.save_ele_potential = False

PyEC4PyHT_fastion.py

Lines changed: 107 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#
88
# This file is part of the code:
99
#
10-
# PyECLOUD Version 6.7.2
10+
# PyECLOUD Version 7.0.0
1111
#
1212
#
1313
# Main author: Giovanni IADAROLA
@@ -62,29 +62,23 @@ class MP_light(object):
6262

6363
class Ecloud_fastion(Ecloud):
6464

65-
def __init__(self, L_ecloud, slicer, Dt_ref, MP_e_mass, MP_e_charge, pyecl_input_folder = './',
65+
def __init__(self, L_ecloud, slicer, Dt_ref, pyecl_input_folder = './',
6666
flag_clean_slices = False, slice_by_slice_mode = False, space_charge_obj = None,
6767
beam_monitor = None, include_cloud_sc = False, ionize_only_first_bunch = False, **kwargs):
6868

6969

7070
super(Ecloud_fastion, self).__init__(L_ecloud, slicer, Dt_ref, pyecl_input_folder = pyecl_input_folder,
7171
flag_clean_slices = flag_clean_slices, slice_by_slice_mode = slice_by_slice_mode,
72-
space_charge_obj = space_charge_obj, MP_e_mass = MP_e_mass,
73-
MP_e_charge = MP_e_charge, **kwargs)
72+
space_charge_obj = space_charge_obj, **kwargs)
7473

7574
self.beam_monitor = beam_monitor
76-
self.gas_ion_flag = kwargs['gas_ion_flag']
7775
self.include_cloud_sc = include_cloud_sc
7876
self.ionize_only_first_bunch = ionize_only_first_bunch
7977

8078
self.MP_e_field_state = self.spacech_ele.PyPICobj.get_state_object()
8179
self.MP_p_field_state = self.spacech_ele.PyPICobj.get_state_object()
8280

83-
if self.gas_ion_flag == 1:
84-
chamb = self.impact_man.chamb
85-
gas_ionization = residual_gas_ionization(kwargs['unif_frac'], kwargs['P_nTorr'], kwargs['sigma_ion_MBarn'],
86-
kwargs['Temp_K'], chamb, kwargs['E_init_ion'])
87-
self.gas_ionization = gas_ionization
81+
self.gas_ionization = self.resgasion
8882

8983

9084

@@ -112,7 +106,7 @@ def track(self, beam):
112106
# Only track over slices with particles
113107
filled_slices = np.where(slices.n_macroparticles_per_slice > 0)[0]
114108

115-
for i in filled_slices[::-1]:
109+
for i in xrange(slices.n_slices-1, -1, -1):
116110

117111
# select particles in the bunch
118112
ix = slices.particle_indices_of_slice(i)
@@ -163,112 +157,107 @@ def generate_twin_ecloud_with_shared_space_charge(self):
163157
#@profile
164158
def _track_single_slice(self, beam, ix, dz):
165159

166-
#pass
167-
if len(ix) > 0:
168-
169-
MP_e = self.MP_e
170-
dynamics = self.dynamics
171-
impact_man = self.impact_man
172-
spacech_ele = self.spacech_ele
173-
MP_e_state = self.MP_e_field_state
174-
MP_p_state = self.MP_p_field_state
175-
176-
dt = dz / (beam.beta * c)
177-
178-
# define substep
179-
if dt > self.Dt_ref:
180-
N_sub_steps = int(np.round(dt / self.Dt_ref))
181-
else:
182-
N_sub_steps = 1
183-
184-
Dt_substep = dt / N_sub_steps
185-
# print Dt_substep, N_sub_steps, dt
186-
187-
# beam particles
188-
MP_p = MP_light()
189-
MP_p.x_mp = beam.x[ix]
190-
MP_p.y_mp = beam.y[ix]
191-
MP_p.nel_mp = beam.x[ix] * 0. + beam.particlenumber_per_mp
192-
MP_p.N_mp = len(beam.x[ix])
193-
MP_p.charge = beam.charge
194-
195-
mean_x = np.mean(beam.x[ix])
196-
mean_y = np.mean(beam.y[ix])
197-
sigma_x = np.std(beam.x[ix])
198-
sigma_y = np.std(beam.y[ix])
199-
200-
if self.gas_ion_flag == 1:
201-
Np_bunch = MP_p.N_mp * beam.particlenumber_per_mp
202-
dz_bunch = dz
203-
lambda_bunch = Np_bunch
204-
dt_bunch = 1 / c
205-
MP_e = self.gas_ionization.generate(MP_e=MP_e, lambda_t=lambda_bunch, Dt=dt_bunch, sigmax=sigma_x,
206-
sigmay=sigma_y, x_beam_pos=mean_x, y_beam_pos=mean_y)
207-
if self.ionize_only_first_bunch:
208-
self.gas_ion_flag = 0
209-
210-
# scatter fields
211-
MP_e_state.scatter(MP_e.x_mp[0:MP_e.N_mp],MP_e.y_mp[0:MP_e.N_mp],MP_e.nel_mp[0:MP_e.N_mp], charge = MP_e.charge)
212-
MP_p_state.scatter(MP_p.x_mp[0:MP_p.N_mp],MP_p.y_mp[0:MP_p.N_mp],MP_p.nel_mp[0:MP_p.N_mp], charge = MP_p.charge)
213-
214-
# solve fields
215-
spacech_ele.PyPICobj.solve_states([MP_e_state, MP_p_state])
216-
217-
# gather fields
218-
Ex_sc_p, Ey_sc_p = MP_e_state.gather(MP_p.x_mp[0:MP_p.N_mp],MP_p.y_mp[0:MP_p.N_mp])
219-
Ex_n_beam, Ey_n_beam = MP_p_state.gather(MP_e.x_mp[0:MP_e.N_mp],MP_e.y_mp[0:MP_e.N_mp])
220-
221-
# kick cloud particles
222-
MP_e.vx_mp[:MP_e.N_mp] += Ex_n_beam * MP_e.charge / MP_e.mass / c
223-
MP_e.vy_mp[:MP_e.N_mp] += Ey_n_beam * MP_e.charge / MP_e.mass / c
224-
225-
# kick beam particles
226-
fact_kick = beam.charge / (beam.mass * beam.beta * beam.beta * beam.gamma * c * c) * self.L_ecloud
227-
beam.xp[ix] += fact_kick * Ex_sc_p
228-
beam.yp[ix] += fact_kick * Ey_sc_p
229-
230-
231-
# Total electric field on electrons
232-
if self.include_cloud_sc:
233-
Ex_sc_n, Ey_sc_n = MP_e_state.gather(MP_e.x_mp[0:MP_e.N_mp],MP_e.y_mp[0:MP_e.N_mp])
234-
Ex_n = Ex_sc_n
235-
Ey_n = Ey_sc_n
236-
else:
237-
Ex_n = MP_e.vx_mp[:MP_e.N_mp] * 0.
238-
Ey_n = Ex_n
239-
240-
# save position before motion step
241-
old_pos = MP_e.get_positions()
242-
243-
# motion electrons
244-
MP_e = dynamics.stepcustomDt(MP_e, Ex_n,Ey_n, Dt_substep=Dt_substep, N_sub_steps=N_sub_steps)
245-
246-
# impacts: backtracking and secondary emission
247-
MP_e = impact_man.backtrack_and_second_emiss(old_pos, MP_e)
248-
249-
250-
if self.save_ele_distributions_last_track:
251-
self.rho_ele_last_track.append(spacech_ele.rho.copy())
252-
#print 'Here'
253-
254-
if self.save_ele_potential_and_field:
255-
self.phi_ele_last_track.append(spacech_ele.phi.copy())
256-
self.Ex_ele_last_track.append(spacech_ele.efx.copy())
257-
self.Ey_ele_last_track.append(spacech_ele.efy.copy())
258-
259-
if self.save_ele_MP_position:
260-
self.x_MP_last_track.append(MP_e.x_mp.copy())
261-
self.y_MP_last_track.append(MP_e.y_mp.copy())
262-
263-
if self.save_ele_MP_velocity:
264-
self.vx_MP_last_track.append(MP_e.vx_mp.copy())
265-
self.vy_MP_last_track.append(MP_e.vy_mp.copy())
266-
267-
if self.save_ele_MP_size:
268-
self.nel_MP_last_track.append(MP_e.nel_mp.copy())
269-
270-
if self.save_ele_MP_position or self.save_ele_MP_velocity or self.save_ele_MP_size:
271-
self.N_MP_last_track.append(MP_e.N_mp)
160+
MP_e = self.MP_e
161+
dynamics = self.dynamics
162+
impact_man = self.impact_man
163+
spacech_ele = self.spacech_ele
164+
MP_e_state = self.MP_e_field_state
165+
MP_p_state = self.MP_p_field_state
166+
167+
dt = dz / (beam.beta * c)
168+
169+
# define substep
170+
if dt > self.Dt_ref:
171+
N_sub_steps = int(np.round(dt / self.Dt_ref))
172+
else:
173+
N_sub_steps = 1
174+
175+
Dt_substep = dt / N_sub_steps
176+
# print Dt_substep, N_sub_steps, dt
177+
178+
# beam particles
179+
MP_p = MP_light()
180+
MP_p.x_mp = beam.x[ix]
181+
MP_p.y_mp = beam.y[ix]
182+
MP_p.nel_mp = beam.x[ix] * 0. + beam.particlenumber_per_mp
183+
MP_p.N_mp = len(beam.x[ix])
184+
MP_p.charge = beam.charge
185+
186+
mean_x = np.mean(beam.x[ix])
187+
mean_y = np.mean(beam.y[ix])
188+
sigma_x = np.std(beam.x[ix])
189+
sigma_y = np.std(beam.y[ix])
272190

191+
if self.gas_ion_flag == 1:
192+
Np_bunch = MP_p.N_mp * beam.particlenumber_per_mp
193+
dz_bunch = dz
194+
lambda_bunch = Np_bunch
195+
dt_bunch = 1 / c
196+
MP_e = self.gas_ionization.generate(MP_e=MP_e, lambda_t=lambda_bunch, Dt=dt_bunch, sigmax=sigma_x,
197+
sigmay=sigma_y, x_beam_pos=mean_x, y_beam_pos=mean_y)
198+
if self.ionize_only_first_bunch:
199+
self.gas_ion_flag = 0
200+
201+
# scatter fields
202+
MP_e_state.scatter(MP_e.x_mp[0:MP_e.N_mp],MP_e.y_mp[0:MP_e.N_mp],MP_e.nel_mp[0:MP_e.N_mp], charge = MP_e.charge)
203+
MP_p_state.scatter(MP_p.x_mp[0:MP_p.N_mp],MP_p.y_mp[0:MP_p.N_mp],MP_p.nel_mp[0:MP_p.N_mp], charge = MP_p.charge)
204+
205+
# solve fields
206+
spacech_ele.PyPICobj.solve_states([MP_e_state, MP_p_state])
207+
208+
# gather fields
209+
Ex_sc_p, Ey_sc_p = MP_e_state.gather(MP_p.x_mp[0:MP_p.N_mp],MP_p.y_mp[0:MP_p.N_mp])
210+
Ex_n_beam, Ey_n_beam = MP_p_state.gather(MP_e.x_mp[0:MP_e.N_mp],MP_e.y_mp[0:MP_e.N_mp])
211+
212+
# kick cloud particles
213+
MP_e.vx_mp[:MP_e.N_mp] += Ex_n_beam * MP_e.charge / MP_e.mass / c
214+
MP_e.vy_mp[:MP_e.N_mp] += Ey_n_beam * MP_e.charge / MP_e.mass / c
215+
216+
# kick beam particles
217+
fact_kick = beam.charge / (beam.mass * beam.beta * beam.beta * beam.gamma * c * c) * self.L_ecloud
218+
beam.xp[ix] += fact_kick * Ex_sc_p
219+
beam.yp[ix] += fact_kick * Ey_sc_p
220+
221+
222+
# Total electric field on electrons
223+
if self.include_cloud_sc:
224+
Ex_sc_n, Ey_sc_n = MP_e_state.gather(MP_e.x_mp[0:MP_e.N_mp],MP_e.y_mp[0:MP_e.N_mp])
225+
Ex_n = Ex_sc_n
226+
Ey_n = Ey_sc_n
273227
else:
274-
pass
228+
Ex_n = MP_e.vx_mp[:MP_e.N_mp] * 0.
229+
Ey_n = Ex_n
230+
231+
# save position before motion step
232+
old_pos = MP_e.get_positions()
233+
234+
# motion electrons
235+
MP_e = dynamics.stepcustomDt(MP_e, Ex_n,Ey_n, Dt_substep=Dt_substep, N_sub_steps=N_sub_steps)
236+
237+
# impacts: backtracking and secondary emission
238+
MP_e = impact_man.backtrack_and_second_emiss(old_pos, MP_e)
239+
240+
241+
if self.save_ele_distributions_last_track:
242+
self.rho_ele_last_track.append(spacech_ele.rho.copy())
243+
#print 'Here'
244+
245+
if self.save_ele_potential_and_field:
246+
self.phi_ele_last_track.append(spacech_ele.phi.copy())
247+
self.Ex_ele_last_track.append(spacech_ele.efx.copy())
248+
self.Ey_ele_last_track.append(spacech_ele.efy.copy())
249+
250+
if self.save_ele_MP_position:
251+
self.x_MP_last_track.append(MP_e.x_mp.copy())
252+
self.y_MP_last_track.append(MP_e.y_mp.copy())
253+
254+
if self.save_ele_MP_velocity:
255+
self.vx_MP_last_track.append(MP_e.vx_mp.copy())
256+
self.vy_MP_last_track.append(MP_e.vy_mp.copy())
257+
258+
if self.save_ele_MP_size:
259+
self.nel_MP_last_track.append(MP_e.nel_mp.copy())
260+
261+
if self.save_ele_MP_position or self.save_ele_MP_velocity or self.save_ele_MP_size:
262+
self.N_MP_last_track.append(MP_e.N_mp)
263+

0 commit comments

Comments
 (0)