Skip to content

Commit fc821c6

Browse files
committed
Generate n_segments+1 entries for optics functions!
Satisfies the documentation requirements by TransverseMap and makes sure that D_x[n_segments+1] is fine in special cases when the longitudinal focussing is to be put at the end (and it tries to address the last index n_segments+1). Fixes occurring problems with Adrian and Kevin's simulations.
1 parent 3cdb230 commit fc821c6

File tree

2 files changed

+72
-64
lines changed

2 files changed

+72
-64
lines changed

CERNmachines.py

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ def __init__(self, *args, **kwargs):
3939
self.app_y = 0.0000e-9
4040
self.app_xy = 0
4141

42-
self.alpha_x = 0 * np.ones(self.n_segments)
43-
self.beta_x = self.circumference/(2*np.pi*self.Q_x) * np.ones(self.n_segments)
44-
self.D_x = 0 * np.ones(self.n_segments)
45-
self.alpha_y = 0 * np.ones(self.n_segments)
46-
self.beta_y = self.circumference/(2*np.pi*self.Q_y) * np.ones(self.n_segments)
47-
self.D_y = 0 * np.ones(self.n_segments)
42+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
43+
self.beta_x = self.circumference/(2*np.pi*self.Q_x) * np.ones(self.n_segments + 1)
44+
self.D_x = 0 * np.ones(self.n_segments + 1)
45+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
46+
self.beta_y = self.circumference/(2*np.pi*self.Q_y) * np.ones(self.n_segments + 1)
47+
self.D_y = 0 * np.ones(self.n_segments + 1)
4848

4949
self.alpha = 0.06
5050
self.h1 = 1
@@ -73,12 +73,12 @@ def __init__(self, *args, **kwargs):
7373
self.app_y = 0.0000e-9
7474
self.app_xy = 0
7575

76-
self.alpha_x = 0 * np.ones(self.n_segments)
77-
self.beta_x = self.circumference/(2*np.pi*self.Q_x) * np.ones(self.n_segments)
78-
self.D_x = 0 * np.ones(self.n_segments)
79-
self.alpha_y = 0 * np.ones(self.n_segments)
80-
self.beta_y = self.circumference/(2*np.pi*self.Q_y) * np.ones(self.n_segments)
81-
self.D_y = 0 * np.ones(self.n_segments)
76+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
77+
self.beta_x = self.circumference/(2*np.pi*self.Q_x) * np.ones(self.n_segments + 1)
78+
self.D_x = 0 * np.ones(self.n_segments + 1)
79+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
80+
self.beta_y = self.circumference/(2*np.pi*self.Q_y) * np.ones(self.n_segments + 1)
81+
self.D_y = 0 * np.ones(self.n_segments + 1)
8282

8383
self.alpha = 0.06
8484
self.h1 = 1
@@ -107,12 +107,12 @@ def __init__(self, *args, **kwargs):
107107
self.app_y = 0.0000e-9
108108
self.app_xy = 0
109109

110-
self.alpha_x = 0 * np.ones(self.n_segments)
111-
self.beta_x = self.circumference/(2*np.pi*self.Q_x) * np.ones(self.n_segments)
112-
self.D_x = 0 * np.ones(self.n_segments)
113-
self.alpha_y = 0 * np.ones(self.n_segments)
114-
self.beta_y = self.circumference/(2*np.pi*self.Q_y) * np.ones(self.n_segments)
115-
self.D_y = 0 * np.ones(self.n_segments)
110+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
111+
self.beta_x = self.circumference/(2*np.pi*self.Q_x) * np.ones(self.n_segments + 1)
112+
self.D_x = 0 * np.ones(self.n_segments + 1)
113+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
114+
self.beta_y = self.circumference/(2*np.pi*self.Q_y) * np.ones(self.n_segments + 1)
115+
self.D_y = 0 * np.ones(self.n_segments + 1)
116116

117117
self.alpha = 0.06
118118
self.h1 = 1
@@ -153,12 +153,12 @@ def __init__(self, *args, **kwargs):
153153

154154
self.gamma = 27.7
155155

156-
self.alpha_x = 0 * np.ones(self.n_segments)
157-
self.beta_x = 54.6 * np.ones(self.n_segments)
158-
self.D_x = 0 * np.ones(self.n_segments)
159-
self.alpha_y = 0 * np.ones(self.n_segments)
160-
self.beta_y = 54.6 * np.ones(self.n_segments)
161-
self.D_y = 0 * np.ones(self.n_segments)
156+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
157+
self.beta_x = 54.6 * np.ones(self.n_segments + 1)
158+
self.D_x = 0 * np.ones(self.n_segments + 1)
159+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
160+
self.beta_y = 54.6 * np.ones(self.n_segments + 1)
161+
self.D_y = 0 * np.ones(self.n_segments + 1)
162162

