xcoll 0.6.1__py3-none-any.whl → 0.6.3__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.

Files changed (90) hide show
  1. xcoll/__init__.py +1 -1
  2. xcoll/general.py +1 -1
  3. xcoll/prebuild_kernels/__init__.py +7 -0
  4. xcoll/prebuild_kernels/element_inits.py +6 -0
  5. xcoll/prebuild_kernels/elements.py +20 -0
  6. xcoll/rf_sweep.py +158 -173
  7. {xcoll-0.6.1.dist-info → xcoll-0.6.3.dist-info}/METADATA +18 -13
  8. xcoll-0.6.3.dist-info/RECORD +65 -0
  9. {xcoll-0.6.1.dist-info → xcoll-0.6.3.dist-info}/WHEEL +1 -1
  10. xcoll-0.6.3.dist-info/entry_points.txt +3 -0
  11. xcoll/__init__.py.orig +0 -26
  12. xcoll/general.py.orig +0 -20
  13. xcoll/initial_distribution.py.orig +0 -256
  14. xcoll/scattering_routines/fluka/flukaio/.git +0 -1
  15. xcoll/scattering_routines/fluka/flukaio/.gitignore +0 -2
  16. xcoll/scattering_routines/fluka/flukaio/CMakeLists.txt +0 -18
  17. xcoll/scattering_routines/fluka/flukaio/ComponentMakefile +0 -192
  18. xcoll/scattering_routines/fluka/flukaio/Makefile +0 -144
  19. xcoll/scattering_routines/fluka/flukaio/README +0 -26
  20. xcoll/scattering_routines/fluka/flukaio/doc/Doxyfile +0 -1551
  21. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO.asciidoc +0 -1054
  22. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO.epub +0 -0
  23. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO.html +0 -1607
  24. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO.pdf +0 -0
  25. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO__1.png +0 -0
  26. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO__2.png +0 -0
  27. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO__3.png +0 -0
  28. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO__4.png +0 -0
  29. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO__5.png +0 -0
  30. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO__6.png +0 -0
  31. xcoll/scattering_routines/fluka/flukaio/doc/FlukaIO__7.png +0 -0
  32. xcoll/scattering_routines/fluka/flukaio/doc/Makefile +0 -8
  33. xcoll/scattering_routines/fluka/flukaio/doc/docbook.xsl +0 -1690
  34. xcoll/scattering_routines/fluka/flukaio/include/Connection.h +0 -79
  35. xcoll/scattering_routines/fluka/flukaio/include/FlukaIO.h +0 -58
  36. xcoll/scattering_routines/fluka/flukaio/include/FlukaIOServer.h +0 -33
  37. xcoll/scattering_routines/fluka/flukaio/include/FortranFlukaIO.h +0 -277
  38. xcoll/scattering_routines/fluka/flukaio/include/Message.h +0 -89
  39. xcoll/scattering_routines/fluka/flukaio/include/ParticleInfo.h +0 -76
  40. xcoll/scattering_routines/fluka/flukaio/lib/libFlukaIO64.a +0 -0
  41. xcoll/scattering_routines/fluka/flukaio/lib/libFlukaIO64.so +0 -0
  42. xcoll/scattering_routines/fluka/flukaio/samples/ClientTest.c +0 -156
  43. xcoll/scattering_routines/fluka/flukaio/samples/ServerTest.c +0 -123
  44. xcoll/scattering_routines/fluka/flukaio/samples/fclient.f +0 -149
  45. xcoll/scattering_routines/fluka/flukaio/samples/fserver.f +0 -118
  46. xcoll/scattering_routines/fluka/flukaio/src/Connection.c +0 -264
  47. xcoll/scattering_routines/fluka/flukaio/src/Connection.d +0 -69
  48. xcoll/scattering_routines/fluka/flukaio/src/Connection.o +0 -0
  49. xcoll/scattering_routines/fluka/flukaio/src/FlukaIO.c +0 -211
  50. xcoll/scattering_routines/fluka/flukaio/src/FlukaIO.d +0 -46
  51. xcoll/scattering_routines/fluka/flukaio/src/FlukaIO.o +0 -0
  52. xcoll/scattering_routines/fluka/flukaio/src/FlukaIOHandshake.c +0 -45
  53. xcoll/scattering_routines/fluka/flukaio/src/FlukaIOHandshake.d +0 -29
  54. xcoll/scattering_routines/fluka/flukaio/src/FlukaIOHandshake.h +0 -17
  55. xcoll/scattering_routines/fluka/flukaio/src/FlukaIOHandshake.o +0 -0
  56. xcoll/scattering_routines/fluka/flukaio/src/FlukaIOServer.c +0 -84
  57. xcoll/scattering_routines/fluka/flukaio/src/FlukaIOServer.d +0 -70
  58. xcoll/scattering_routines/fluka/flukaio/src/FlukaIOServer.o +0 -0
  59. xcoll/scattering_routines/fluka/flukaio/src/FlukaIOServer_private.h +0 -22
  60. xcoll/scattering_routines/fluka/flukaio/src/FlukaIO_private.h +0 -16
  61. xcoll/scattering_routines/fluka/flukaio/src/FortranFlukaIO.c +0 -533
  62. xcoll/scattering_routines/fluka/flukaio/src/FortranFlukaIO.d +0 -40
  63. xcoll/scattering_routines/fluka/flukaio/src/FortranFlukaIO.o +0 -0
  64. xcoll/scattering_routines/fluka/flukaio/src/NetIO.c +0 -304
  65. xcoll/scattering_routines/fluka/flukaio/src/NetIO.d +0 -66
  66. xcoll/scattering_routines/fluka/flukaio/src/NetIO.h +0 -30
  67. xcoll/scattering_routines/fluka/flukaio/src/NetIO.o +0 -0
  68. xcoll/scattering_routines/fluka/flukaio/src/tags +0 -167
  69. xcoll/scattering_routines/fluka/flukaio/tests/AllTests.cpp +0 -8
  70. xcoll/scattering_routines/fluka/flukaio/tests/CommonTest.h +0 -10
  71. xcoll/scattering_routines/fluka/flukaio/tests/ConnectionTest.cpp +0 -99
  72. xcoll/scattering_routines/fluka/flukaio/tests/FlukaIOServerTest.cpp +0 -104
  73. xcoll/scattering_routines/fluka/flukaio/tests/FlukaIOTest.cpp +0 -439
  74. xcoll/scattering_routines/fluka/flukaio/tests/FortranFlukaIOTest.cpp +0 -682
  75. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeConnection.c +0 -19
  76. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeConnection.h +0 -16
  77. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeFlukaIO.c +0 -74
  78. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeFlukaIO.h +0 -50
  79. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeFlukaIOHandshake.c +0 -16
  80. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeFlukaIOHandshake.h +0 -20
  81. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeFlukaIOServer.c +0 -12
  82. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeFlukaIOServer.h +0 -18
  83. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeFortranFlukaIO.h +0 -19
  84. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeNetIO.c +0 -80
  85. xcoll/scattering_routines/fluka/flukaio/tests/fakes/FakeNetIO.h +0 -35
  86. xcoll-0.6.1.dist-info/LICENSE +0 -201
  87. xcoll-0.6.1.dist-info/NOTICE +0 -2
  88. xcoll-0.6.1.dist-info/RECORD +0 -138
  89. /LICENSE → /xcoll-0.6.3.dist-info/LICENSE +0 -0
  90. /NOTICE → /xcoll-0.6.3.dist-info/NOTICE +0 -0
