Skip to content

Commit 6c92659

Browse files
committed
Merge branch 'master' of https://github.com/like2000/PyHEADTAIL
2 parents 6c11ab7 + f6abb24 commit 6c92659

File tree

5 files changed

+85
-70
lines changed

5 files changed

+85
-70
lines changed

monitors/monitors.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,9 @@ def _write_data_to_file(self, bunch, arrays_dict):
380380
for quant in self.quantities_to_store:
381381
quant_values = getattr(bunch, quant)
382382
all_quantities[quant] = quant_values
383-
all_quantities.update(arrays_dict)
383+
384+
if arrays_dict is not None:
385+
all_quantities.update(arrays_dict)
384386

385387
for quant in all_quantities.keys():
386388
quant_values = all_quantities[quant]

particles/generators.py

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -409,19 +409,23 @@ class CutRFBucket6D(ParticleGenerator):
409409
the optics resp. TWISS parameters taken from a TransverseMap
410410
instance. The longitudinal phase space is initialised as a
411411
bi-gaussian with given sigma_z and sigma_dp which is then cut along
412-
the funciotn given by is_accepted which is typically the function
413-
is_in_separatrix of the rfbucket instance of the longitudinal map.
414-
To avoid bucket leakage and particle losses as a consequence of the
415-
unmatched initialisation, a margin / tolerance can be specified by
416-
the argument margin (in % of RFBucket.Hmax, 5% by default), so that
417-
particles will not be initialised too close to the separatrix. The
418-
boundary will in fact be given by the equihamiltonian with a value
419-
of margin*Hmax.
412+
the function given by is_accepted. The usual choices for
413+
is_accepted are either RFBucket.is_in_separatrix or
414+
RFBucket.is_accepted . The former strictly follows the separatrix
415+
of the bucket (the equihamiltonian with a value of 0), while with
416+
the latter, tighter boundaries can be used (equihamiltonian lying
417+
inside the RFBucket) as a result of which particles are not
418+
initialised too close to the separatrix. This option is usually
419+
preferred as it avoids bucket leakage and particle losses which may
420+
occur as a consequence of the unmatched initialisation. The
421+
RFBucket.is_accepted method must be created first however, by
422+
calling the RFBucket.make_is_accepted(margin) method with a certain
423+
value for the margin (in % of RFBucket.Hmax, 5% by default).
420424
'''
421425
def __init__(self, macroparticlenumber, intensity, charge, mass,
422426
circumference, gamma_reference,
423427
transverse_map, epsn_x, epsn_y,
424-
sigma_z, sigma_dp, is_accepted, margin=0.05,
428+
sigma_z, sigma_dp, is_accepted,
425429
*args, **kwargs):
426430
'''Uses the transverse_map to extract the optics parameters
427431
and the rf_bucket to match the longitudinal distribution.
@@ -433,7 +437,7 @@ def __init__(self, macroparticlenumber, intensity, charge, mass,
433437
self._rf_bucket_matcher = CutRFBucket2D(
434438
macroparticlenumber, intensity, charge, mass,
435439
circumference, gamma_reference,
436-
sigma_z, sigma_dp, is_accepted, margin, *args, **kwargs)
440+
sigma_z, sigma_dp, is_accepted, *args, **kwargs)
437441
super(CutRFBucket6D, self).__init__(
438442
macroparticlenumber, intensity, charge, mass, circumference,
439443
gamma_reference, HEADTAILcoords.coordinates, *args, **kwargs)
@@ -478,27 +482,29 @@ def distribute(self):
478482

479483

480484
class CutRFBucket2D(ParticleGenerator):
481-
'''
482-
For HEADTAIL style matching into RF bucket.
483-
The argument is_accepted takes a function (usually
484-
RFBucket.is_in_separatrix) defining the separatrix of the rf bucket.
485-
To avoid bucket leakage and particle losses as a consequence of the
486-
unmatched initialisation, a margin / tolerance can be specified by
487-
the argument margin (in % of RFBucket.Hmax, 5% by default), so that
488-
particles will not be initialised too close to the separatrix. The
489-
boundary will in fact be given by the equihamiltonian with a value
490-
of margin*Hmax.
485+
'''For HEADTAIL style matching into RF bucket.
486+
The argument is_accepted takes a function (i.e. reference to a
487+
function). The usual choices are RFBucket.is_in_separatrix or
488+
RFBucket.is_accepted . The former strictly follows the separatrix
489+
of the bucket (the equihamiltonian with a value of 0), while with
490+
the latter, tighter boundaries can be used (equihamiltonian lying
491+
inside the RFBucket) as a result of which particles are not
492+
initialised too close to the separatrix. This option is usually
493+
preferred as it avoids bucket leakage and particle losses which may
494+
occur as a consequence of the unmatched initialisation.
495+
The RFBucket.is_accepted method must be created first however, by
496+
calling the RFBucket.make_is_accepted(margin) method with a certain
497+
value for the margin (in % of RFBucket.Hmax, 5% by default).
491498
492499
BY KEVIN: NEEDS TO BE CLEANED UP BY ADRIAN!
493500
'''
494501
def __init__(self, macroparticlenumber, intensity, charge, mass,
495502
circumference, gamma_reference, sigma_z, sigma_dp,
496-
is_accepted, margin=0.05, *args, **kwargs):
503+
is_accepted, *args, **kwargs):
497504

498505
self.sigma_z = sigma_z
499506
self.sigma_dp = sigma_dp
500507
self.is_accepted = is_accepted
501-
self.margin = margin
502508

503509
super(CutRFBucket2D, self).__init__(
504510
macroparticlenumber, intensity, charge, mass, circumference,
@@ -514,12 +520,12 @@ def distribute(self):
514520

515521
def _redistribute(self, z, dp):
516522

517-
mask_out = ~self.is_accepted(z, dp, self.margin)
523+
mask_out = ~self.is_accepted(z, dp)
518524
while mask_out.any():
519525
n_gen = np.sum(mask_out)
520526
z[mask_out] = normal(0, self.sigma_z, n_gen)
521527
dp[mask_out] = normal(0, self.sigma_dp, n_gen)
522-
mask_out = ~self.is_accepted(z, dp, self.margin)
528+
mask_out = ~self.is_accepted(z, dp)
523529
self.prints('Reiterate on non-accepted particles')
524530

525531

testing/interactive-tests/GeneratorTest.ipynb

Lines changed: 21 additions & 29 deletions
Large diffs are not rendered by default.

testing/interactive-tests/MonitorTest.ipynb

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"metadata": {
33
"name": "",
4-
"signature": "sha256:dfff2f627b552921077821c4363a152f9af9e974b4c53e6434e2d24a4b077c40"
4+
"signature": "sha256:40730948c653f14f34c07a1fed2c8a8d06c79f2381ae5f9084b77273c9fcb345"
55
},
66
"nbformat": 3,
77
"nbformat_minor": 0,
@@ -44,7 +44,7 @@
4444
"output_type": "stream",
4545
"stream": "stdout",
4646
"text": [
47-
"PyHEADTAIL v1.0.0\n",
47+
"PyHEADTAIL v1.0.4\n",
4848
"\n",
4949
"\n"
5050
]
@@ -95,7 +95,6 @@
9595
" for key in particledata[step].keys():\n",
9696
" _[:] = particledata[step][key][:]\n",
9797
" \n",
98-
" \n",
9998
" bunchdata.close()\n",
10099
" slicedata.close()\n",
101100
" particledata.close()\n",
@@ -149,7 +148,7 @@
149148
"language": "python",
150149
"metadata": {},
151150
"outputs": [],
152-
"prompt_number": 3
151+
"prompt_number": 12
153152
},
154153
{
155154
"cell_type": "code",
@@ -176,7 +175,7 @@
176175
"language": "python",
177176
"metadata": {},
178177
"outputs": [],
179-
"prompt_number": 4
178+
"prompt_number": 9
180179
},
181180
{
182181
"cell_type": "heading",
@@ -211,7 +210,7 @@
211210
"language": "python",
212211
"metadata": {},
213212
"outputs": [],
214-
"prompt_number": 5
213+
"prompt_number": 10
215214
},
216215
{
217216
"cell_type": "code",
@@ -240,13 +239,17 @@
240239
" write_buffer_every=20)\n",
241240
"particle_monitor = ParticleMonitor(filename=particle_filename, stride=10, parameters_dict={'Q_x': Q_x})\n",
242241
"\n",
242+
"arrays_dict = {}\n",
243243
"map_ = trans_map\n",
244244
"for i in xrange(n_turns):\n",
245245
" for m_ in map_:\n",
246246
" m_.track(bunch)\n",
247247
" bunch_monitor.dump(bunch)\n",
248248
" slice_monitor.dump(bunch)\n",
249-
" particle_monitor.dump(bunch)\n",
249+
" \n",
250+
" slice_set_pmon = bunch.get_slices(unibin_slicer)\n",
251+
" arrays_dict.update({'slidx': slice_set_pmon.slice_index_of_particle, 'zz': bunch.z})\n",
252+
" particle_monitor.dump(bunch, arrays_dict)\n",
250253
"\n",
251254
"read_all_data(bunch_filename, slice_filename, particle_filename)\n",
252255
"read_n_plot_data(bunch_filename, slice_filename, particle_filename)"
@@ -258,11 +261,11 @@
258261
"output_type": "stream",
259262
"stream": "stdout",
260263
"text": [
261-
"0.0580668146353\n"
264+
"0.0576953432278\n"
262265
]
263266
}
264267
],
265-
"prompt_number": 8
268+
"prompt_number": 13
266269
},
267270
{
268271
"cell_type": "code",

trackers/rf_bucket.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -261,14 +261,26 @@ def p_max(self, zc):
261261
f = self.equihamiltonian(zc)
262262
return np.amax(f(self.zs))
263263

264-
def is_in_separatrix(self, z, dp, margin):
265-
"""
266-
Returns boolean whether this coordinate is located inside the
267-
separatrix. A margin, in % of self.Hmax, can be specified so
268-
that the separatrix is not strictly followed.
269-
"""
264+
def is_in_separatrix(self, z, dp):
265+
""" Returns boolean whether the coordinate (z, dp) is located
266+
strictly inside the separatrix. """
270267
return np.logical_and(np.logical_and(self.zleft < z, z < self.zright),
271-
self.hamiltonian(z, dp) > margin * self.Hmax)
268+
self.hamiltonian(z, dp) > 0)
269+
270+
def make_is_accepted(self, margin):
271+
""" Returns the function is_accepted(z, dp) definining the
272+
equihamiltonian with a value of margin*self.Hmax . For margin 0,
273+
the returned is_accepted(z, dp) function is equivalent to
274+
self.is_in_separatrix(z, dp). """
275+
276+
def is_accepted(z, dp):
277+
""" Returns boolean whether the coordinate (z, dp) is
278+
located inside the equihamiltonian defined by
279+
margin*self.Hmax . """
280+
return np.logical_and(
281+
np.logical_and(self.zleft < z, z < self.zright),
282+
self.hamiltonian(z, dp) > margin * self.Hmax)
283+
return is_accepted
272284

273285
def bucket_area(self):
274286
xmin, xmax = self.zleft, self.zright

0 commit comments

Comments
 (0)