xcoll 0.6.3__tar.gz → 0.6.4__tar.gz

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.

Files changed (67) hide show
  1. {xcoll-0.6.3 → xcoll-0.6.4}/PKG-INFO +2 -2
  2. {xcoll-0.6.3 → xcoll-0.6.4}/pyproject.toml +4 -4
  3. xcoll-0.6.4/xcoll/beam_elements/elements_src/rf_sweep.h +23 -0
  4. xcoll-0.6.4/xcoll/beam_elements/sweep.py +0 -0
  5. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/general.py +1 -1
  6. xcoll-0.6.4/xcoll/geometry.md +42 -0
  7. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/rf_sweep.py +64 -52
  8. {xcoll-0.6.3 → xcoll-0.6.4}/LICENSE +0 -0
  9. {xcoll-0.6.3 → xcoll-0.6.4}/NOTICE +0 -0
  10. {xcoll-0.6.3 → xcoll-0.6.4}/README.md +0 -0
  11. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/__init__.py +0 -0
  12. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/__init__.py +0 -0
  13. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/absorber.py +0 -0
  14. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/base.py +0 -0
  15. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/blowup.py +0 -0
  16. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/black_absorber.h +0 -0
  17. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/black_crystal.h +0 -0
  18. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/blowup.h +0 -0
  19. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/emittance_monitor.h +0 -0
  20. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/everest_block.h +0 -0
  21. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/everest_collimator.h +0 -0
  22. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/everest_crystal.h +0 -0
  23. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/transparent_collimator.h +0 -0
  24. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/elements_src/transparent_crystal.h +0 -0
  25. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/everest.py +0 -0
  26. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/monitor.py +0 -0
  27. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/beam_elements/transparent.py +0 -0
  28. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/colldb.py +0 -0
  29. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/headers/checks.h +0 -0
  30. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/headers/particle_states.py +0 -0
  31. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/initial_distribution.py +0 -0
  32. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/interaction_record/__init__.py +0 -0
  33. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/interaction_record/interaction_record.py +0 -0
  34. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/interaction_record/interaction_record_src/interaction_record.h +0 -0
  35. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/interaction_record/interaction_types.py +0 -0
  36. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/line_tools.py +0 -0
  37. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/lossmap.py +0 -0
  38. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/plot.py +0 -0
  39. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/prebuild_kernels/__init__.py +0 -0
  40. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/prebuild_kernels/element_inits.py +0 -0
  41. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/prebuild_kernels/elements.py +0 -0
  42. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/engine.py +0 -0
  43. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/environment.py +0 -0
  44. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/__init__.py +0 -0
  45. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/amorphous.h +0 -0
  46. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/channelling.h +0 -0
  47. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/constants.h +0 -0
  48. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/crystal_parameters.h +0 -0
  49. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/everest.h +0 -0
  50. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/everest.py +0 -0
  51. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/ionisation_loss.h +0 -0
  52. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/jaw.h +0 -0
  53. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/materials.py +0 -0
  54. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/multiple_coulomb_scattering.h +0 -0
  55. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/nuclear_interaction.h +0 -0
  56. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/everest/properties.h +0 -0
  57. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/__init__.py +0 -0
  58. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/collimator_geometry.h +0 -0
  59. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/crystal_geometry.h +0 -0
  60. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/geometry.py +0 -0
  61. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/get_s.h +0 -0
  62. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/methods.h +0 -0
  63. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/objects.h +0 -0
  64. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/rotation.h +0 -0
  65. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/segments.h +0 -0
  66. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/scattering_routines/geometry/sort.h +0 -0
  67. {xcoll-0.6.3 → xcoll-0.6.4}/xcoll/xaux.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: xcoll
3
- Version: 0.6.3
3
+ Version: 0.6.4
4
4
  Summary: Xsuite collimation package
5
5
  License: Apache-2.0
6
6
  Author: Frederik F. Van der Veken