xcoll/__init__.py CHANGED
@@ -11,7 +11,7 @@ from .beam_elements import BlackAbsorber, BlackCrystal, TransparentCollimator, T
11
11
  from .scattering_routines.everest import materials, Material, CrystalMaterial
12
12
  from .colldb import CollimatorDatabase
13
13
  from .interaction_record import InteractionRecord
14
- from .rf_sweep import RFSweep
14
+ from .rf_sweep import RFSweep, prepare_rf_sweep
15
15
  from .lossmap import LossMap, MultiLossMap
16
16
 
17
17
 
xcoll/general.py CHANGED
@@ -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.1'
15
+ __version__ = '0.6.3'
16
16
  # ======================
@@ -0,0 +1,7 @@
1
+ # copyright ############################### #
2
+ # This file is part of the Xcoll package. #
3
+ # Copyright (c) CERN, 2025. #
4
+ # ######################################### #
5
+
6
+ from .elements import DEFAULT_XCOLL_ELEMENTS
7
+ from .element_inits import XCOLL_ELEMENTS_INIT_DEFAULTS
@@ -0,0 +1,6 @@
1
+ # copyright ############################### #
2
+ # This file is part of the Xcoll package. #
3
+ # Copyright (c) CERN, 2025. #
4
+ # ######################################### #
5
+
6
+ XCOLL_ELEMENTS_INIT_DEFAULTS = {}
@@ -0,0 +1,20 @@
1
+ # copyright ############################### #
2
+ # This file is part of the Xcoll package. #
3
+ # Copyright (c) CERN, 2025. #
4
+ # ######################################### #
5
+
6
+ from ..beam_elements import *
7
+
8
+
9
+ DEFAULT_XCOLL_ELEMENTS = [
10
+ BlackAbsorber,
11
+ BlackCrystal,
12
+ TransparentCollimator,
13
+ TransparentCrystal,
14
+ EverestBlock,
15
+ EverestCollimator,
16
+ EverestCrystal,
17
+ BlowUp,
18
+ # ParticleStatsMonitor,
19
+ EmittanceMonitor
20
+ ]
xcoll/rf_sweep.py CHANGED
@@ -1,197 +1,182 @@
1
1
  # copyright ############################### #
2
2
  # This file is part of the Xcoll package. #
3
- # Copyright (c) CERN, 2024. #
3
+ # Copyright (c) CERN, 2025. #
4
4
  # ######################################### #
5
5
 
6
6
  import numpy as np
7
7
  import scipy.constants as sc
8
- from time import perf_counter
9
8
 
10
9
  import xtrack as xt
11
- from xtrack.progress_indicator import progress
12
10
 
13
- class RFSweep:
14
11
 