163163
self.Q_x = 20.13
164164
self.Q_y = 20.18
@@ -184,12 +184,12 @@ def __init__(self, *args, **kwargs):
184184

185185
self.gamma = 27.7
186186

187-
self.alpha_x = 0 * np.ones(self.n_segments)
188-
self.beta_x = 42. * np.ones(self.n_segments)
189-
self.D_x = 0 * np.ones(self.n_segments)
190-
self.alpha_y = 0 * np.ones(self.n_segments)
191-
self.beta_y = 42. * np.ones(self.n_segments)
192-
self.D_y = 0 * np.ones(self.n_segments)
187+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
188+
self.beta_x = 42. * np.ones(self.n_segments + 1)
189+
self.D_x = 0 * np.ones(self.n_segments + 1)
190+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
191+
self.beta_y = 42. * np.ones(self.n_segments + 1)
192+
self.D_y = 0 * np.ones(self.n_segments + 1)
193193

194194
self.Q_x = 26.13
195195
self.Q_y = 26.18
@@ -215,12 +215,12 @@ def __init__(self, *args, **kwargs):
215215

216216
self.gamma = np.sqrt((450e9*e/(m_p*c**2))**2+1)
217217

218-
self.alpha_x = 0 * np.ones(self.n_segments)
219-
self.beta_x = 54.6 * np.ones(self.n_segments)
220-
self.D_x = 0 * np.ones(self.n_segments)
221-
self.alpha_y = 0 * np.ones(self.n_segments)
222-
self.beta_y = 54.6 * np.ones(self.n_segments)
223-
self.D_y = 0 * np.ones(self.n_segments)
218+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
219+
self.beta_x = 54.6 * np.ones(self.n_segments + 1)
220+
self.D_x = 0 * np.ones(self.n_segments + 1)
221+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
222+
self.beta_y = 54.6 * np.ones(self.n_segments + 1)
223+
self.D_y = 0 * np.ones(self.n_segments + 1)
224224

225225
self.Q_x = 20.13
226226
self.Q_y = 20.18
@@ -272,12 +272,12 @@ def __init__(self, *args, **kwargs):
272272
self.Q_x = 64.28
273273
self.Q_y = 59.31
274274

275-
self.alpha_x = 0 * np.ones(self.n_segments)
276-
self.beta_x = self.R/self.Q_x * np.ones(self.n_segments)
277-
self.D_x = 0 * np.ones(self.n_segments)
278-
self.alpha_y = 0 * np.ones(self.n_segments)
279-
self.beta_y = self.R/self.Q_y * np.ones(self.n_segments)
280-
self.D_y = 0 * np.ones(self.n_segments)
275+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
276+
self.beta_x = self.R/self.Q_x * np.ones(self.n_segments + 1)
277+
self.D_x = 0 * np.ones(self.n_segments + 1)
278+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
279+
self.beta_y = self.R/self.Q_y * np.ones(self.n_segments + 1)
280+
self.D_y = 0 * np.ones(self.n_segments + 1)
281281

282282
self.Qp_x = 0
283283
self.Qp_y = 0
@@ -306,12 +306,12 @@ def __init__(self, *args, **kwargs):
306306
self.Q_x = 64.31
307307
self.Q_y = 59.32
308308

309-
self.alpha_x = 0 * np.ones(self.n_segments)
310-
self.beta_x = self.R/self.Q_x * np.ones(self.n_segments)
311-
self.D_x = 0 * np.ones(self.n_segments)
312-
self.alpha_y = 0 * np.ones(self.n_segments)
313-
self.beta_y = self.R/self.Q_y * np.ones(self.n_segments)
314-
self.D_y = 0 * np.ones(self.n_segments)
309+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
310+
self.beta_x = self.R/self.Q_x * np.ones(self.n_segments + 1)
311+
self.D_x = 0 * np.ones(self.n_segments + 1)
312+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
313+
self.beta_y = self.R/self.Q_y * np.ones(self.n_segments + 1)
314+
self.D_y = 0 * np.ones(self.n_segments + 1)
315315

316316
self.Qp_x = 0
317317
self.Qp_y = 0
@@ -360,12 +360,12 @@ def __init__(self, *args, **kwargs):
360360
self.Q_x = 62.31
361361
self.Q_y = 60.32
362362

363-
self.alpha_x = 0 * np.ones(self.n_segments)
364-
self.beta_x = self.R/self.Q_x * np.ones(self.n_segments)
365-
self.D_x = 0 * np.ones(self.n_segments)
366-
self.alpha_y = 0 * np.ones(self.n_segments)
367-
self.beta_y = self.R/self.Q_y * np.ones(self.n_segments)
368-
self.D_y = 0 * np.ones(self.n_segments)
363+
self.alpha_x = 0 * np.ones(self.n_segments + 1)
364+
self.beta_x = self.R/self.Q_x * np.ones(self.n_segments + 1)
365+
self.D_x = 0 * np.ones(self.n_segments + 1)
366+
self.alpha_y = 0 * np.ones(self.n_segments + 1)
367+
self.beta_y = self.R/self.Q_y * np.ones(self.n_segments + 1)
368+
self.D_y = 0 * np.ones(self.n_segments + 1)
369369