@@ -22,7 +22,7 @@ Requires-Dist: ruamel-yaml (>=0.17.31,<0.18.15)
22
22
  Requires-Dist: xdeps (>=0.10.6)
23
23
  Requires-Dist: xobjects (>=0.5.2)
24
24
  Requires-Dist: xpart (>=0.23.1)
25
- Requires-Dist: xtrack (>=0.89.3)
25
+ Requires-Dist: xtrack (>=0.90.1)
26
26
  Project-URL: Bug Tracker, https://github.com/xsuite/xsuite/issues
27
27
  Project-URL: Documentation, https://xsuite.readthedocs.io/
28
28
  Project-URL: Homepage, https://github.com/xsuite/xcoll
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xcoll"
3
- version = "0.6.3"
3
+ version = "0.6.4"
4
4
  description = "Xsuite collimation package"
5
5
  authors = [
6
6
  {name="Frederik F. Van der Veken", email="frederik@cern.ch"},
@@ -25,7 +25,7 @@ dependencies = [
25
25
  "xobjects>=0.5.2",
26
26
  "xdeps>=0.10.6",
27
27
  "xpart>=0.23.1",
28
- "xtrack>=0.89.3",
28
+ "xtrack>=0.90.1",
29
29
  ]
30
30
 
31
31
  [project.optional-dependencies]
@@ -46,11 +46,11 @@ exclude = ["xcoll/lib", "xcoll/config"]
46
46
 
47
47
  [poetry.group.dev.dependencies]
48
48
  pytest = ">=7.3"
49
- xaux = ">=0.3.5"
49
+ xaux = ">=0.3.6"
50
50
 
51
51
  [build-system]
52
52
  # Needed for pip install -e (BTW: need pip version 22)
53
- requires = ["poetry-core>=1.0.8"]
53
+ requires = ["poetry-core>=2.0"]
54
54
  build-backend = "poetry.core.masonry.api"
55
55
 
56
56
  # pyproject.toml
@@ -0,0 +1,23 @@
1
+ // copyright ############################### #
2
+ // This file is part of the Xcoll package. #
3
+ // Copyright (c) CERN, 2025. #
4
+ // ######################################### #
5
+
6
+ #ifndef XCOLL_RF_SWEEP_H
7
+ #define XCOLL_RF_SWEEP_H
8
+
9
+ /*gpufun*/
10
+ void RFSweep_track_local_particle(RFSweepData el, LocalParticle* part0){
11
+ double const step = RFSweepData_get__rf_sweep_df_step(el); // L*df/(f0 + df)
12
+ int64_t const start_turn = RFSweepData_get_start_turn(el);
13
+ int64_t const stop_turn = RFSweepData_get_stop_turn(el);
14
+
15
+ //start_per_particle_block (part0->part)
16
+ int64_t at_turn = LocalParticle_get_at_turn(part);
17
+ if (at_turn >= start_turn && at_turn <= stop_turn){
18
+ LocalParticle_add_to_zeta(part, -(at_turn - start_turn + 1)*step);
19
+ }
20
+ //end_per_particle_block
21
+ }
22
+
23
+ #endif /* XCOLL_RF_SWEEP_H */
File without changes
@@ -12,5 +12,5 @@ citation = "F.F. Van der Veken, et al.: Recent Developments with the New Tools f
12
12
  # ======================
13
13
  # Do not change
14
14
  # ======================
15
- __version__ = '0.6.3'
15
+ __version__ = '0.6.4'
16
16
  # ======================
@@ -0,0 +1,42 @@
1
+ PSEUDOCODE for material interactions tracking in collimator
2
+ ===========================================================
3
+
4
+ - create DriftTrajectory from particle
5
+ - loop:
6
+ - find first crossing with collimator shape (segments)
7
+ - if distance larger than end of BeamElement -> move particle to exendit and break loop
8
+ - move particle to collimator impact point
9
+ - create MCSTrajectory from new particle
10
+ - loop:
11
+ - find first crossing with collimator shape (segments)
12
+ - do not move, but calculate path length
13
+ - compare to distance to nuclear interaction
14
+ - shortest wins (nuclear or exit)
15
+ - move to next point
16
+ - when at exit, create DriftTrajectory from particle
17
+
18
+
19
+
20
+ PSEUDOCODE for material interactions tracking in crystal
21
+ ========================================================
22
+
23
+ - create DriftTrajectory from particle
24
+ - loop:
25
+ - find first crossing with crystal shape (segments)
26
+ - if distance larger than end of BeamElement -> move particle to end and break loop
27
+ - move particle to crystal impact point
28
+ - create MCSTrajectory (if amorphous) or CircularTrajectory (if channelling) from new particle
29
+ - loop:
30
+ - find first crossing with crystal shape (segments)
31
+ - do not move, but calculate path length
32
+ - compare to distance to nuclear interaction and dechannelling
33
+ - shortest wins (nuclear, dechannelling, or exit)
34
+ - move to next point
35
+ - when at exit, create DriftTrajectory from particle
36
+
37
+
38
+ PSEUDOCODE for crossing finder
39
+ ==============================
40
+
41
+ - if DriftTrajectory and any segment
42
+ => use analytical
@@ -4,12 +4,13 @@
4
4
  # ######################################### #
5
5
 
6
6
  import numpy as np
7
+ from warnings import warn
7
8
  import scipy.constants as sc
8
9
 
9
10
  import xtrack as xt
10
11
 
11
12
 
12
- def prepare_rf_sweep(line, cavities=None, sweep=None, sweep_per_turn=None, num_turns=None):
13
+ def prepare_rf_sweep(line, *, cavities=None, sweep=None, sweep_per_turn=None, num_turns=None):
13
14
  rf_sweep = RFSweep(line=line, cavities=cavities)
14
15
  rf_sweep.prepare(sweep=sweep, sweep_per_turn=sweep_per_turn, num_turns=num_turns)
15
16
 
@@ -17,57 +18,63 @@ def prepare_rf_sweep(line, cavities=None, sweep=None, sweep_per_turn=None, num_t
17
18
  class RFSweep:
18
19
  def __init__(self, line, cavities=None):
19
20
  self.line = line
20
- if line._var_management is None:
21
- raise ValueError("Line must have a `var_management` to use RFSweep!" \
21
+ if line.env.ref_manager is None:
22
+ raise ValueError("Environment must have a `ref_manager` to use RFSweep!" \
22
23
  + "Do not use `optimize_for_tracking` as it will "
23
24
  + "disable expressions, which are needed for RFSweep.")
25
+ line.enable_time_dependent_vars = False # To be able to twiss in the prepare step
24
26
  self.env = line.env
25
27
  self.cavities = cavities
26
28
  self.env['rf_sweep_df'] = 0
29
+ self._prepared = False
27
30
 
28
31
  @property
29
32
  def current_sweep_value(self):
30
33
  return self.env['rf_sweep_df']
31
34
 
32
- def prepare(self, sweep=None, sweep_per_turn=None, num_turns=None):
33
- if sweep_per_turn is not None:
34
- if np.isclose(sweep_per_turn, 0):
35
- raise ValueError("Variable `sweep_per_turn` must be non-zero!")
36
- if sweep is not None:
37
- raise ValueError("Provide either `sweep` or `sweep_per_turn`, not both.")
38
- if num_turns is not None:
39
- raise ValueError("Variable `num_turns` cannot be set when using `sweep_per_turn`.")
40
- self.sweep_per_turn = sweep_per_turn
41
- elif sweep is not None:
42
- if np.isclose(sweep, 0):
43
- raise ValueError("Variable `sweep` must be non-zero!")
44
- if num_turns is None:
45
- num_turns = int(abs(sweep))
46
- if num_turns <= 0:
47
- raise ValueError("When using `sweep`, `num_turns` must be a positive integer.")
48
- self.sweep_per_turn = sweep / num_turns
49
- else:
50
- raise ValueError("Either `sweep` or `sweep_per_turn` must be provided.")
51
- self._get_cavity_data(self.sweep_per_turn)
52
- self._install_zeta_shift()
53
- self.tw = self.line.twiss()
54
- self.reset() # Initialize rf_sweep_df
55
- self.env['rf_sweep'].dzeta = f"{self.L} * rf_sweep_df / ({self.f_RF} + rf_sweep_df)"
56
- for cavs in self.cavities:
57
- for cav in cavs['names']:
58
- scale_factor = int(np.round(cavs['freq'] / self.f_RF))
59
- if scale_factor == 1:
60
- self.env.ref[cav].frequency += self.env.ref["rf_sweep_df"]
61
- else:
62
- self.env.ref[cav].frequency += scale_factor * self.env.ref["rf_sweep_df"]
63
- self.line.enable_time_dependent_vars = True
64
- print("Enabled time-dependent variables in the line.")
35
+ def prepare(self, *, sweep=None, num_turns=None, sweep_per_turn=None):
36
+ # TODO: if using sweep and num_turns, the sweep should stop after num_turns,
37
+ # but if using sweep_per_turn, it should continue indefinitely.
38
+ if not self._prepared:
39
+ if sweep_per_turn is not None:
40
+ if np.isclose(sweep_per_turn, 0):
41
+ raise ValueError("Variable `sweep_per_turn` must be non-zero!")
42
+ if sweep is not None:
43
+ raise ValueError("Provide either `sweep` or `sweep_per_turn`, not both.")
44
+ if num_turns is not None:
45
+ raise ValueError("Variable `num_turns` cannot be set when using `sweep_per_turn`.")
46
+ self.sweep_per_turn = sweep_per_turn
47
+ elif sweep is not None:
48
+ if np.isclose(sweep, 0):
49
+ raise ValueError("Variable `sweep` must be non-zero!")
50
+ if num_turns is None:
51
+ num_turns = int(abs(sweep))
52
+ if num_turns <= 0:
53
+ raise ValueError("When using `sweep`, `num_turns` must be a positive integer.")
54
+ self.sweep_per_turn = sweep / num_turns
55
+ else:
56
+ raise ValueError("Either `sweep` or `sweep_per_turn` must be provided.")
57
+ self._get_cavity_data()
58
+ self._install_zeta_shift()
59
+ self.tw = self.line.twiss()
60
+ self.reset() # Initialize rf_sweep_df
61
+ self.env['rf_sweep'].dzeta = f"{self.L} * rf_sweep_df / ({self.f_RF} + rf_sweep_df)"
62
+ for cavs in self.cavities:
63
+ for cav in cavs['names']:
64
+ scale_factor = int(np.round(cavs['freq'] / self.f_RF))
65
+ if scale_factor == 1:
66
+ self.env.ref[cav].frequency += self.env.ref["rf_sweep_df"]
67
+ else:
68
+ self.env.ref[cav].frequency += scale_factor * self.env.ref["rf_sweep_df"]
69
+ self.line.enable_time_dependent_vars = True
70
+ print("Enabled time-dependent variables in the line.")
71
+ self._prepared = True
65
72
 
66
73
 
67
74
  def reset(self):
68
75
  if self.sweep_per_turn is None:
69
76
  raise ValueError("RFSweep not prepared. Call `prepare` first.")
70
- t_turn = self.tw.T_rev0
77
+ t_turn = self.tw.T_rev0 # To start sweeping from turn 0
71
78
  current_time = self.env['t_turn_s']
72
79
  if current_time == 0:
73
80
  self.env['rf_sweep_df'] = f"(t_turn_s + {t_turn}) / {t_turn} * {self.sweep_per_turn}"
@@ -76,10 +83,12 @@ class RFSweep:
76
83
 
77
84
 
78
85
  def info(self, sweep=None, num_turns=None):
79
- if sweep is not None:
80
- raise DeprecationWarning("The `sweep` argument is deprecated.")
81
- if num_turns is not None:
82
- raise DeprecationWarning("The `num_turns` argument is deprecated.")
86
+ if sweep is not None or num_turns is not None:
87
+ if sweep is not None:
88
+ warn("The `sweep` argument is deprecated.", DeprecationWarning)
89
+ if num_turns is not None:
90
+ warn("The `num_turns` argument is deprecated.", DeprecationWarning)
91
+ self.prepare(sweep=sweep, num_turns=num_turns)
83
92
  if self.sweep_per_turn is None:
84
93
  raise ValueError("RFSweep not prepared. Call `prepare` first.")
85
94
  existing_sweep = self.current_sweep_value
@@ -98,8 +107,9 @@ class RFSweep:
98
107
  print(f"The current frequency is {self.f_RF + existing_sweep}Hz, adding "
99
108
  + f"{self.sweep_per_turn}Hz per turn.")
100
109
  print(f"This sweep will move the center of the bucket with \u0394\u03B4 = "
101
- + f"{delta_shift} per turn.")
102
- print(f"This implies one bucket shift every {bucket_turns} turns.")
110
+ + f"{delta_shift:.4} per turn.")
111
+ print(f"The bucket height is {bucket_height:.4}, so this implies the sweep "
112
+ + f"will shift one bucket every {round(bucket_turns, 2)} turns.")
103
113
  if self.tw.qs * bucket_turns < 3:
104
114
  print(f"Warning: This is a very fast sweep, moving ~1 bucket in "
105
115
  + f"~{round(self.tw.qs * bucket_turns, 2)} synchrotron oscillations "
@@ -110,11 +120,14 @@ class RFSweep:
110
120
 
111
121
  # For backward compatibility
112
122
  def track(self, sweep=0, particles=None, num_turns=0, verbose=True, *args, **kwargs):
113
- self.prepare(sweep, num_turns)
114
- self.line.track(particles=particles, *args, **kwargs)
123
+ warn("Using RFSweep.track() is deprecated. Please use RFSweep.prepare() "
124
+ + "and then xt.Line.track().", DeprecationWarning)
125
+ self.prepare(sweep=sweep, num_turns=num_turns)
126
+ self.line.track(particles=particles, num_turns=num_turns, *args, **kwargs)
115
127
 
116
128
 
117
- def _get_cavity_data(self, sweep):
129
+ def _get_cavity_data(self):
130
+ # Cavity data not yet extracted
118
131
  tt = self.line.get_table()
119
132
  tt_c = tt.rows[[nn for nn, ttt in zip(tt.name, tt.element_type)
120
133
  if 'Cavity' in ttt and 'CrabCavity' not in ttt]]
@@ -145,8 +158,8 @@ class RFSweep:
145
158
  raise ValueError(f"Cavity `{cav}` not found in the line!")
146
159
  idx = np.argsort(freq)
147
160
  boundaries = np.where(~np.isclose(freq[idx][1:], freq[idx][:-1],
148
- rtol=1e-8, atol=1e-12)
149
- )[0] + 1
161
+ rtol=1e-8, atol=1e-12)
162
+ )[0] + 1
150
163
  groups = []
151
164
  for gidx in np.split(idx, boundaries):
152
165
  groups.append({
@@ -168,10 +181,9 @@ class RFSweep:
168
181
  print("Found multiple cavities with different frequencies:")
169
182
  for g in self.cavities:
170
183
  print(f"{g['freq']}Hz at {g['voltage']}V: {g['names']}")
171
- print(r"The sweep ($\Delta f$ = " + f"{sweep}Hz per turn) will be "
172
- + f"performed with respect to the highest voltage cavity at "
173
- + f"{self.f_RF}Hz. The other cavities will be shifted "
174
- + f"accordingly.")
184
+ print(r"The sweep will be performed with respect to the highest "
185
+ + f"voltage cavity at {self.f_RF}Hz. The other cavities will "
186
+ + f"be shifted accordingly.")
175
187
 
176
188
 
177
189
  def _install_zeta_shift(self):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes