xcoll 0.3.0__py3-none-any.whl → 0.3.2__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/__init__.py CHANGED
@@ -3,11 +3,13 @@
3
3
  # Copyright (c) CERN, 2023. #
4
4
  # ######################################### #
5
5
 
6
- from .general import _pkg_root, __version__
6
+ from .general import _pkg_root, __version__, citation
7
7
 
8
- from .beam_elements import BlackAbsorber, EverestBlock, EverestCollimator, EverestCrystal
8
+ from .beam_elements import BlackAbsorber, EverestBlock, EverestCollimator, EverestCrystal, element_classes
9
9
  from .scattering_routines.everest import materials, Material, CrystalMaterial
10
10
  from .manager import CollimatorManager
11
11
  from .colldb import CollimatorDatabase, load_SixTrack_colldb
12
12
  from .rf_sweep import RFSweep
13
13
 
14
+ # print("If you use Xcoll in your simulations, please cite us :-)")
15
+ # print(citation)
@@ -1,5 +1,11 @@
1
- from .base_collimator import BaseCollimator
1
+ from .base import BaseBlock, BaseCollimator
2
2
  from .absorber import BlackAbsorber
3
- from .everest_collimator import EverestBlock, EverestCollimator, EverestCrystal
3
+ from .everest import EverestBlock, EverestCollimator, EverestCrystal
4
4
 
5
5
  _all_collimator_types = {BlackAbsorber, EverestCollimator, EverestCrystal}
6
+
7
+ block_classes = tuple(v for v in globals().values()
8
+ if isinstance(v, type) and issubclass(v, BaseBlock) and v != BaseBlock)
9
+ collimator_classes = tuple(v for v in globals().values()
10
+ if isinstance(v, type) and issubclass(v, BaseCollimator) and v != BaseCollimator)
11
+ element_classes = block_classes + collimator_classes
@@ -5,7 +5,7 @@
5
5
 
6
6
  import xtrack as xt
7
7
  import xobjects as xo
8
- from .base_collimator import BaseCollimator, InvalidXcoll
8
+ from .base import BaseCollimator, InvalidXcoll
9
9
  from ..general import _pkg_root
10
10
 
11
11
 
@@ -1,5 +1,5 @@
1
1
  # copyright ############################### #
2
- # This file is part of the Xcoll Package. #
2
+ # This file is part of the Xcoll Package. #
3
3
  # Copyright (c) CERN, 2023. #
4
4
  # ######################################### #
5
5
 
@@ -20,6 +20,7 @@ class InvalidXcoll(xt.BeamElement):
20
20
 
21
21
  isthick = True
22
22
  behaves_like_drift = True
23
+ # allow_track = False # Need to wait for xtrack release to implement
23
24
  skip_in_loss_location_refinement = True
24
25
  allow_backtrack = True
25
26
 
@@ -47,6 +48,7 @@ class BaseBlock(xt.BeamElement):
47
48
 
48
49
  isthick = True
49
50
  behaves_like_drift = True
51
+ # allow_track = False # Need to wait for xtrack release to implement
50
52
  skip_in_loss_location_refinement = True
51
53
 
52
54
  _extra_c_sources = [
@@ -88,6 +90,7 @@ class BaseCollimator(xt.BeamElement):
88
90
 
89
91
  isthick = True
90
92
  behaves_like_drift = True
93
+ # allow_track = False # Need to wait for xtrack release to implement
91
94
  skip_in_loss_location_refinement = True
92
95
 
93
96
  _skip_in_to_dict = ['jaw_L', 'jaw_R', 'ref_x', 'ref_y',
@@ -10,12 +10,13 @@
10
10
 
11
11
 
12
12
  /*gpufun*/
13
- void EverestBlock_set_material(EverestBlockData el, LocalParticle* part0){
13
+ void EverestBlock_set_material(EverestBlockData el){
14
14
  MaterialData material = EverestBlockData_getp__material(el);
15
15
  RandomRutherfordData rng = EverestBlockData_getp_rutherford_rng(el);
16
16
  RandomRutherford_set_by_xcoll_material(rng, (GeneralMaterialData) material);
17
17
  }
18
18
 
19
+
19
20
  /*gpufun*/
20
21
  EverestCollData EverestBlock_init(EverestBlockData el, LocalParticle* part0, int8_t active){
21
22
  EverestCollData coll = (EverestCollData) malloc(sizeof(EverestCollData_));
@@ -32,6 +33,7 @@ EverestCollData EverestBlock_init(EverestBlockData el, LocalParticle* part0, int
32
33
  coll->csref[0] = MaterialData_get_cross_section(material, 0);
33
34
  coll->csref[1] = MaterialData_get_cross_section(material, 1);
34
35
  coll->csref[5] = MaterialData_get_cross_section(material, 5);
36
+ coll->only_mcs = MaterialData_get__only_mcs(material);
35
37
 
36
38
  // Impact table
37
39
  coll->record = EverestBlockData_getp_internal_record(el, part0);
@@ -46,29 +48,27 @@ EverestCollData EverestBlock_init(EverestBlockData el, LocalParticle* part0, int
46
48
 
47
49
 
48
50
  /*gpufun*/
49
- EverestData EverestBlock_init_data(LocalParticle* part, EverestCollData coll, int8_t only_mcs){
51
+ EverestData EverestBlock_init_data(LocalParticle* part, EverestCollData coll){
50
52
  EverestData everest = (EverestData) malloc(sizeof(EverestData_));
51
53
  everest->coll = coll;
52
54
  everest->rescale_scattering = 1;
53
55
  #ifndef XCOLL_REFINE_ENERGY
54
- if (!only_mcs){
55
- // Preinitialise scattering parameters
56
- double charge_ratio = LocalParticle_get_charge_ratio(part);
57
- double mass_ratio = charge_ratio / LocalParticle_get_chi(part);
58
- double energy = ( LocalParticle_get_ptau(part) + 1 / LocalParticle_get_beta0(part)
59
- ) * mass_ratio * LocalParticle_get_p0c(part) / 1e9; // energy in GeV
60
- calculate_scattering(everest, energy);
61
- calculate_ionisation_properties(everest, energy);
62
- }
56
+ // Preinitialise scattering parameters
57
+ double charge_ratio = LocalParticle_get_charge_ratio(part);
58
+ double mass_ratio = charge_ratio / LocalParticle_get_chi(part);
59
+ double energy = ( LocalParticle_get_ptau(part) + 1 / LocalParticle_get_beta0(part)
60
+ ) * mass_ratio * LocalParticle_get_p0c(part) / 1e9; // energy in GeV
61
+ calculate_scattering(everest, energy);
62
+ calculate_ionisation_properties(everest, energy);
63
63
  #endif
64
64
  return everest;
65
65
  }
66
66
 
67
+
67
68
  /*gpufun*/
68
69
  void EverestBlock_track_local_particle(EverestBlockData el, LocalParticle* part0) {
69
70
  int8_t active = EverestBlockData_get__tracking(el);
70
71
  double const length = EverestBlockData_get_length(el);
71
- int8_t const only_mcs = EverestBlockData_get__only_mcs(el);
72
72
 
73
73
  // Initialise collimator data
74
74
  // TODO: we want this to happen before tracking (instead of every turn), as a separate kernel
@@ -84,7 +84,7 @@ void EverestBlock_track_local_particle(EverestBlockData el, LocalParticle* part0
84
84
  int8_t is_valid = xcoll_check_particle_init(coll->rng, part);
85
85
 
86
86
  if (is_valid) {
87
- EverestData everest = EverestBlock_init_data(part, coll, only_mcs);
87
+ EverestData everest = EverestBlock_init_data(part, coll);
88
88
  double const e0 = LocalParticle_get_energy0(part) / 1.e9; // Reference energy in GeV
89
89
  double const p0 = LocalParticle_get_p0c(part) / 1e9; // Reference momentum in GeV
90
90
  double const mass_ratio = LocalParticle_get_charge_ratio(part) / LocalParticle_get_chi(part); // m/m0
@@ -95,7 +95,7 @@ void EverestBlock_track_local_particle(EverestBlockData el, LocalParticle* part0
95
95
  double const px_in = LocalParticle_get_px(part);
96
96
  double const py_in = LocalParticle_get_py(part);
97
97
 
98
- double* result = jaw(everest, part, energy, length, only_mcs, 0);
98
+ double* result = jaw(everest, part, energy, length, 0);
99
99
  energy = result[0];
100
100
  if (result[1] == 1){ is_abs = 1; }
101
101
  double s_out = result[2];
@@ -9,8 +9,7 @@
9
9
  #include <stdio.h>
10
10
 
11
11
 
12
- /*gpufun*/
13
- void EverestCollimator_set_material(EverestCollimatorData el, LocalParticle* part0){
12
+ void EverestCollimator_set_material(EverestCollimatorData el){
14
13
  MaterialData material = EverestCollimatorData_getp__material(el);
15
14
  RandomRutherfordData rng = EverestCollimatorData_getp_rutherford_rng(el);
16
15
  RandomRutherford_set_by_xcoll_material(rng, (GeneralMaterialData) material);
@@ -36,6 +35,7 @@ EverestCollData EverestCollimator_init(EverestCollimatorData el, LocalParticle*
36
35
  coll->csref[0] = MaterialData_get_cross_section(material, 0);
37
36
  coll->csref[1] = MaterialData_get_cross_section(material, 1);
38
37
  coll->csref[5] = MaterialData_get_cross_section(material, 5);
38
+ coll->only_mcs = MaterialData_get__only_mcs(material);
39
39
 
40
40
  // Impact table
41
41
  coll->record = EverestCollimatorData_getp_internal_record(el, part0);
@@ -93,8 +93,8 @@ void EverestCollimator_track_local_particle(EverestCollimatorData el, LocalParti
93
93
  double const sin_zR = EverestCollimatorData_get_sin_zR(el);
94
94
  double const cos_zR = EverestCollimatorData_get_cos_zR(el);
95
95
  if (fabs(sin_zL-sin_zR) > 1.e-10 || fabs(cos_zL-cos_zR) > 1.e-10 ){
96
- printf("Jaws with different angles not yet implemented!");
97
- fflush(stdout);
96
+ printf("Jaws with different angles not yet implemented!"); //only_for_context cpu_serial
97
+ fflush(stdout); //only_for_context cpu_serial
98
98
  kill_all_particles(part0, XC_ERR_NOT_IMPLEMENTED);
99
99
  };
100
100
 
@@ -9,9 +9,8 @@
9
9
  #include <stdio.h>
10
10
 
11
11
 
12
-
13
12
  /*gpufun*/
14
- void EverestCrystal_set_material(EverestCrystalData el, LocalParticle* part0){
13
+ void EverestCrystal_set_material(EverestCrystalData el){
15
14
  CrystalMaterialData material = EverestCrystalData_getp__material(el);
16
15
  RandomRutherfordData rng = EverestCrystalData_getp_rutherford_rng(el);
17
16
  RandomRutherford_set_by_xcoll_material(rng, (GeneralMaterialData) material);
@@ -9,12 +9,11 @@ import xobjects as xo
9
9
  import xpart as xp
10
10
  import xtrack as xt
11
11
 
12
- from .base_collimator import BaseBlock, BaseCollimator, InvalidXcoll
12
+ from .base import BaseBlock, BaseCollimator, InvalidXcoll
13
13
  from ..scattering_routines.everest import GeneralMaterial, Material, CrystalMaterial, EverestEngine
14
14
  from ..general import _pkg_root
15
15
 
16
16
 
17
-
18
17
  # TODO:
19
18
  # We want these elements to behave as if 'iscollective = True' when doing twiss etc (because they would ruin the CO),
20
19
  # but as if 'iscollective = False' for normal tracking as it is natively in C...
@@ -28,8 +27,7 @@ class EverestBlock(BaseBlock):
28
27
  _xofields = { **BaseBlock._xofields,
29
28
  '_material': Material,
30
29
  'rutherford_rng': xt.RandomRutherford,
31
- '_tracking': xo.Int8,
32
- '_only_mcs': xo.Int8
30
+ '_tracking': xo.Int8
33
31
  }
34
32
 
35
33
  isthick = True
@@ -46,10 +44,10 @@ class EverestBlock(BaseBlock):
46
44
  _pkg_root.joinpath('beam_elements','collimators_src','everest_block.h')
47
45
  ]
48
46
 
49
- _per_particle_kernels = {
50
- '_EverestBlock_set_material': xo.Kernel(
47
+ _kernels = {
48
+ 'EverestBlock_set_material': xo.Kernel(
51
49
  c_name='EverestBlock_set_material',
52
- args=[]
50
+ args=[xo.Arg(xo.ThisClass, name='el')]
53
51
  )
54
52
  }
55
53
 
@@ -64,20 +62,20 @@ class EverestBlock(BaseBlock):
64
62
  or mat['__class__'] != "Material":
65
63
  raise ValueError("Invalid material!")
66
64
  kwargs['_material'] = mat
67
- # TODO: this should be better
68
- if np.allclose(mat.Z, 0.) or np.allclose(mat.A, 0.) \
69
- or np.allclose(mat.density, 0.) \
70
- or np.allclose(mat.excitation_energy, 0.) \
71
- or np.allclose(mat.nuclear_radius, 0.) \
72
- or np.allclose(mat.nuclear_elastic_slope, 0.):
73
- kwargs['_only_mcs'] = True
74
- else:
75
- kwargs['_only_mcs'] = False
76
65
  kwargs.setdefault('rutherford_rng', xt.RandomRutherford())
77
66
  kwargs.setdefault('_tracking', True)
67
+ use_prebuilt_kernels = kwargs.pop('use_prebuilt_kernels', True)
78
68
  super().__init__(**kwargs)
79
69
  if '_xobject' not in kwargs:
80
- self._EverestBlock_set_material(xp.Particles())
70
+ try: # TODO: small workaround until PR
71
+ self.compile_kernels(use_prebuilt_kernels=use_prebuilt_kernels,
72
+ particles_class=xp.Particles,
73
+ only_if_needed=True)
74
+ except TypeError:
75
+ self.compile_kernels(particles_class=xp.Particles,
76
+ only_if_needed=True)
77
+ self._context.kernels.EverestBlock_set_material(el=self)
78
+
81
79
 
82
80
  @property
83
81
  def material(self):
@@ -88,8 +86,10 @@ class EverestBlock(BaseBlock):
88
86
  if not isinstance(material, Material):
89
87
  if not isinstance('material', dict) or material['__class__'] != "Material":
90
88
  raise ValueError("Invalid material!")
91
- self._material = material
92
- self._EverestBlock_set_material(xp.Particles())
89
+ if not xt.line._dicts_equal(self.material.to_dict(), material.to_dict()):
90
+ self._material = material
91
+ self.compile_kernels(particles_class=xp.Particles, only_if_needed=True)
92
+ self._context.kernels.EverestBlock_set_material(el=self)
93
93
 
94
94
  def get_backtrack_element(self, _context=None, _buffer=None, _offset=None):
95
95
  return InvalidXcoll(length=-self.length, _context=_context,
@@ -117,10 +117,10 @@ class EverestCollimator(BaseCollimator):
117
117
  _pkg_root.joinpath('beam_elements','collimators_src','everest_collimator.h')
118
118
  ]
119
119
 
120
- _per_particle_kernels = {
121
- '_EverestCollimator_set_material': xo.Kernel(
120
+ _kernels = {
121
+ 'EverestCollimator_set_material': xo.Kernel(
122
122
  c_name='EverestCollimator_set_material',
123
- args=[]
123
+ args=[xo.Arg(xo.ThisClass, name='el')]
124
124
  )
125
125
  }
126
126
 
@@ -136,9 +136,17 @@ class EverestCollimator(BaseCollimator):
136
136
  kwargs['_material'] = kwargs.pop('material')
137
137
  kwargs.setdefault('rutherford_rng', xt.RandomRutherford())
138
138
  kwargs.setdefault('_tracking', True)
139
+ use_prebuilt_kernels = kwargs.pop('use_prebuilt_kernels', True)
139
140
  super().__init__(**kwargs)
140
141
  if '_xobject' not in kwargs:
141
- self._EverestCollimator_set_material(xp.Particles())
142
+ try: # TODO: small workaround until PR
143
+ self.compile_kernels(use_prebuilt_kernels=use_prebuilt_kernels,
144
+ particles_class=xp.Particles,
145
+ only_if_needed=True)
146
+ except TypeError:
147
+ self.compile_kernels(particles_class=xp.Particles,
148
+ only_if_needed=True)
149
+ self._context.kernels.EverestCollimator_set_material(el=self)
142
150
 
143
151
  @property
144
152
  def material(self):
@@ -149,8 +157,10 @@ class EverestCollimator(BaseCollimator):
149
157
  if not isinstance(material, Material):
150
158
  if not isinstance('material', dict) or material['__class__'] != "Material":
151
159
  raise ValueError("Invalid material!")
152
- self._material = material
153
- self._EverestCollimator_set_material(xp.Particles())
160
+ if not xt.line._dicts_equal(self.material.to_dict(), material.to_dict()):
161
+ self._material = material
162
+ self.compile_kernels(particles_class=xp.Particles, only_if_needed=True)
163
+ self._context.kernels.EverestCollimator_set_material(el=self)
154
164
 
155
165
  def get_backtrack_element(self, _context=None, _buffer=None, _offset=None):
156
166
  return InvalidXcoll(length=-self.length, _context=_context,
@@ -189,10 +199,10 @@ class EverestCrystal(BaseCollimator):
189
199
  _pkg_root.joinpath('beam_elements','collimators_src','everest_crystal.h')
190
200
  ]
191
201
 
192
- _per_particle_kernels = {
193
- '_EverestCrystal_set_material': xo.Kernel(
202
+ _kernels = {
203
+ 'EverestCrystal_set_material': xo.Kernel(
194
204
  c_name='EverestCrystal_set_material',
195
- args=[]
205
+ args=[xo.Arg(xo.ThisClass, name='el')]
196
206
  )
197
207
  }
198
208
 
@@ -223,13 +233,22 @@ class EverestCrystal(BaseCollimator):
223
233
  kwargs['_orient'] = _lattice_setter(kwargs.pop('lattice', 'strip'))
224
234
  kwargs.setdefault('rutherford_rng', xt.RandomRutherford())
225
235
  kwargs.setdefault('_tracking', True)
236
+ use_prebuilt_kernels = kwargs.pop('use_prebuilt_kernels', True)
226
237
  super().__init__(**kwargs)
227
238
  if '_xobject' not in kwargs:
228
239
  if bending_radius:
229
240
  self._bending_angle = np.arcsin(self.active_length/bending_radius)
230
241
  if bending_angle:
231
242
  self._bending_radius = self.active_length / np.sin(bending_angle)
232
- self._EverestCrystal_set_material(xp.Particles())
243
+ try: # TODO: small workaround until PR
244
+ self.compile_kernels(use_prebuilt_kernels=use_prebuilt_kernels,
245
+ particles_class=xp.Particles,
246
+ only_if_needed=True)
247
+ except TypeError:
248
+ self.compile_kernels(particles_class=xp.Particles,
249
+ only_if_needed=True)
250
+ self._context.kernels.EverestCrystal_set_material(el=self)
251
+
233
252
 
234
253
  @property
235
254
  def critical_angle(self):
@@ -275,8 +294,10 @@ class EverestCrystal(BaseCollimator):
275
294
  if not isinstance(material, CrystalMaterial):
276
295
  if not isinstance(material, dict) or material['__class__'] != "CrystalMaterial":
277
296
  raise ValueError("Invalid material!")
278
- self._material = material
279
- self._EverestCrystal_set_material(xp.Particles())
297
+ if not xt.line._dicts_equal(self.material.to_dict(), material.to_dict()):
298
+ self._material = material
299
+ self.compile_kernels(particles_class=xp.Particles, only_if_needed=True)
300
+ self._context.kernels.EverestCrystal_set_material(el=self)
280
301
 
281
302
 
282
303
  def get_backtrack_element(self, _context=None, _buffer=None, _offset=None):
@@ -293,3 +314,17 @@ def _lattice_setter(lattice):
293
314
  raise ValueError(f"Illegal value {lattice} for 'lattice'! "
294
315
  + "Only use 'strip' (110) or 'quasi-mosaic' (111).")
295
316
 
317
+
318
+ # TODO: We want this in the HybridClass to get Kernels attached automatically,
319
+ # like the PerParticlePyMethod in BeamElement
320
+ # def _exec_kernel(el, kernel_name, **kwargs):
321
+ # # context = el._context
322
+ # # desired_classes = tuple(a.atype for a in el._kernels[kernel_name].args)
323
+ # # if (kernel_name, desired_classes) not in context.kernels:
324
+ # # el.compile_kernels(particles_class=xp.Particles)
325
+ # # kern = context.kernels[(kernel_name, desired_classes)]
326
+ # # return kern(el=el._xobject, **kwargs)
327
+ # el.compile_kernels(particles_class=xp.Particles, only_if_needed=True)
328
+ # return getattr(el._context.kernels, kernel_name)(el=el, **kwargs)
329
+
330
+
xcoll/general.py CHANGED
@@ -7,8 +7,10 @@ from pathlib import Path
7
7
 
8
8
  _pkg_root = Path(__file__).parent.absolute()
9
9
 
10
+ citation = "F.F. Van der Veken, et al.: Recent Developments with the New Tools for Collimation Simulations in Xsuite, Proceedings of HB2023, Geneva, Switzerland."
11
+
10
12
  # ===================
11
13
  # Do not change
12
14
  # ===================
13
- __version__ = '0.3.0'
15
+ __version__ = '0.3.2'
14
16
  # ===================
xcoll/headers/checks.h CHANGED
@@ -10,18 +10,18 @@
10
10
  int8_t xcoll_check_particle_init(RandomRutherfordData rng, LocalParticle* part) {
11
11
  int8_t is_tracking = assert_tracking(part, XC_ERR_INVALID_TRACK);
12
12
  if (!is_tracking){
13
- printf("Collimator tracking code is called, but we are not supposed to be tracking!");
14
- fflush(stdout);
13
+ printf("Collimator tracking code is called, but we are not supposed to be tracking!"); //only_for_context cpu_serial
14
+ fflush(stdout); //only_for_context cpu_serial
15
15
  }
16
16
  int8_t rng_is_set = assert_rng_set(part, RNG_ERR_SEEDS_NOT_SET);
17
17
  if (!rng_is_set){
18
- printf("Random generator seeds in particles object are not set!");
19
- fflush(stdout);
18
+ printf("Random generator seeds in particles object are not set!"); //only_for_context cpu_serial
19
+ fflush(stdout); //only_for_context cpu_serial
20
20
  }
21
21
  int8_t ruth_is_set = assert_rutherford_set(rng, part, RNG_ERR_RUTH_NOT_SET);
22
22
  if (!ruth_is_set){
23
- printf("Rutherford random generator not initialised!");
24
- fflush(stdout);
23
+ printf("Rutherford random generator not initialised!"); //only_for_context cpu_serial
24
+ fflush(stdout); //only_for_context cpu_serial
25
25
  }
26
26
  return is_tracking*rng_is_set*ruth_is_set;
27
27
  }
xcoll/manager.py CHANGED
@@ -332,22 +332,19 @@ class CollimatorManager:
332
332
  elif name not in self.collimator_names:
333
333
  raise Exception(f"Warning: Collimator {name} not found in CollimatorDatabase!...")
334
334
  if self.tracker_ready:
335
- raise Exception("Tracker already built!\nPlease install collimators before building tracker!")
336
-
337
- # Get collimator centers
338
- positions = dict(zip(names,line.get_s_position(names)))
335
+ raise Exception("Tracker already built!\nPlease install collimators before building "
336
+ + "tracker!")
339
337
 
340
338
  # Loop over collimators to install
341
339
  for name in names:
342
-
343
- # Get the settings from the CollimatorDatabase
344
- thiscoll = df.loc[name]
345
- # Create the collimator element
346
- newcoll = install_func(thiscoll, name)
347
- collimator_class = newcoll.__class__
340
+
341
+ # Get s positions
342
+ # This cannot go outside the loop as the indices will change!
343
+ ss = line.get_s_position()
348
344
 
349
345
  # Get the settings from the CollimatorDatabase
350
346
  thiscoll = df.loc[name]
347
+ idx = line.element_names.index(name)
351
348
  # Create the collimator element
352
349
  newcoll = install_func(thiscoll, name)
353
350
  collimator_class = newcoll.__class__
@@ -356,15 +353,16 @@ class CollimatorManager:
356
353
  # TODO: automatically replace collimator type and print warning
357
354
  if isinstance(line[name], tuple(_all_collimator_types - {collimator_class})):
358
355
  raise ValueError(f"Trying to install {name} as {collimator_class.__name__},"
359
- + f" but it is already installed as {type(line[name]).__name__}!\n"
360
- + "Please reconstruct the line.")
356
+ + f" but it is already installed as {type(line[name]).__name__}!\n"
357
+ + f"Please reconstruct the line.")
361
358
 
362
359
  # Check that collimator is not installed previously
363
360
  elif isinstance(line[name], collimator_class):
364
361
  if df.loc[name,'collimator_type'] != collimator_class.__name__:
365
- raise Exception(f"Something is wrong: Collimator {name} already installed in line "
366
- + f"as {collimator_class.__name__} element, but registered in CollimatorDatabase "
367
- + f"as {df.loc[name, 'collimator_type']}. Please reconstruct the line.")
362
+ raise Exception(f"Something is wrong: Collimator {name} already installed in "
363
+ + f"line as {collimator_class.__name__} element, but registered "
364
+ + f"in CollimatorDatabase as {df.loc[name, 'collimator_type']}. "
365
+ + f"Please reconstruct the line.")
368
366
  if verbose: print(f"Collimator {name} already installed. Skipping...")
369
367
  continue
370
368
 
@@ -372,37 +370,98 @@ class CollimatorManager:
372
370
  # How to do this with importing a line for MAD-X or SixTrack...?
373
371
  elif not isinstance(line[name], (xt.Marker, xt.Drift)) and not support_legacy_elements:
374
372
  raise ValueError(f"Trying to install {name} as {collimator_class.__name__},"
375
- + f" but the line element to replace is not an xtrack.Marker (or xtrack.Drift)!\n"
376
- + "Please check the name, or correct the element.")
373
+ + f" but the line element to replace is not an xtrack.Marker "
374
+ + f"(or xtrack.Drift)!\nPlease check the name, or correct the "
375
+ + f"element.")
377
376
 
378
- if verbose: print(f"Installing {name:16} as {collimator_class.__name__}")
377
+ if verbose: print(f"Installing {name:20} as {collimator_class.__name__}")
379
378
  # Update the position and type in the CollimatorDatabase
380
- df.loc[name,'s_center'] = positions[name]
379
+ df.loc[name,'s_center'] = ss[idx]
381
380
  df.loc[name,'collimator_type'] = collimator_class.__name__
382
- # Do the installation
383
- s_install = df.loc[name,'s_center'] - thiscoll['active_length']/2 - thiscoll['inactive_front']
384
- has_apertures = np.unique([nn for nn in line.element_names if name + '_aper' in nn])
385
- if len(has_apertures) > 0:
386
- if len(has_apertures) > 1:
387
- # Choose the aperture closest to the element
388
- has_apertures = [aa for aa in has_apertures
389
- if line.element_names.index(aa) < line.element_names.index(name)]
390
- has_apertures.sort(key=lambda nn: line.element_names.index(nn))
391
- coll_aper = line[has_apertures[-1]]
392
- assert coll_aper.__class__.__name__.startswith('Limit')
393
- if np.any([name + '_aper_tilt_' in nn for nn in line.element_names]):
394
- raise NotImplementedError("Collimator apertures with tilt not implemented!")
395
- if np.any([name + '_aper_offset_' in nn for nn in line.element_names]):
396
- raise NotImplementedError("Collimator apertures with offset not implemented!")
397
- else:
398
- coll_aper = None
399
381
 
382
+ # Find apertures and store them
383
+ # TODO: same with cryotanks for FLUKA
384
+ # TODO: use compound info -> need full collimator info from MADX
385
+ # TODO: this is all very hacky....
386
+ aper_before = {}
387
+ aper_after = {}
388
+ if f'{name}_mken' in line.element_names\
389
+ and f'{name}_mkex'in line.element_names:
390
+ # TODO what with transformations? How to shift them in s if different?
391
+ aper_before = {nn.replace('mken', 'upstream'): line[nn].copy()
392
+ for nn in line.element_names if nn.startswith(f'{name}_mken_aper')}
393
+ aper_after = {nn.replace('mkex', 'downstream'): line[nn].copy()
394
+ for nn in line.element_names if nn.startswith(f'{name}_mkex_aper')}
395
+ if len(aper_before) == 0:
396
+ # TODO what with transformations? How to shift them in s from centre to start/end?
397
+ aper_before = {nn.replace('_aper', '_upstream_aper'): line[nn].copy()
398
+ for nn in line.element_names if nn.startswith(f'{name}_aper')}
399
+ if len(aper_after) == 0:
400
+ aper_after = {nn.replace('_aper', '_downstream_aper'): line[nn].copy()
401
+ for nn in line.element_names if nn.startswith(f'{name}_aper')}
402
+ if len(aper_before) == 0 or len(aper_after) == 0:
403
+ print(f"Warning: No aperture found for collimator {name}!")
404
+
405
+ # Remove stuff at location of collimator
406
+ l = thiscoll['active_length']
407
+ to_remove = []
408
+ i = idx - 1
409
+ # We remove everything between the beginning and end of the collimator except drifts
410
+ while ss[i] >= ss[idx] - l/2:
411
+ el = line[i]
412
+ nn = line.element_names[i]
413
+ if el.__class__.__name__ == 'Drift':
414
+ i -= 1
415
+ continue
416
+ if hasattr(el, 'length') and el.length > 0:
417
+ raise ValueError(f"Found active element {nn} with length "
418
+ + f"{el.length} at location inside collimator!")
419
+ # I don't like this class selection...
420
+ if not el.__class__.__name__ in ['Marker', 'SRotation', \
421
+ 'YRotation', 'XRotation', 'XYShift'] \
422
+ and not el.__class__.__name__.startswith('Limit'):
423
+ print(f"Warning: Removed active element {nn} "
424
+ + f"at location inside collimator!")
425
+ to_remove.append(nn)
426
+ i -= 1
427
+ i = idx + 1
428
+ while ss[i] <= ss[idx] + l/2:
429
+ el = line[i]
430
+ nn = line.element_names[i]
431
+ if el.__class__.__name__ == 'Drift':
432
+ i += 1
433
+ continue
434
+ if hasattr(el, 'length') and el.length > 0:
435
+ raise ValueError(f"Found active element {nn} with length "
436
+ + f"{el.length} at location inside collimator!")
437
+ # I don't like this class selection...
438
+ if not el.__class__.__name__ in ['Marker', 'SRotation', \
439
+ 'YRotation', 'XRotation', 'XYShift'] \
440
+ and not el.__class__.__name__.startswith('Limit'):
441
+ print(f"Warning: Removed active element {line.element_names[i]} "
442
+ + f"at location inside collimator!")
443
+ to_remove.append(nn)
444
+ i += 1
445
+ for nn in to_remove:
446
+ # TODO: need to update Compounds
447
+ line.element_names.remove(nn)
448
+ line.element_dict.pop(nn)
449
+
450
+ # Do the installation
451
+ s_install = df.loc[name,'s_center'] - thiscoll['active_length']/2 \
452
+ - thiscoll['inactive_front']
400
453
  line.insert_element(element=newcoll, name=name, at_s=s_install)
401
454
 
402
- if coll_aper is not None:
403
- line.insert_element(element=coll_aper, name=name+'_aper_front', index=name)
404
- line.insert_element(element=coll_aper, name=name+'_aper_back',
455
+ # Reinstall apertures
456
+ for aper, el in aper_before.items():
457
+ # TODO: need to update Compounds
458
+ line.insert_element(element=el, name=aper, index=name)
459
+ for aper, el in reversed(aper_after.items()):
460
+ # Reversed because of index+1
461
+ # TODO: need to update Compounds
462
+ line.insert_element(element=el, name=aper,
405
463
  index=line.element_names.index(name)+1)
464
+
406
465
  self._set_record_impacts()
407
466
 
408
467
 
@@ -854,7 +913,7 @@ class CollimatorManager:
854
913
 
855
914
  if file is not None:
856
915
  with open(Path(file), 'w') as fid:
857
- json.dump(self._lossmap, fid, indent=True)
916
+ json.dump(self._lossmap, fid, cls=xo.JEncoder, indent=True)
858
917
 
859
918
  return self._lossmap
860
919
 
@@ -43,6 +43,7 @@ typedef struct EverestCollData_ {
43
43
  double ai;
44
44
  double eum;
45
45
  double collnt;
46
+ int8_t only_mcs;
46
47
  } EverestCollData_;
47
48
  typedef EverestCollData_ *EverestCollData;
48
49
 
@@ -90,7 +90,7 @@ int ichoix(EverestData restrict everest, LocalParticle* part) {
90
90
 
91
91
 
92
92
  /*gpufun*/
93
- double* jaw(EverestData restrict everest, LocalParticle* part, double p, double zlm, int only_mcs, int edge_check) {
93
+ double* jaw(EverestData restrict everest, LocalParticle* part, double p, double zlm, int edge_check) {
94
94
 
95
95
  double* result = (double*)malloc(3 * sizeof(double));
96
96
 
@@ -108,7 +108,7 @@ double* jaw(EverestData restrict everest, LocalParticle* part, double p, double
108
108
  double z = LocalParticle_get_y(part);
109
109
  double zp = LocalParticle_get_py(part)*rpp_in;
110
110
 
111
- if (only_mcs) {
111
+ if (everest->coll->only_mcs) {
112
112
  double* res = mcs(everest, part, zlm, p, x, xp, z, zp, edge_check);
113
113
  s = res[0];
114
114
  x = res[1];
@@ -174,7 +174,7 @@ double* jaw(EverestData restrict everest, LocalParticle* part, double p, double
174
174
  int inter = ichoix(everest, part);
175
175
  nabs = inter;
176
176
  if (inter == 1) {
177
- s = (zlm-rlen)+zlm1;
177
+ s = zlm - rlen + zlm1;
178
178
  m_dpodx = calcionloss(everest, part, rlen);
179
179
  p = p-m_dpodx*s;
180
180
  break;
@@ -208,14 +208,14 @@ double* jaw(EverestData restrict everest, LocalParticle* part, double p, double
208
208
  xp = xp + tx;
209
209
  zp = zp + tz;
210
210
 
211
- // Treat single-diffractive scattering.
211
+ // Treat single-diffractive scattering. TODO: this does nothing??
212
212
  if(inter == 4) {
213
213
  // added update for s
214
- s = (zlm-rlen)+zlm1;
214
+ s = zlm - rlen + zlm1;
215
215
  }
216
216
 
217
217
  // Calculate the remaining interaction length and close the iteration loop.
218
- rlen = rlen-zlm1;
218
+ rlen = rlen - zlm1;
219
219
  }
220
220
  }
221
221
 
@@ -223,6 +223,7 @@ double* jaw(EverestData restrict everest, LocalParticle* part, double p, double
223
223
  LocalParticle_set_px(part, xp/rpp_in);
224
224
  LocalParticle_set_y(part, z);
225
225
  LocalParticle_set_py(part, zp/rpp_in);
226
+ LocalParticle_add_to_s(part, s); // TODO: is this correct with tilt etc?
226
227
 
227
228
  result[0] = p;
228
229
  result[1] = nabs;
@@ -1,6 +1,6 @@
1
1
  # copyright ############################### #
2
- # This file is part of the Xcoll Package. #
3
- # Copyright (c) CERN, 2023. #
2
+ # This file is part of the Xcoll Package. #
3
+ # Copyright (c) CERN, 2024. #
4
4
  # ######################################### #
5
5
 
6
6
  import xobjects as xo
@@ -31,7 +31,8 @@ class GeneralMaterial(xo.HybridClass):
31
31
  # Index 0:Total, 1:absorption, 2:nuclear elastic, 3:pp or pn elastic
32
32
  # 4:Single Diffractive pp or pn, 5:Coulomb for t above mcs
33
33
  'hcut': xo.Float64,
34
- 'name': xo.String
34
+ 'name': xo.String,
35
+ '_only_mcs': xo.Int8
35
36
  }
36
37
 
37
38
  def __init__(self, **kwargs):
@@ -40,6 +41,15 @@ class GeneralMaterial(xo.HybridClass):
40
41
  kwargs.setdefault('cross_section', [0., 0., 0., 0., 0., 0.])
41
42
  kwargs.setdefault('name', "NO NAME")
42
43
  kwargs['name'] = kwargs['name'].ljust(55) # Pre-allocate 64 byte using whitespace
44
+ # TODO: this should be better
45
+ if kwargs.get('Z', None) is None or kwargs.get('A', None) is None \
46
+ or kwargs.get('density', None) is None \
47
+ or kwargs.get('excitation_energy', None) is None \
48
+ or kwargs.get('nuclear_radius', None) is None \
49
+ or kwargs.get('nuclear_elastic_slope', None) is None:
50
+ kwargs['_only_mcs'] = True
51
+ else:
52
+ kwargs['_only_mcs'] = False
43
53
  super().__init__(**kwargs)
44
54
  self.name = self.name.strip()
45
55
 
@@ -145,10 +145,10 @@ double* mcs(EverestData restrict everest, LocalParticle* part, double zlm1, doub
145
145
  xp = res[1];
146
146
  free(res);
147
147
  if (x <= 0) {
148
- s = (rlen0-rlen)+ s;
148
+ s = rlen0 - rlen + s;
149
149
  break; // go to 20
150
150
  }
151
- if ((s + dh) >= rlen) {
151
+ if (s + dh >= rlen) {
152
152
  s = rlen0;
153
153
  break; // go to 20
154
154
  }
@@ -157,11 +157,11 @@ double* mcs(EverestData restrict everest, LocalParticle* part, double zlm1, doub
157
157
  }
158
158
 
159
159
  } else {
160
- s = rlen0;
161
- double* res = scamcs(part, x, xp, s);
160
+ double* res = scamcs(part, x, xp, rlen0);
162
161
  x = res[0];
163
162
  xp = res[1];
164
163
  free(res);
164
+ s = rlen0;
165
165
  }
166
166
 
167
167
  double* res = scamcs(part, z, zp, s);
@@ -89,7 +89,7 @@ void scatter(EverestData restrict everest, LocalParticle* part, double length){
89
89
  if (zlm > 0.) {
90
90
  is_hit = 1;
91
91
 
92
- double* jaw_result = jaw(everest, part, energy, zlm, 0, 1);
92
+ double* jaw_result = jaw(everest, part, energy, zlm, 1);
93
93
 
94
94
  energy = jaw_result[0];
95
95
  if (jaw_result[1] == 1){
@@ -99,7 +99,7 @@ void scatter(EverestData restrict everest, LocalParticle* part, double length){
99
99
  free(jaw_result);
100
100
 
101
101
  if (is_abs != 1) {
102
- // Do the rest drift, if particle left collimator early
102
+ // Do the rest drift, if particle left collimator early
103
103
  Drift_single_particle_4d(part, zlm-s_out);
104
104
  }
105
105
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xcoll
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Xsuite collimation package
5
5
  Home-page: https://github.com/xsuite/xcoll
6
6
  License: Apache 2.0
@@ -1,39 +1,39 @@
1
1
  LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
2
2
  NOTICE,sha256=6DO_E7WCdRKc42vUoVVBPGttvQi4mRt9fAcxj9u8zy8,74
3
- xcoll/__init__.py,sha256=aR1cGO47NuYwAZp1w4xBlnk2lTCxff6aG3IeXeJCO9M,529
4
- xcoll/beam_elements/__init__.py,sha256=C7MOF6VkGc04b_cadW6pz-nBqTaW9Jmi4RHNA7f8dC8,236
5
- xcoll/beam_elements/absorber.py,sha256=pTs2PL8L8ewg0AJ-HLDQtDuaIsTX3pJ5Xbq4g4A7KFs,1247
6
- xcoll/beam_elements/base_collimator.py,sha256=Rfh6ocJKxHJHhxElDDvvTFV5Pz4XgTld796seYMjOl8,15347
3
+ xcoll/__init__.py,sha256=XO53i_KKg6kaJfTCpmNJLy14tou4RMF9MDuXlH70iTQ,642
4
+ xcoll/beam_elements/__init__.py,sha256=9rKZ5O2jRpjkBlU457ii27eiVGAauCM1M-ALDgJ4f0g,591
5
+ xcoll/beam_elements/absorber.py,sha256=qWBEQA7fEJkLffbr2p0Kx5WYJOcoF7Ikz_A_hL1hdAo,1236
6
+ xcoll/beam_elements/base.py,sha256=jeGSn1SXAtzhSpLDXt9sQO6AkeFrmEE80Q5NENtzCDM,15573
7
7
  xcoll/beam_elements/collimators_src/absorber.h,sha256=rW8ODVDsKb1VR0Xkrhk2i5AQ1F616ugOfrcI9JPK9Lw,5313
8
8
  xcoll/beam_elements/collimators_src/base_block.h,sha256=KlxxqKVNbkoqVvgHFqoPGtFaD82rL6lFzkzkD7G0jsY,421
9
9
  xcoll/beam_elements/collimators_src/base_collimator.h,sha256=zUkv-wczcN8xGJqC_c35QhHTTMSTTEy0eG_URUclUrk,428
10
- xcoll/beam_elements/collimators_src/everest_block.h,sha256=qKPdU24nLMhBbnJRGCrLNcDezE1v-_I_ceeMGMS21uc,5708
11
- xcoll/beam_elements/collimators_src/everest_collimator.h,sha256=981zTeOmDKdQxmTVyuqwdTcu4_OYkaMlEfEemYrfXIo,6161
12
- xcoll/beam_elements/collimators_src/everest_crystal.h,sha256=1L9njfnC-2wT6_o3sJujXWtF9bUXcx1OXismkQZWBH0,5187
10
+ xcoll/beam_elements/collimators_src/everest_block.h,sha256=Gpr5wyFLtcaNgVj3auKgFWB-2KPP5cjbEWTfC3f9q1U,5596
11
+ xcoll/beam_elements/collimators_src/everest_collimator.h,sha256=wsGIFBb-VMCRhxwK2G5k9SEX-6SzIgRX4XE5g_I2okg,6296
12
+ xcoll/beam_elements/collimators_src/everest_crystal.h,sha256=pX9cmW5lfsUoszR14tXWU4Emu-0VwX4bbfg6Q6pxXR4,5164
13
13
  xcoll/beam_elements/collimators_src/invalid_collimator.h,sha256=xwZEQ1STOS0_a3Rso-03Wp0L7wmC5YVy88xtOt1IyEk,423
14
- xcoll/beam_elements/everest_collimator.py,sha256=5ipSK_2zBX7BZ4nT7c1HUFuPVtV6PfhAS1ndm0DBk2g,11209
14
+ xcoll/beam_elements/everest.py,sha256=Thh5rk9rulieW6JiiEnq4C9Q3LbOyUg7NIu_dKi7Rko,13469
15
15
  xcoll/colldb.py,sha256=e2VK1TE2zOjVLwWD-kSs8g0OEGXDVDQvJKrku7OxCwI,48253
16
16
  xcoll/collimator_settings.py,sha256=uj25cpSaM-EY7VM65OUq3Cxb8gedSmi-r9mpkP-ikrg,17015
17
- xcoll/general.py,sha256=ZMCCv5sIZBnQo76NZ3L4IlkeDlDC2NLHwN9HPp8i4-E,361
18
- xcoll/headers/checks.h,sha256=xEhZQHIvgl3_sh9nkD-yISbX1tKMXTSAyi81pLnvfJk,1023
17
+ xcoll/general.py,sha256=6Yxa4-rchtnWttv0NdskFDH7tRMFNeAdQa3DG85Vqm4,525
18
+ xcoll/headers/checks.h,sha256=nTo2bMdtfEXdODcImLwkBPfIcdyf4lBn-CrYXlDiT48,1365
19
19
  xcoll/headers/particle_states.h,sha256=YxpS56_ZD8mhrqKTohcyVe3hbQZ6H9vspYHSVM6a5-U,844
20
20
  xcoll/impacts/__init__.py,sha256=yKQdIeLG2CT3qo-iZB6MODm-WHzkTmulgUvOAS41w7E,39
21
21
  xcoll/impacts/impacts.py,sha256=ShyKrN8nmCG9UWS40V5zDeW2W0VTUHZaTKR3FIycOkc,3929
22
22
  xcoll/impacts/impacts_src/impacts.h,sha256=w_hDpuffO2zrc_iJQkdoVZwozGDN8QqMLQ1IqgxUtRA,6110
23
23
  xcoll/impacts/interaction_types.py,sha256=iHbhC4beN1vZRWeHbALqSFo8lG10R7asc08BRpIqXx0,2493
24
24
  xcoll/install_collimators.py,sha256=wJZ7QelXokWuM7kOySg8LMELMCcTmvWWetTOjUjTU04,9003
25
- xcoll/manager.py,sha256=pI60QiMmGKYcqRdLL7HM3giUJOR5TCYic0JYJ-xVaEk,42067
25
+ xcoll/manager.py,sha256=AF9XziOQ2JT62VSKdzOZzlNFeuaqowzWfqv6msONR9k,45001
26
26
  xcoll/rf_sweep.py,sha256=sUstmeeXmozmM4f8xUGCKLyJYOV3xD4aVZG_FCRspVA,5402
27
27
  xcoll/scattering_routines/everest/__init__.py,sha256=JVJQnyNeUiA3bTNz-rFp-RYxIMBiKEdBhcokk8aj-dg,101
28
28
  xcoll/scattering_routines/everest/constants.h,sha256=9Kus-RKyxsGdlxx9tfMWUz2H5Q-qy6y_F4kddIZzO30,1390
29
29
  xcoll/scattering_routines/everest/crystal.h,sha256=WlA_e9ePuVhc9fmMVdSXFBKvHrFvCQ5aG4d67iMrtuQ,54119
30
- xcoll/scattering_routines/everest/everest.h,sha256=rOlEGmxemOOl7GVv4rn8Ago5G60zqp0ytLPY7BRrbJ8,3722
30
+ xcoll/scattering_routines/everest/everest.h,sha256=p4yfzxRvh19N-V1vorf_CCIBotodV40Lcrzzy7339WM,3743
31
31
  xcoll/scattering_routines/everest/everest.py,sha256=dP4br8KN1vJ7IkvQ92KedI4zXyxOvNvOWnS6vAAYUy8,1305
32
- xcoll/scattering_routines/everest/jaw.h,sha256=iQ1cDyErjLllrkc5uSWtZtEssaXI2q00DRqNkQFV9Ms,7197
33
- xcoll/scattering_routines/everest/materials.py,sha256=Ck4EC9mDnqtDRnVJIAvNnxwtq0FZNZps8Cm7QBxcnBQ,9150
34
- xcoll/scattering_routines/everest/multiple_coulomb_scattering.h,sha256=hW1CnnvQYAYUGk5Z9jGqQXKsbBnYUVirVVx6H5RJGlg,4515
32
+ xcoll/scattering_routines/everest/jaw.h,sha256=lmijUU7ih4veifVho3ehGe0DVyIYkDHMVIIclDNbZds,7308
33
+ xcoll/scattering_routines/everest/materials.py,sha256=zzQcJyTCWkzdvRffuBI8oHYeEE6T_wHt9-c9-YICZJ4,9665
34
+ xcoll/scattering_routines/everest/multiple_coulomb_scattering.h,sha256=0Euxsnc2BU8YqxYwfXZIiplNcnDzFq9HgWAoqGwuSAg,4518
35
35
  xcoll/scattering_routines/everest/properties.h,sha256=aRqkX5ZpUeTnbygqFVsoIKwWyoB5VXzD5vq5d-xiI74,6585
36
- xcoll/scattering_routines/everest/scatter.h,sha256=3hQph45_sToEYLCdVxJMtcUGUXznDmxbZtLZOS6CeaA,6333
36
+ xcoll/scattering_routines/everest/scatter.h,sha256=jl-SAIpizYCbUfy1KAhuO00sA5BBhNBCIjueQ8bCxoQ,6333
37
37
  xcoll/scattering_routines/everest/scatter_crystal.h,sha256=BHBPNiMKynq1XNxIiWJXYxMwW2bhmmbmC8j7-Dy-SNs,9455
38
38
  xcoll/scattering_routines/fluka/flukaio/.git,sha256=5ZxurpwP1waJk2Zu2AstENGOp4rXU8-C-oU4CypmIVI,73
39
39
  xcoll/scattering_routines/fluka/flukaio/.gitignore,sha256=bhrpWiAnKChkcwIaIPX_zKxyG2nCtNzNgQAHnIJa8Fw,12
@@ -385,7 +385,7 @@ xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_colldb_load.py,sha
385
385
  xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_interaction.py,sha256=Z8-ntyXTqK-sr_1PcGtkdQpaOPNVl3xAsu6zSsH7qnQ,6015
386
386
  xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tilt.py,sha256=q-8CpGFH_5u3r3Xa25EpMbxY1YlLrzJ7Q_i9hSwgTGg,2396
387
387
  xcoll/scattering_routines/geant4/collimasim/tests/test_xtrack_tracking.py,sha256=wgf0ncOe3miF3ZOrte_zebY0yulnFz2GFAWksF5-0z0,2940
388
- xcoll-0.3.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
389
- xcoll-0.3.0.dist-info/WHEEL,sha256=vxFmldFsRN_Hx10GDvsdv1wroKq8r5Lzvjp6GZ4OO8c,88
390
- xcoll-0.3.0.dist-info/METADATA,sha256=rFEsb8ylvSBoh4itokxFA74Oerl92-Mq6mSIixob3PA,2657
391
- xcoll-0.3.0.dist-info/RECORD,,
388
+ xcoll-0.3.2.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
389
+ xcoll-0.3.2.dist-info/WHEEL,sha256=vxFmldFsRN_Hx10GDvsdv1wroKq8r5Lzvjp6GZ4OO8c,88
390
+ xcoll-0.3.2.dist-info/METADATA,sha256=I8dB3azZohNOKlsDDMJ1zLXjMvcGJfc4lL0_ECKndvM,2657
391
+ xcoll-0.3.2.dist-info/RECORD,,
File without changes
File without changes