15
- def __init__(self, line):
16
- self.line = line
17
- self._get_base_frequency()
18
- self._install_zeta_shift()
19
- self.reset()
20
-
21
- def _get_base_frequency(self):
22
- self.cavities = self.line.get_elements_of_type(xt.Cavity)[1]
23
- freq = np.unique([round(self.line[cav].frequency, 9) for cav in self.cavities])
24
- if len(freq) > 1:
25
- raise NotImplementedError(f"Cannot sweep multiple cavities with different frequencies!")
26
- elif abs(freq[0]) < 1e-9 :
27
- raise ValueError(f"Cavity frequency not set!")
28
- self.f_RF = freq[0]
29
- phi = np.unique(np.array([self.line[cav].lag for cav in self.cavities])*np.pi/180.)
30
- if len(phi) > 1:
31
- raise NotImplementedError(f"Cannot sweep multiple cavities with different phases!")
32
- self.phi = phi[0]
33
- self.V = np.array([self.line[cav].voltage for cav in self.cavities]).sum()
34
- self.L = self.line.get_length()
12
+ def prepare_rf_sweep(line, cavities=None, sweep=None, sweep_per_turn=None, num_turns=None):
13
+ rf_sweep = RFSweep(line=line, cavities=cavities)
14
+ rf_sweep.prepare(sweep=sweep, sweep_per_turn=sweep_per_turn, num_turns=num_turns)
35
15
 
36
- def _install_zeta_shift(self):
37
- if 'rf_sweep' in self.line.element_names:
38
- print(f"Found existing RF sweep in line.")
39
- else:
40
- s_cav = min([self.line.get_s_position(cav) for cav in self.cavities])
41
- if self.line.tracker is not None:
42
- self.line.unfreeze()
43
- line_was_built = True
44
- else:
45
- line_was_built = False
46
- self.line.insert_element(element=xt.ZetaShift(dzeta=0), name='rf_sweep', at_s=s_cav)
47
- if line_was_built:
48
- self.line.build_tracker()
16
+
17
+ class RFSweep:
18
+ def __init__(self, line, cavities=None):
19
+ self.line = line
20
+ if line._var_management is None:
21
+ raise ValueError("Line must have a `var_management` to use RFSweep!" \
22
+ + "Do not use `optimize_for_tracking` as it will "
23
+ + "disable expressions, which are needed for RFSweep.")
24
+ self.env = line.env
25
+ self.cavities = cavities
26
+ self.env['rf_sweep_df'] = 0
49
27
 
50
28
  @property
51
29
  def current_sweep_value(self):
52
- dzeta = self.line['rf_sweep'].dzeta
53
- return round(self.f_RF * dzeta/(self.L-dzeta), 6)
54
-
55
-
56
- def info(self, sweep=0, num_turns=0):
57
- if abs(sweep) > 1e-9:
58
- existing_sweep = self.current_sweep_value
59
-
60
- beta0 = self.line.particle_ref.beta0[0]
61
- E = self.line.particle_ref.energy0[0]
62
- q = self.line.particle_ref.q0
63
- h = self.f_RF * self.L / beta0 / sc.c
64
- tw = self.line.twiss()
65
- eta = tw.slip_factor
66
-
67
- bucket_height = np.sqrt(abs(q*self.V*beta0**2 / (np.pi*h*eta*E) * (
68
- 2*np.cos(self.phi) + (2*self.phi-np.pi)*np.sin(self.phi)
69
- )))
70
- delta_shift = -sweep / self.f_RF / eta
71
- bucket_shift = delta_shift / bucket_height / 2
72
- if num_turns > 0:
73
- rf_shift_per_turn = sweep / num_turns
74
- print(f"The current frequency is {self.f_RF + existing_sweep}Hz, adding {rf_shift_per_turn}Hz "
75
- + f"per turn until {self.f_RF + existing_sweep + sweep} (for {num_turns} turns).")
76
- print(f"This sweep will move the center of the bucket with \u0394\u03B4 = "
77
- + f"{delta_shift} ({bucket_shift} buckets).")
78
- if num_turns > 0 and num_turns < 3*bucket_shift/tw.qs:
79
- print(f"Warning: This is a very fast sweep, moving ~{round(bucket_shift, 2)} buckets in "
80
- + f"~{round(num_turns*tw.qs, 2)} synchrotron oscillations (on average). If the "
81
- + f"bucket moves faster than a particle can follow, that particle will move out of "
82
- + f"the bucket and remain uncaptured.")
83
-
84
-
85
- def track(self, sweep=0, particles=None, num_turns=0, verbose=True, *args, **kwargs):
86
-
87
- # Was there a previous sweep?
88
- # If yes, we do not overwrite it but continue from there
89
- existing_sweep = self.current_sweep_value
30
+ return self.env['rf_sweep_df']
31
+
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.")
90
65
 
91
- # Just set the new RF frequency, no tracking
92
- if num_turns == 0:
93
- sweep += existing_sweep
94
- if verbose:
95
- print(f"The current frequency is {self.f_RF + existing_sweep}Hz, moving to {self.f_RF + sweep}Hz."
96
- + "No tracking performed.")
97
- self.line['rf_sweep'].dzeta = self.L * sweep / (self.f_RF + sweep)
98
66
 
99
- # Sweep and track
67
+ def reset(self):
68
+ if self.sweep_per_turn is None:
69
+ raise ValueError("RFSweep not prepared. Call `prepare` first.")
70
+ t_turn = self.tw.T_rev0
71
+ current_time = self.env['t_turn_s']
72
+ if current_time == 0:
73
+ self.env['rf_sweep_df'] = f"(t_turn_s + {t_turn}) / {t_turn} * {self.sweep_per_turn}"
100
74
  else:
101
- if self.line.tracker is None:
102
- raise ValueError("Need to build tracker first!")
103
- if particles is None:
104
- raise ValueError("Need particles to track!")
105
- time = kwargs.pop('time', False)
106
- with_progress = kwargs.pop('with_progress', False)
107
- rf_shift_per_turn = sweep / num_turns
108
-
109
- # This is taken from xtrack.tracker.Tracker._track
110
- if time:
111
- t0 = perf_counter()
112
- if with_progress:
113
- if self.line.tracker.enable_pipeline_hold:
114
- raise ValueError("Progress indicator is not supported with pipeline hold")
115
- if num_turns < 2:
116
- raise ValueError('Tracking with progress indicator is only '
117
- 'possible over more than one turn.')
118
- if with_progress is True:
119
- batch_size = scaling = 100
120
- else:
121
- batch_size = int(with_progress)
122
- scaling = with_progress if batch_size > 1 else None
123
- if kwargs.get('turn_by_turn_monitor') is True:
124
- ele_start = kwargs.get('ele_start') or 0
125
- ele_stop = kwargs.get('ele_stop')
126
- if ele_stop is None:
127
- ele_stop = len(self.line)
128
- if ele_start >= ele_stop:
129
- # we need an additional turn and space in the monitor for
130
- # the incomplete turn
131
- num_turns += 1
132
- _, monitor, _, _ = self.line.tracker._get_monitor(particles, True, num_turns)
133
- kwargs['turn_by_turn_monitor'] = monitor
134
-
135
- for ii in progress(
136
- range(0, num_turns, batch_size),
137
- desc='Tracking',
138
- unit_scale=scaling,
139
- ):
140
- one_turn_kwargs = kwargs.copy()
141
- is_first_batch = ii == 0
142
- is_last_batch = ii + batch_size >= num_turns
143
-
144
- if is_first_batch and is_last_batch:
145
- # This is the only batch, we track as normal
146
- pass
147
- elif is_first_batch:
148
- # Not the last batch, so track until the last element
149
- one_turn_kwargs['ele_stop'] = None
150
- one_turn_kwargs['num_turns'] = batch_size
151
- elif is_last_batch:
152
- # Not the first batch, so track from the first element
153
- one_turn_kwargs['ele_start'] = None
154
- remaining_turns = num_turns % batch_size
155
- if remaining_turns == 0:
156
- remaining_turns = batch_size
157
- one_turn_kwargs['num_turns'] = remaining_turns
158
- one_turn_kwargs['_reset_log'] = False
159
- elif not is_first_batch and not is_last_batch:
160
- # A 'middle batch', track from first to last element
161
- one_turn_kwargs['num_turns'] = batch_size
162
- one_turn_kwargs['ele_start'] = None
163
- one_turn_kwargs['ele_stop'] = None
164
- one_turn_kwargs['_reset_log'] = False
165
- self._tracking_func(particles, rf_shift_per_turn, **one_turn_kwargs)
166
- if not np.any(particles.state == 1):
167
- break
75
+ self.env['rf_sweep_df'] = f"(t_turn_s - {current_time} + {t_turn}) / {t_turn} * {self.sweep_per_turn}"
168
76
 
169
- else:
170
- self._tracking_func(particles, rf_shift_per_turn, num_turns=num_turns, *args, **kwargs)
171
77
 
172
- if not np.any(particles.state == 1):
173
- print(f"All particles lost at turn {particles.at_turn.max()}, stopped sweep at "
174
- + f"{self.current_sweep_value}Hz.")
78
+ 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.")
83
+ if self.sweep_per_turn is None:
84
+ raise ValueError("RFSweep not prepared. Call `prepare` first.")
85
+ existing_sweep = self.current_sweep_value
175
86
 
176
- if time:
177
- t1 = perf_counter()
178
- self.line.tracker._context.synchronize()
179
- self.line.tracker.time_last_track = t1 - t0
180
- else:
181
- self.line.tracker.time_last_track = None
87
+ beta0 = self.line.particle_ref.beta0[0]
88
+ E = self.line.particle_ref.energy0[0]
89
+ q = self.line.particle_ref.q0
90
+ h = self.f_RF * self.L / beta0 / sc.c
91
+ eta = self.tw.slip_factor
92
+
93
+ bucket_height = np.sqrt(abs(q*self.V*beta0**2 / (np.pi*h*eta*E) * (
94
+ 2*np.cos(self.phi) + (2*self.phi-np.pi)*np.sin(self.phi)
95
+ )))
96
+ delta_shift = -self.sweep_per_turn / self.f_RF / eta
97
+ bucket_turns = bucket_height * 2 / abs(delta_shift)
98
+ print(f"The current frequency is {self.f_RF + existing_sweep}Hz, adding "
99
+ + f"{self.sweep_per_turn}Hz per turn.")
100
+ 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.")
103
+ if self.tw.qs * bucket_turns < 3:
104
+ print(f"Warning: This is a very fast sweep, moving ~1 bucket in "
105
+ + f"~{round(self.tw.qs * bucket_turns, 2)} synchrotron oscillations "
106
+ + f"(on average). If the bucket moves faster than a particle "
107
+ + f"can follow, that particle will move out of the bucket and "
108
+ + f"remain uncaptured.")
109
+
110
+
111
+ # For backward compatibility
112
+ 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)
182
115
 
183
116
 
184
- def reset(self):
185
- self.line['rf_sweep'].dzeta = 0
117
+ def _get_cavity_data(self, sweep):
118
+ tt = self.line.get_table()
119
+ tt_c = tt.rows[[nn for nn, ttt in zip(tt.name, tt.element_type)
120
+ if 'Cavity' in ttt and 'CrabCavity' not in ttt]]
121
+ mask = tt_c.parent_name == None # Unsliced cavities
122
+ if self.cavities is None:
123
+ self.cavities = np.unique(list(tt_c.name[mask]) + list(tt_c.parent_name[~mask]))
124
+ else:
125
+ if isinstance(self.cavities, str):
126
+ self.cavities = [self.cavities]
127
+ for cav in self.cavities:
128
+ if cav not in self.env.elements:
129
+ raise ValueError(f"Cavity `{cav}` not found in environment!")
130
+ if len(self.cavities) == 0:
131
+ raise ValueError("No cavities found in the line!")
132
+ freq = np.array([self.env[cav].frequency for cav in self.cavities])
133
+ volt = np.array([self.env[cav].voltage for cav in self.cavities])
134
+ lag = np.array([self.env[cav].lag for cav in self.cavities])
135
+ s_pos = []
136
+ name_first_in_line = []
137
+ for cav in self.cavities:
138
+ if cav in tt_c.name:
139
+ s_pos.append(tt_c.rows[cav].s_start[0])
140
+ name_first_in_line.append(cav)
141
+ elif cav in tt_c.parent_name:
142
+ s_pos.append(tt_c.rows[tt_c.parent_name == cav].s_start.min())
143
+ name_first_in_line.append(tt_c.rows[tt_c.parent_name == cav].name[0])
144
+ else:
145
+ raise ValueError(f"Cavity `{cav}` not found in the line!")
146
+ idx = np.argsort(freq)
147
+ boundaries = np.where(~np.isclose(freq[idx][1:], freq[idx][:-1],
148
+ rtol=1e-8, atol=1e-12)
149
+ )[0] + 1
150
+ groups = []
151
+ for gidx in np.split(idx, boundaries):
152
+ groups.append({
153
+ 'names': self.cavities[gidx],
154
+ 'freq': np.mean(freq[gidx]),
155
+ 'voltage': volt[gidx].sum(),
156
+ 's_pos': np.array(s_pos)[gidx],
157
+ 'lag': lag[gidx],
158
+ 'name_first_in_line': np.array(name_first_in_line)[gidx],
159
+ })
160
+ self.cavities = sorted(groups, key=lambda g: (g['voltage'], g['freq']), reverse=True)
161
+ if np.isclose(self.cavities[0]['voltage'], 0):
162
+ raise ValueError("No active cavity found!")
163
+ self.f_RF = self.cavities[0]['freq']
164
+ self.phi = np.deg2rad(self.cavities[0]['lag'].mean())
165
+ self.V = self.cavities[0]['voltage']
166
+ self.L = self.line.get_length()
167
+ if len(self.cavities) > 1:
168
+ print("Found multiple cavities with different frequencies:")
169
+ for g in self.cavities:
170
+ 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.")
186
175
 
187
176
 
188
- def _tracking_func(self, particles, rf_shift_per_turn, num_turns=1, *args, **kwargs):
189
- existing_sweep = self.current_sweep_value
190
- for i in range(num_turns):
191
- sweep = existing_sweep + i*rf_shift_per_turn
192
- self.line['rf_sweep'].dzeta = self.L * sweep / (self.f_RF + sweep)
193
- # for cav in cavities:
194
- # self.line[cav].frequency = freq + sweep
195
- self.line.track(particles, num_turns=1, *args, **kwargs)
196
- if not np.any(particles.state == 1):
197
- break
177
+ def _install_zeta_shift(self):
178
+ if 'rf_sweep' not in self.env.elements:
179
+ idx = np.argsort(self.cavities[0]['s_pos'])
180
+ first_cavity = self.cavities[0]['name_first_in_line'][idx[0]]
181
+ self.env.elements['rf_sweep'] = xt.ZetaShift(dzeta=0)
182
+ self.line.insert('rf_sweep', at=f'{first_cavity}@start')
@@ -1,28 +1,33 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: xcoll
3
- Version: 0.6.1
3
+ Version: 0.6.3
4
4
  Summary: Xsuite collimation package
5
- Home-page: https://github.com/xsuite/xcoll
6
- License: Apache 2.0
5
+ License: Apache-2.0
7
6
  Author: Frederik F. Van der Veken
8
7
  Author-email: frederik@cern.ch
