xcoll 0.5.9__py3-none-any.whl → 0.5.11__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of xcoll might be problematic. Click here for more details.
- xcoll/beam_elements/base.py +40 -9
- xcoll/colldb.py +164 -176
- xcoll/general.py +1 -1
- xcoll/initial_distribution.py +8 -2
- xcoll/line_tools.py +6 -6
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/METADATA +4 -4
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/RECORD +10 -13
- xcoll/beam_elements/__init__.py.orig +0 -32
- xcoll/colldb.py.orig +0 -654
- xcoll/initial_distribution.py.orig +0 -224
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/LICENSE +0 -0
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/NOTICE +0 -0
- {xcoll-0.5.9.dist-info → xcoll-0.5.11.dist-info}/WHEEL +0 -0
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
# copyright ############################### #
|
|
2
|
-
# This file is part of the Xcoll package. #
|
|
3
|
-
# Copyright (c) CERN, 2024. #
|
|
4
|
-
# ######################################### #
|
|
5
|
-
|
|
6
|
-
import numpy as np
|
|
7
|
-
from warnings import warn
|
|
8
|
-
|
|
9
|
-
import xtrack as xt
|
|
10
|
-
import xobjects as xo
|
|
11
|
-
import xpart as xp
|
|
12
|
-
|
|
13
|
-
<<<<<<< HEAD
|
|
14
|
-
from .beam_elements import _all_collimator_classes, EverestCrystal, FlukaCollimator
|
|
15
|
-
=======
|
|
16
|
-
from .beam_elements import collimator_classes, EverestCrystal
|
|
17
|
-
>>>>>>> release/v0.6.0
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def generate_pencil_on_collimator(line, name, num_particles, *, side='+-', pencil_spread=1e-6,
|
|
21
|
-
impact_parameter=0, sigma_z=7.61e-2, twiss=None, longitudinal=None,
|
|
22
|
-
longitudinal_betatron_cut=None, tw=None, **kwargs):
|
|
23
|
-
"""
|
|
24
|
-
Generate a pencil beam on a collimator.
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
if not line._has_valid_tracker():
|
|
28
|
-
raise ValueError("Please build tracker before generating pencil distribution!")
|
|
29
|
-
|
|
30
|
-
coll = line[name]
|
|
31
|
-
|
|
32
|
-
if not isinstance(coll, tuple(collimator_classes)):
|
|
33
|
-
raise ValueError("Need to provide a valid collimator!")
|
|
34
|
-
|
|
35
|
-
if coll.optics is None:
|
|
36
|
-
raise ValueError("Need to assign optics to collimators before generating pencil distribution!")
|
|
37
|
-
|
|
38
|
-
num_particles = int(num_particles)
|
|
39
|
-
if len(line.get_elements_of_type(FlukaCollimator)[0]) > 0:
|
|
40
|
-
kwargs.setdefault('_capacity', 2*num_particles)
|
|
41
|
-
|
|
42
|
-
if coll.side == 'left':
|
|
43
|
-
side = '+'
|
|
44
|
-
if coll.side == 'right':
|
|
45
|
-
side = '-'
|
|
46
|
-
|
|
47
|
-
# Define the plane
|
|
48
|
-
angle = coll.angle
|
|
49
|
-
if abs(np.mod(angle-90,180)-90) < 1e-6:
|
|
50
|
-
plane = 'x'
|
|
51
|
-
transv_plane = 'y'
|
|
52
|
-
elif abs(np.mod(angle,180)-90) < 1e-6:
|
|
53
|
-
plane = 'y'
|
|
54
|
-
transv_plane = 'x'
|
|
55
|
-
else:
|
|
56
|
-
raise NotImplementedError("Pencil beam on a skew collimator not yet supported!")
|
|
57
|
-
|
|
58
|
-
if tw is not None:
|
|
59
|
-
warn("The argument tw is deprecated. Please use twiss instead.", FutureWarning)
|
|
60
|
-
if twiss is None:
|
|
61
|
-
twiss = tw
|
|
62
|
-
|
|
63
|
-
if twiss is None:
|
|
64
|
-
twiss = line.twiss()
|
|
65
|
-
|
|
66
|
-
# Is it converging or diverging? # TODO: This might change with a tilt!!!!!!
|
|
67
|
-
is_converging = twiss[f'alf{plane}', name] > 0
|
|
68
|
-
print(f"Collimator {name} is {'con' if is_converging else 'di'}verging.")
|
|
69
|
-
|
|
70
|
-
beam_sizes = twiss.get_beam_covariance(nemitt_x=coll.nemitt_x, nemitt_y=coll.nemitt_y)
|
|
71
|
-
if is_converging:
|
|
72
|
-
# pencil at front of jaw
|
|
73
|
-
sigma = beam_sizes.rows[name:f'{name}>>1'][f'sigma_{plane}'][0]
|
|
74
|
-
sigma_transv = beam_sizes.rows[name:f'{name}>>1'][f'sigma_{transv_plane}'][0]
|
|
75
|
-
tw_at_s = twiss.rows[name]
|
|
76
|
-
at_element = name
|
|
77
|
-
else:
|
|
78
|
-
# pencil at back of jaw
|
|
79
|
-
sigma = beam_sizes.rows[name:f'{name}>>1'][f'sigma_{plane}'][1]
|
|
80
|
-
sigma_transv = beam_sizes.rows[name:f'{name}>>1'][f'sigma_{transv_plane}'][1]
|
|
81
|
-
tw_at_s = twiss.rows[f'{name}>>1']
|
|
82
|
-
at_element = line.element_names[line.element_names.index(name)+1]
|
|
83
|
-
|
|
84
|
-
dr_sigmas = pencil_spread/sigma
|
|
85
|
-
|
|
86
|
-
# Generate 4D coordinates
|
|
87
|
-
# TODO: there is some looping in the calculation here and in xpart. Can it be improved?
|
|
88
|
-
if side == '+-':
|
|
89
|
-
num_plus = int(num_particles/2)
|
|
90
|
-
num_min = int(num_particles - num_plus)
|
|
91
|
-
coords_plus = _generate_4D_pencil_one_jaw(line, name, num_plus, plane, '+', impact_parameter, dr_sigmas, at_element, is_converging, tw_at_s)
|
|
92
|
-
coords_min = _generate_4D_pencil_one_jaw(line, name, num_min, plane, '-', impact_parameter, dr_sigmas, at_element, is_converging, tw_at_s)
|
|
93
|
-
coords = [ [*c_plus, *c_min] for c_plus, c_min in zip(coords_plus, coords_min)]
|
|
94
|
-
else:
|
|
95
|
-
coords = _generate_4D_pencil_one_jaw(line, name, num_particles, plane, side, impact_parameter, dr_sigmas, at_element, is_converging, tw_at_s)
|
|
96
|
-
pencil = coords[0]
|
|
97
|
-
p_pencil = coords[1]
|
|
98
|
-
transverse_norm = coords[2]
|
|
99
|
-
p_transverse_norm = coords[3]
|
|
100
|
-
|
|
101
|
-
# Longitudinal plane
|
|
102
|
-
# TODO: make this more general, make this better
|
|
103
|
-
if longitudinal is None:
|
|
104
|
-
delta = 0
|
|
105
|
-
zeta = 0
|
|
106
|
-
elif longitudinal == 'matched_dispersion':
|
|
107
|
-
raise NotImplementedError
|
|
108
|
-
# if longitudinal_betatron_cut is None:
|
|
109
|
-
# cut = 0
|
|
110
|
-
# else:
|
|
111
|
-
# cut = np.random.uniform(-longitudinal_betatron_cut, longitudinal_betatron_cut,
|
|
112
|
-
# num_particles)
|
|
113
|
-
# delta = generate_delta_from_dispersion(line, name, plane=plane, position_mm=pencil,
|
|
114
|
-
# nemitt_x=nemitt_x, nemitt_y=nemitt_y, twiss=tw,
|
|
115
|
-
# betatron_cut=cut, match_at_front=is_converging)
|
|
116
|
-
# zeta = 0
|
|
117
|
-
elif longitudinal == 'bucket':
|
|
118
|
-
zeta, delta = xp.generate_longitudinal_coordinates(
|
|
119
|
-
num_particles=num_particles, distribution='gaussian', sigma_z=sigma_z, line=line
|
|
120
|
-
)
|
|
121
|
-
elif not hasattr(longitudinal, '__iter__'):
|
|
122
|
-
raise ValueError
|
|
123
|
-
elif len(longitudinal) != 2:
|
|
124
|
-
raise ValueError
|
|
125
|
-
elif isinstance(longitudinal, str):
|
|
126
|
-
raise ValueError
|
|
127
|
-
elif isinstance(longitudinal, dict):
|
|
128
|
-
zeta = longitudinal['zeta']
|
|
129
|
-
delta = longitudinal['delta']
|
|
130
|
-
else:
|
|
131
|
-
zeta = longitudinal[0]
|
|
132
|
-
delta = longitudinal[1]
|
|
133
|
-
|
|
134
|
-
# Build the particles
|
|
135
|
-
if plane == 'x':
|
|
136
|
-
part = xp.build_particles(
|
|
137
|
-
x=pencil, px=p_pencil, y_norm=transverse_norm, py_norm=p_transverse_norm,
|
|
138
|
-
zeta=zeta, delta=delta, nemitt_x=coll.nemitt_x, nemitt_y=coll.nemitt_y,
|
|
139
|
-
line=line, at_element=at_element, _context=coll._buffer.context, **kwargs
|
|
140
|
-
)
|
|
141
|
-
else:
|
|
142
|
-
part = xp.build_particles(
|
|
143
|
-
x_norm=transverse_norm, px_norm=p_transverse_norm, y=pencil, py=p_pencil,
|
|
144
|
-
zeta=zeta, delta=delta, nemitt_x=coll.nemitt_x, nemitt_y=coll.nemitt_y,
|
|
145
|
-
line=line, at_element=at_element, _context=coll._buffer.context, **kwargs
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
part._init_random_number_generator()
|
|
149
|
-
|
|
150
|
-
if not is_converging:
|
|
151
|
-
dri = xt.Drift(length=-coll.length)
|
|
152
|
-
dri.track(part)
|
|
153
|
-
part.start_tracking_at_element -= 1
|
|
154
|
-
part.at_element -= 1
|
|
155
|
-
|
|
156
|
-
return part
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
def generate_delta_from_dispersion(line, at_element, *, plane, position_mm, nemitt_x, nemitt_y,
|
|
160
|
-
twiss=None, betatron_cut=0, match_at_front=True):
|
|
161
|
-
if line.tracker is None:
|
|
162
|
-
raise ValueError("Need to build tracker first!")
|
|
163
|
-
if not hasattr(betatron_cut, '__iter__'):
|
|
164
|
-
if hasattr(position_mm, '__iter__'):
|
|
165
|
-
betatron_cut = np.full_like(position_mm, betatron_cut)
|
|
166
|
-
elif not hasattr(position_mm, '__iter__'):
|
|
167
|
-
position_mm = np.full_like(betatron_cut, position_mm)
|
|
168
|
-
elif len(position_mm) != len(betatron_cut):
|
|
169
|
-
raise ValueError
|
|
170
|
-
if plane not in ['x', 'y']:
|
|
171
|
-
raise ValueError("The variable 'plane' needs to be either 'x' or 'y'!")
|
|
172
|
-
|
|
173
|
-
if twiss is None:
|
|
174
|
-
twiss = line.twiss()
|
|
175
|
-
|
|
176
|
-
beam_sizes = twiss.get_beam_covariance(nemitt_x=nemitt_x, nemitt_y=nemitt_y)
|
|
177
|
-
beam_sizes = beam_sizes.rows[at_element:f'{at_element}>>1'][f'sigma_{plane}']
|
|
178
|
-
sigma = beam_sizes[0] if match_at_front else beam_sizes[1]
|
|
179
|
-
delta = (position_mm - betatron_cut*sigma - twiss.rows[at_element][plane])
|
|
180
|
-
delta /= twiss.rows[at_element][f'd{plane}']
|
|
181
|
-
|
|
182
|
-
return delta
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
def _generate_4D_pencil_one_jaw(line, name, num_particles, plane, side, impact_parameter,
|
|
186
|
-
dr_sigmas, at_element, is_converging, tw_at_s=None):
|
|
187
|
-
coll = line[name]
|
|
188
|
-
|
|
189
|
-
if side == '+':
|
|
190
|
-
if is_converging:
|
|
191
|
-
if isinstance(coll, EverestCrystal):
|
|
192
|
-
pencil_pos = coll.jaw_U + impact_parameter
|
|
193
|
-
else:
|
|
194
|
-
pencil_pos = coll.jaw_LU + impact_parameter
|
|
195
|
-
else:
|
|
196
|
-
if isinstance(coll, EverestCrystal):
|
|
197
|
-
pencil_pos = coll.jaw_D - impact_parameter
|
|
198
|
-
else:
|
|
199
|
-
pencil_pos = coll.jaw_LD + impact_parameter
|
|
200
|
-
elif side == '-':
|
|
201
|
-
if is_converging:
|
|
202
|
-
if isinstance(coll, EverestCrystal):
|
|
203
|
-
pencil_pos = coll.jaw_U - impact_parameter
|
|
204
|
-
else:
|
|
205
|
-
pencil_pos = coll.jaw_RU - impact_parameter
|
|
206
|
-
else:
|
|
207
|
-
if isinstance(coll, EverestCrystal):
|
|
208
|
-
pencil_pos = coll.jaw_D + impact_parameter
|
|
209
|
-
else:
|
|
210
|
-
pencil_pos = coll.jaw_RD - impact_parameter
|
|
211
|
-
|
|
212
|
-
# Collimator plane: generate pencil distribution
|
|
213
|
-
pencil, p_pencil = xp.generate_2D_pencil_with_absolute_cut(
|
|
214
|
-
num_particles, plane=plane, absolute_cut=pencil_pos, line=line,
|
|
215
|
-
dr_sigmas=dr_sigmas, nemitt_x=coll.nemitt_x, nemitt_y=coll.nemitt_y,
|
|
216
|
-
at_element=at_element, side=side, twiss=tw_at_s
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
# Other plane: generate gaussian distribution in normalized coordinates
|
|
220
|
-
transverse_norm = np.random.normal(size=num_particles)
|
|
221
|
-
p_transverse_norm = np.random.normal(size=num_particles)
|
|
222
|
-
|
|
223
|
-
return [pencil, p_pencil, transverse_norm, p_transverse_norm]
|
|
224
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|