370370
self.Qp_x = 0
371371
self.Qp_y = 0

machines.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ def __init__(self, *args, **kwargs):
3030
'''
3131
self.chromaticity_on = kwargs.pop('chromaticity_on', True)
3232
self.amplitude_detuning_on = kwargs.pop('amplitude_detuning_on', True)
33+
34+
if not hasattr(self, 'longitudinal_focusing'):
35+
self.longitudinal_focusing = kwargs.pop('longitudinal_focusing')
36+
if self.longitudinal_focusing not in ['linear', 'non-linear']:
37+
raise ValueError('longitudinal_focusing not recognized!!!')
38+
3339
for attr in kwargs.keys():
3440
if kwargs[attr] is not None:
3541
self.prints('Synchrotron init. From kwargs: %s = %s'
@@ -121,7 +127,6 @@ def track(self, bunch, verbose=False):
121127

122128
def create_transverse_map(self, chromaticity_on=True,
123129
amplitude_detuning_on=True):
124-
125130
detuners = []
126131
if chromaticity_on:
127132
detuners.append(Chromaticity(self.Qp_x, self.Qp_y))
@@ -137,7 +142,6 @@ def create_transverse_map(self, chromaticity_on=True,
137142
self.Q_x, self.Q_y, *detuners)
138143

139144
def create_longitudinal_map(self, one_turn_map_insert_idx=0):
140-
141145
if self.longitudinal_focusing == 'linear':
142146
self.longitudinal_map = LinearMap(
143147
[self.alpha],
@@ -154,17 +158,16 @@ def create_longitudinal_map(self, one_turn_map_insert_idx=0):
154158
D_y=self.D_y[one_turn_map_insert_idx]
155159
)
156160
else:
157-
raise ValueError('ERROR: unknown focusing',
158-
self.longitudinal_focusing)
161+
raise NotImplementedError(
162+
'Something wrong with self.longitudinal_focusing')
159163

160164
def generate_6D_Gaussian_bunch(self, n_macroparticles, intensity,
161165
epsn_x, epsn_y, sigma_z):
162-
'''
163-
Generates a 6D Gaussian distribution of particles which is
166+
'''Generate a 6D Gaussian distribution of particles which is
164167
transversely matched to the Synchrotron. Longitudinally, the
165168
distribution is matched only in terms of linear focusing.
166169
For a non-linear bucket, the Gaussian distribution is cut along
167-
the separatrix (with some margin) and will gradually filament
170+
the separatrix (with some margin). It will gradually filament
168171
into the bucket. This will change the specified bunch length.
169172
'''
170173
if self.longitudinal_focusing == 'linear':
@@ -173,7 +176,8 @@ def generate_6D_Gaussian_bunch(self, n_macroparticles, intensity,
173176
check_inside_bucket = self.longitudinal_map.get_bucket(
174177
gamma=self.gamma).make_is_accepted(margin=0.05)
175178
else:
176-
raise ValueError('Longitudinal_focusing not recognized!!!')
179+
raise NotImplementedError(
180+
'Something wrong with self.longitudinal_focusing')
177181

178182
beta_z = np.abs(self.eta)*self.circumference/2./np.pi/self.Q_s
179183
sigma_dp = sigma_z/beta_z
@@ -202,15 +206,18 @@ def generate_6D_Gaussian_bunch(self, n_macroparticles, intensity,
202206
def generate_6D_Gaussian_bunch_matched(
203207
self, n_macroparticles, intensity, epsn_x, epsn_y,
204208
sigma_z=None, epsn_z=None):
205-
'''
206-
Generates a 6D Gaussian distribution of particles which is
209+
'''Generate a 6D Gaussian distribution of particles which is
207210
transversely as well as longitudinally matched.
208211
The distribution is found iteratively to exactly yield the
209212
given bunch length while at the same time being stationary in
210213
the non-linear bucket. Thus, the bunch length should amount
211214
to the one specificed and should not change significantly
212215
during the synchrotron motion.
216+
217+
Requires self.longitudinal_focusing == 'non-linear'
218+
for the bucket.
213219
'''
220+
assert self.longitudinal_focusing == 'non-linear'
214221
epsx_geo = epsn_x/self.betagamma
215222
epsy_geo = epsn_y/self.betagamma
216223

@@ -231,3 +238,4 @@ def generate_6D_Gaussian_bunch_matched(
231238
).generate()
232239

233240
return bunch
241+

0 commit comments

Comments
 (0)