9
- Requires-Python: >=3.8
10
- Classifier: License :: Other/Proprietary License
8
+ Requires-Python: >=3.10
9
+ Classifier: License :: OSI Approved :: Apache Software License
11
10
  Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.8
13
- Classifier: Programming Language :: Python :: 3.9
14
11
  Classifier: Programming Language :: Python :: 3.10
15
12
  Classifier: Programming Language :: Python :: 3.11
16
13
  Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
17
15
  Provides-Extra: tests
18
16
  Requires-Dist: numpy (>=1.0)
19
17
  Requires-Dist: pandas (>=1.4)
20
- Requires-Dist: ruamel-yaml (>=0.17.31,<0.18.0) ; extra == "tests"
21
- Requires-Dist: xdeps (>=0.10.5)
22
- Requires-Dist: xobjects (>=0.5.0)
23
- Requires-Dist: xpart (>=0.23.0)
24
- Requires-Dist: xtrack (>=0.84.6)
18
+ Requires-Dist: pytest ; extra == "tests"
19
+ Requires-Dist: pytest-html ; extra == "tests"
20
+ Requires-Dist: pytest-xdist ; extra == "tests"
21
+ Requires-Dist: ruamel-yaml (>=0.17.31,<0.18.15)
22
+ Requires-Dist: xdeps (>=0.10.6)
23
+ Requires-Dist: xobjects (>=0.5.2)
24
+ Requires-Dist: xpart (>=0.23.1)
25
+ Requires-Dist: xtrack (>=0.89.3)
26
+ Project-URL: Bug Tracker, https://github.com/xsuite/xsuite/issues
27
+ Project-URL: Documentation, https://xsuite.readthedocs.io/
28
+ Project-URL: Homepage, https://github.com/xsuite/xcoll
25
29
  Project-URL: Repository, https://github.com/xsuite/xcoll
30
+ Project-URL: download, https://pypi.python.org/pypi/xcoll
26
31
  Description-Content-Type: text/markdown
27
32
 
28
33
  # xcoll
@@ -0,0 +1,65 @@
1
+ xcoll/__init__.py,sha256=7qEja96thydS08Q1IVdLeeT3VslAZ1OQbGzXJ96euVE,872
2
+ xcoll/beam_elements/__init__.py,sha256=qu2-LefWfEKZHfALGqZo97DTrwdZVh7Sp97V-3XokJU,1189
3
+ xcoll/beam_elements/absorber.py,sha256=Gw1l1ng1MqF0dRTk7YhkiPAoinS5xsTASMxMDWGsmTw,2842
4
+ xcoll/beam_elements/base.py,sha256=mjnzLbZ-GC56N56Eq5r5oQB8cLmeaqR5oEH1-FnS_H4,57816
5
+ xcoll/beam_elements/blowup.py,sha256=0jfuxaIwXsEY4e6DlzGmv29OY7DGRKhbb2L-qKJwImQ,8079
6
+ xcoll/beam_elements/elements_src/black_absorber.h,sha256=AXs_bNLaK8xBl8IeLJvGz7AfFaasruPMtYz8lbRtqG4,4705
7
+ xcoll/beam_elements/elements_src/black_crystal.h,sha256=ZlLkJec4_naeoS3jEx-vQVAKBI0dInzMZq06pzKQOn0,4355
8
+ xcoll/beam_elements/elements_src/blowup.h,sha256=YlTt7YxswLM0ZjPuEjuE7xzjQ3hMt6FX9V3MbqVYmN4,1564
9
+ xcoll/beam_elements/elements_src/emittance_monitor.h,sha256=vlHzQFoUjKQHWBmzpaSzRbILtxSWqEasMtxHC-FFoAc,7078
10
+ xcoll/beam_elements/elements_src/everest_block.h,sha256=ITSzfiqwm8ZNIkAj_odQkAjKhPcdT8b0AUlq_uxtsqI,6562
11
+ xcoll/beam_elements/elements_src/everest_collimator.h,sha256=fkD5GazVv2zlmqyb6s9zVNMq6baXeFb_pf7gg9TKjNc,9787
12
+ xcoll/beam_elements/elements_src/everest_crystal.h,sha256=LISp_9NEWMIi5GvZ3LwPfeSbmsbXvHWcTqxW6eCCsiE,11951
13
+ xcoll/beam_elements/elements_src/transparent_collimator.h,sha256=pA_Fxx85N87iSbpHSjR2OSOx6JN9e38T1pOUKrC7zxs,4610
14
+ xcoll/beam_elements/elements_src/transparent_crystal.h,sha256=DGX4uL0hpm4njOypoPuEWtMzYxnL9jQkf2ZrGaS0alI,4128
15
+ xcoll/beam_elements/everest.py,sha256=iJva_S0OQnmG-qj7rIAiUCssu5WL_Qs5P_n6Qx-IWzo,9080
16
+ xcoll/beam_elements/monitor.py,sha256=baMYT_PNya8KX35ReeMwk5Cm04ePUqiDF_s69L5GTX0,16968
17
+ xcoll/beam_elements/transparent.py,sha256=AZOWfH3dvsetL6DjQGejUgX7T18e_3omIIffG_1gwc0,2894
18
+ xcoll/colldb.py,sha256=WaJC6gkDNVvxo65OhucTM6Fwo6pgRFHNnBnHSkiX7AQ,31054
19
+ xcoll/general.py,sha256=4ksyfjB_QTQ5LHe22beup0CS-e0tu2HDyDX7yuwZxDM,534
20
+ xcoll/headers/checks.h,sha256=qdXsOTBOK1MwW6bdFF93j4yE648mcDtEv5rGN1w9sfk,1582
21
+ xcoll/headers/particle_states.py,sha256=N8ehLtg99358I4RGCJ3sjuKCk2LVdGqgVx2xGoHrRdM,1959
22
+ xcoll/initial_distribution.py,sha256=CHhqeCVjVOyaBWhfy2sDgLwIgtXZoqcTW-su-M2YByE,10989
23
+ xcoll/interaction_record/__init__.py,sha256=UFoLiKa-z2oX7YoszP-7Vgdt1nM6kT382v1CaIu8_u0,50
24
+ xcoll/interaction_record/interaction_record.py,sha256=cCjfVCYUJaV0Y-pCljA2_u8GLyhHt7zNjbSXkE7cRO4,13299
25
+ xcoll/interaction_record/interaction_record_src/interaction_record.h,sha256=0rNagnfSGc2i1jauOMIcDbj9QFic9dV_MOyqVx1kw5Q,6067
26
+ xcoll/interaction_record/interaction_types.py,sha256=XTeg2dcImMpqhTqzkJKh6JYam2v9gUMhED-dDKLsilk,2894
27
+ xcoll/line_tools.py,sha256=JBySkKKZ-RGumqAZF_8PSQ3OV0M87P78NeQgbXAdFc4,16699
28
+ xcoll/lossmap.py,sha256=HLdhej9tUjk36T5BulVWurJtfiNa61L_1X7-8kT6JoQ,28407
29
+ xcoll/plot.py,sha256=27fYdXstPg3o8XyeBlPuD2yz0GR3dKkNWy4kO2BD9WA,4071
30
+ xcoll/prebuild_kernels/__init__.py,sha256=HITO-StW6e3GujTvLzEFz2Y8bMDGnavVttwixVPgA-M,286
31
+ xcoll/prebuild_kernels/element_inits.py,sha256=9Qm34JXN7F08inWzXP6g6DU57ypRbyqHYwPK9Oc9BC4,219
32
+ xcoll/prebuild_kernels/elements.py,sha256=7P5cxZgjfeNmUNuDer372KgtjmhH39Kk1wReyKMhqig,456
33
+ xcoll/rf_sweep.py,sha256=Rrx4SmvKq4cmrfCU_Cetqmzp8c_uVa_QpXU4_rt4k_U,8611
34
+ xcoll/scattering_routines/engine.py,sha256=1VCBEZLMd5orFo3sZqK51NrqbqELBVrbsz6bB2SXsFQ,22962
35
+ xcoll/scattering_routines/environment.py,sha256=xZ8A7XfvSfpe8vYbM5oD5qbcp8Tuag5qWAI6VqgGUlA,12033
36
+ xcoll/scattering_routines/everest/__init__.py,sha256=7lkkeZ1liBjXVHCuRpgzZI6ohzHVMj5uJBO792147XY,286
37
+ xcoll/scattering_routines/everest/amorphous.h,sha256=8v_5P94LDxeLp1xI2nvwdbEPJNDY6LTB1CwXv4AwjZs,11806
38
+ xcoll/scattering_routines/everest/channelling.h,sha256=WrYBcvGWP2Da47__AGbbKsT8yvZmHhVZd5F1gku--GU,10941
39
+ xcoll/scattering_routines/everest/constants.h,sha256=_y9QqKAUSwPOkk8A4BF8ILNdDDJf66eINJwda8skwZM,1380
40
+ xcoll/scattering_routines/everest/crystal_parameters.h,sha256=QtmSQM4qzVXfjdkxs0ns8utqtqZ_u-Ej_y6m7UOKITo,6001
41
+ xcoll/scattering_routines/everest/everest.h,sha256=T9mESIy_oC86WJSsU7LY_A0iqHT2PKl5MmhnKQaGVSg,3200
42
+ xcoll/scattering_routines/everest/everest.py,sha256=aKy5d7HGiqEphFZDZE4RnYbxh0j10Boc04EZ0By9WdM,1542
43
+ xcoll/scattering_routines/everest/ionisation_loss.h,sha256=QIujj_qrKOY7L7CVFNSyexjlDJ94sfilvakhfWVfe44,6108
44
+ xcoll/scattering_routines/everest/jaw.h,sha256=4Ml9FofWPkGlvw6oWNdbZQIYV4K1xhfbEkNwwfDcITc,2069
45
+ xcoll/scattering_routines/everest/materials.py,sha256=pKQfrMNrqU3sitICTRjqfvwsvHrBDSUf3jfmOEE5Kls,10292
46
+ xcoll/scattering_routines/everest/multiple_coulomb_scattering.h,sha256=oX_ZN32eLcZX3VdYn4kAnT5wMKVTe4fLudPgbX9w37Y,5434
47
+ xcoll/scattering_routines/everest/nuclear_interaction.h,sha256=07yg9AD3jAfPetFVSY6cXT0iN5tBCrXXmYWvGMTaUDI,3892
48
+ xcoll/scattering_routines/everest/properties.h,sha256=AJf7Q_iPsiXTavnguzsNozdoH4NYGdDvyqP3iXychKU,3845
49
+ xcoll/scattering_routines/geometry/__init__.py,sha256=a2DFji3U6Msj-aJE2Dt5Il8FgesfICJHeK9yQj4zHa4,221
50
+ xcoll/scattering_routines/geometry/collimator_geometry.h,sha256=0gHiSEALJtQdW0mUav7GmES4JCAvq-xmch_ZRPkCfUI,7819
51
+ xcoll/scattering_routines/geometry/crystal_geometry.h,sha256=DHuQPMKq_Q0uK0WW2YRd7oxxhMwRPWtNUUn5fBW4Cxc,4968
52
+ xcoll/scattering_routines/geometry/geometry.py,sha256=bF8v7aEP09E4_EMkN0KEJFU-PQrBSOB0Xv699VBUzRY,1102
53
+ xcoll/scattering_routines/geometry/get_s.h,sha256=TWxZ-GjCcLrOV1wota7ltE53Nit0LQASoXmsqn-N0LQ,2947
54
+ xcoll/scattering_routines/geometry/methods.h,sha256=I8ik46SgkCHHtZ99anbdb3ZC7A_5Q809fgpeWMajdkY,3747
55
+ xcoll/scattering_routines/geometry/objects.h,sha256=A5ktGvVlSkC4hUsI_PQFsE80CuDwYbcioxKGRmEf2I0,5499
56
+ xcoll/scattering_routines/geometry/rotation.h,sha256=lO3RaQBys9r0ROMjR8T8Rr7UsIEm-H9_C_70Nwz4MXY,701
57
+ xcoll/scattering_routines/geometry/segments.h,sha256=7nKnnin2ByxkKyaYwGvFaqgLQg5uBba4CdLHL7L3iQs,7667
58
+ xcoll/scattering_routines/geometry/sort.h,sha256=b1MkFO2ddzv1fWGeQzsLuz46qo2pKyRSXHjoAEVU7Ts,5763
59
+ xcoll/xaux.py,sha256=mh4E_jhaUFm2LOKawJ0b6X4zuz8JiJhx6w7GcnRgIXQ,2291
60
+ xcoll-0.6.3.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
61
+ xcoll-0.6.3.dist-info/METADATA,sha256=kTXBtG7uiFxoFbGbikFmNyER0Ee2f7-ASiqsEKmYqC8,2953
62
+ xcoll-0.6.3.dist-info/NOTICE,sha256=6DO_E7WCdRKc42vUoVVBPGttvQi4mRt9fAcxj9u8zy8,74
63
+ xcoll-0.6.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
64
+ xcoll-0.6.3.dist-info/entry_points.txt,sha256=fC9oojAU6WjKujnGBodo7ZcEeBGfSfeLPO5287echdY,26
65
+ xcoll-0.6.3.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.0
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [xobjects]
2
+ include=xcoll
3
+
xcoll/__init__.py.orig DELETED
@@ -1,26 +0,0 @@
1
- # copyright ############################### #
2
- # This file is part of the Xcoll package. #
3
- # Copyright (c) CERN, 2025. #
4
- # ######################################### #
5
-
6
- from .general import _pkg_root, __version__, citation
7
-
8
- <<<<<<< HEAD
9
- from .beam_elements import BlackAbsorber, BlackCrystal, EverestBlock, EverestCollimator, EverestCrystal, \
10
- Geant4Collimator, BlowUp, EmittanceMonitor, collimator_classes, crystal_classes, element_classes
11
- =======
12
- from .beam_elements import BlackAbsorber, BlackCrystal, TransparentCollimator, TransparentCrystal, \
13
- EverestBlock, EverestCollimator, EverestCrystal, BlowUp, EmittanceMonitor, \
14
- collimator_classes, crystal_classes, element_classes
15
- >>>>>>> main
16
- from .scattering_routines.everest import materials, Material, CrystalMaterial
17
- from .scattering_routines.geant4 import Geant4Engine
18
- from .colldb import CollimatorDatabase
19
- from .interaction_record import InteractionRecord
20
- from .rf_sweep import RFSweep
21
- from .lossmap import LossMap, MultiLossMap
22
-
23
-
24
- # print("If you use Xcoll in your simulations, please cite us :-)")
25
- # print(citation)
26
-
xcoll/general.py.orig DELETED
@@ -1,20 +0,0 @@
1
- # copyright ############################### #
2
- # This file is part of the Xcoll package. #
3
- # Copyright (c) CERN, 2024. #
4
- # ######################################### #
5
-
6
- from pathlib import Path
7
-
8
- _pkg_root = Path(__file__).parent.absolute()
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
-
12
- # ======================
13
- # Do not change
14
- # ======================
15
- <<<<<<< HEAD
16
- __version__ = '0.5.11.dev0+geant4'
17
- =======
18
- __version__ = '0.6.0'
19
- >>>>>>> main
20
- # ======================