Skip to content

Commit 51c0fc8

Browse files
authored
Merge pull request #66 from xsuite/release/v0.3.5
Release 0.3.5
2 parents dff2aa6 + 96383a0 commit 51c0fc8

18 files changed

+272
-144
lines changed

examples/colldb/lhc_run3.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ families:
4242
# Dump protection
4343
- &TCDQ { <<: *ALL, gap: 7.3, stage: tertiary, material: C, length: 3, angle: 0, side: left }
4444
- &TCSP { <<: *ALL, gap: 7.3, stage: secondary, material: C, length: 1, angle: 0 }
45-
# Physics background minimalisation
45+
# Triplet protection
4646
- &TCT15 { <<: *ALL, gap: 8.5, stage: tertiary, material: Iner, length: 1, parking: 0.020 }
4747
- &TCT2 { <<: *ALL, gap: 37, stage: tertiary, material: Iner, length: 1, }
4848
- &TCT8 { <<: *ALL, gap: 11.5, stage: tertiary, material: Iner, length: 1, }

examples/colldb/lhc_run3_crystals.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ families:
4242
# Dump protection
4343
- &TCDQ { <<: *ALL, gap: 7.3, stage: tertiary, material: C, length: 3, angle: 0, side: left }
4444
- &TCSP { <<: *ALL, gap: 7.3, stage: secondary, material: C, length: 1, angle: 0 }
45-
# Physics background minimalisation
45+
# Triplet protection
4646
- &TCT15 { <<: *ALL, gap: 9.5, stage: tertiary, material: Iner, length: 1, parking: 0.020 }
4747
- &TCT2 { <<: *ALL, gap: 37, stage: tertiary, material: Iner, length: 1, }
4848
- &TCT8 { <<: *ALL, gap: 11.5, stage: tertiary, material: Iner, length: 1, }

examples/lhc_run3_lossmap.py

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,34 @@
77
from pathlib import Path
88
import time
99
start_time = time.time()
10-
import sys, os, contextlib
1110

1211
import xobjects as xo
1312
import xtrack as xt
1413
import xcoll as xc
1514

16-
context = xo.ContextCpu(omp_num_threads='auto')
1715

18-
# On a modern CPU, we get ~5000 particle*turns/s
19-
# So this script should take around half an hour
20-
beam = '1'
21-
plane = 'H'
16+
# We do the majority of the script on the default context to be able to use prebuilt kernels
17+
context = xo.ContextCpu()
2218

23-
num_turns = 200
19+
20+
# This script takes around 3 minutes on a modern CPU (90s preparation+interpolation, 90s tracking)
21+
beam = 1
22+
plane = 'H'
23+
24+
num_turns = 200
2425
num_particles = 50000
25-
engine = 'everest'
2626

2727
path_in = xc._pkg_root.parent / 'examples'
2828
path_out = Path.cwd()
2929

3030

3131
# Load from json
32-
with open(os.devnull, 'w') as fid:
33-
with contextlib.redirect_stdout(fid):
34-
line = xt.Line.from_json(path_in / 'machines' / f'lhc_run3_b{beam}.json')
32+
line = xt.Line.from_json(path_in / 'machines' / f'lhc_run3_b{beam}.json')
3533

3634

3735
# Aperture model check
3836
print('\nAperture model check on imported model:')
39-
with open(os.devnull, 'w') as fid:
40-
with contextlib.redirect_stdout(fid):
41-
df_imported = line.check_aperture()
37+
df_imported = line.check_aperture()
4238
assert not np.any(df_imported.has_aperture_problem)
4339

4440

@@ -47,17 +43,12 @@
4743

4844

4945
# Install collimators into line
50-
if engine == 'everest':
51-
coll_manager.install_everest_collimators(verbose=True)
52-
else:
53-
raise ValueError(f"Unknown scattering engine {engine}!")
46+
coll_manager.install_everest_collimators(verbose=True)
5447

5548

5649
# Aperture model check
5750
print('\nAperture model check after introducing collimators:')
58-
with open(os.devnull, 'w') as fid:
59-
with contextlib.redirect_stdout(fid):
60-
df_with_coll = line.check_aperture()
51+
df_with_coll = line.check_aperture()
6152
assert not np.any(df_with_coll.has_aperture_problem)
6253

6354

@@ -70,33 +61,41 @@
7061
coll_manager.set_openings()
7162

7263

64+
# Optimise the line
65+
line.optimize_for_tracking()
66+
67+
7368
# Generate initial pencil distribution on horizontal collimator
74-
tcp = f"tcp.{'c' if plane=='H' else 'd'}6{'l' if beam=='1' else 'r'}7.b{beam}"
69+
tcp = f"tcp.{'c' if plane=='H' else 'd'}6{'l' if f'{beam}'=='1' else 'r'}7.b{beam}"
7570
part = coll_manager.generate_pencil_on_collimator(tcp, num_particles=num_particles)
7671

7772

78-
# Optimise the line
79-
line.optimize_for_tracking()
80-
idx = line.element_names.index(tcp)
81-
part.at_element = idx
82-
part.start_tracking_at_element = idx
73+
74+
# Move the line to an OpenMP context to be able to use all cores
75+
line.discard_tracker()
76+
line.build_tracker(_context=xo.ContextCpu(omp_num_threads='auto'))
77+
# Should move iobuffer as well in case of impacts
8378

8479

85-
# Track
80+
# Track!
8681
coll_manager.enable_scattering()
87-
line.track(part, num_turns=num_turns, time=True)
82+
line.track(part, num_turns=num_turns, time=True, with_progress=1)
8883
coll_manager.disable_scattering()
8984
print(f"Done tracking in {line.time_last_track:.1f}s.")
9085

9186

87+
# Move the line back to the default context to be able to use all prebuilt kernels for the aperture interpolation
88+
line.discard_tracker()
89+
line.build_tracker(_context=xo.ContextCpu())
90+
91+
9292
# Save lossmap to json, which can be loaded, combined (for more statistics),
9393
# and plotted with the 'lossmaps' package
94-
_ = coll_manager.lossmap(part, file=Path(path_out,f'lossmap_B{beam}{plane}.json'))
94+
coll_manager.lossmap(part, file=Path(path_out,f'lossmap_B{beam}{plane}.json'))
9595

9696

9797
# Save a summary of the collimator losses to a text file
9898
summary = coll_manager.summary(part, file=Path(path_out,f'coll_summary_B{beam}{plane}.out'))
9999
print(summary)
100100
print(f"Total calculation time {time.time()-start_time}s")
101101

102-
exit()

examples/lhc_run3_lossmap_with_crystals.py

Lines changed: 53 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3,74 +3,60 @@
33
# Copyright (c) CERN, 2024. #
44
# ######################################### #
55

6-
import json
76
import numpy as np
87
from pathlib import Path
98
import time
109
start_time = time.time()
11-
import sys, os, contextlib
1210

11+
import xobjects as xo
1312
import xpart as xp
1413
import xtrack as xt
1514
import xcoll as xc
1615

17-
if len(sys.argv) < 4:
18-
raise ValueError("Need three arguments: beam, plane, and tilt.")
19-
beam = int(sys.argv[1])
20-
plane = str(sys.argv[2])
21-
tilt = int(sys.argv[3])*1.e-6
2216

17+
# We do the majority of the script on the default context to be able to use prebuilt kernels
18+
context = xo.ContextCpu()
2319

24-
# On a modern CPU, we get ~5000 particle*turns/s
25-
# So this script should take a bit less than 40 minutes
26-
# beam = 1
27-
# plane = 'H'
28-
# tilt = 0 # rad !!
2920

30-
num_turns = 200
31-
num_particles = 5000
32-
engine = 'everest'
21+
# This script takes around 3 minutes on a modern CPU (90s preparation+interpolation, 90s tracking)
22+
beam = 1
23+
plane = 'H'
24+
tilt = 0 # rad !!
25+
26+
num_turns = 200
27+
num_particles = 50000
3328

3429
path_in = xc._pkg_root.parent / 'examples'
3530
path_out = Path.cwd()
3631

3732

3833
# Load from json
39-
with open(os.devnull, 'w') as fid:
40-
with contextlib.redirect_stdout(fid):
41-
line = xt.Line.from_json(path_in / 'machines' / f'lhc_run3_b{beam}.json')
34+
line = xt.Line.from_json(path_in / 'machines' / f'lhc_run3_b{beam}.json')
4235

4336

4437
# Aperture model check
4538
print('\nAperture model check on imported model:')
46-
with open(os.devnull, 'w') as fid:
47-
with contextlib.redirect_stdout(fid):
48-
df_imported = line.check_aperture()
39+
df_imported = line.check_aperture()
4940
assert not np.any(df_imported.has_aperture_problem)
5041

5142

5243
# Initialise collmanager
5344
coll_manager = xc.CollimatorManager.from_yaml(path_in / 'colldb' / f'lhc_run3_crystals.yaml', line=line,
54-
beam=beam, ignore_crystals=False, record_impacts=True)
45+
beam=beam, ignore_crystals=False, _context=context)
5546

5647

5748
# Install collimators into line
58-
if engine == 'everest':
59-
coll_manager.install_everest_collimators(verbose=True)
60-
else:
61-
raise ValueError(f"Unknown scattering engine {engine}!")
49+
coll_manager.install_everest_collimators(verbose=True)
6250

6351

6452
# Aperture model check
6553
print('\nAperture model check after introducing collimators:')
66-
with open(os.devnull, 'w') as fid:
67-
with contextlib.redirect_stdout(fid):
68-
df_with_coll = line.check_aperture()
54+
df_with_coll = line.check_aperture()
6955
assert not np.any(df_with_coll.has_aperture_problem)
7056

7157

7258
# Primary crystal
73-
tcpc = f"tcpc{plane.lower()}.a{6 if plane=='V' else 4 if beam==1 else 5}{'l' if beam==1 else 'r'}7.b{beam}"
59+
tcpc = f"tcpc{plane.lower()}.a{6 if plane=='V' else 4 if f'{beam}'=='1' else 5}{'l' if f'{beam}'=='1' else 'r'}7.b{beam}"
7460

7561

7662
# Build the tracker
@@ -84,6 +70,10 @@
8470
coll_manager.set_openings()
8571

8672

73+
# Optimise the line
74+
line.optimize_for_tracking()
75+
76+
8777
# # Generate initial pencil distribution on crystal
8878
# part = coll_manager.generate_pencil_on_collimator(tcpc, num_particles=num_particles)
8979
# Generate initial halo
@@ -97,12 +87,6 @@
9787
_buffer=coll_manager._part_buffer
9888
)
9989

100-
# Optimise the line
101-
line.optimize_for_tracking()
102-
idx = line.element_names.index(tcpc)
103-
part.at_element = idx
104-
part.start_tracking_at_element = idx
105-
10690

10791
# Apply settings
10892
line[tcpc].tilt_L = tilt
@@ -111,16 +95,27 @@
11195
line[tcpc].ydim = 0.05
11296

11397

114-
# Track
98+
# Move the line to an OpenMP context to be able to use all cores
99+
line.discard_tracker()
100+
line.build_tracker(_context=xo.ContextCpu(omp_num_threads='auto'))
101+
# Should move iobuffer as well in case of impacts
102+
103+
104+
# Track!
115105
coll_manager.enable_scattering()
116-
line.track(part, num_turns=num_turns, time=True)
106+
line.track(part, num_turns=num_turns, time=True, with_progress=1)
117107
coll_manager.disable_scattering()
118108
print(f"Done tracking in {line.time_last_track:.1f}s.")
119109

120110

111+
# Move the line back to the default context to be able to use all prebuilt kernels for the aperture interpolation
112+
line.discard_tracker()
113+
line.build_tracker(_context=xo.ContextCpu())
114+
115+
121116
# Save lossmap to json, which can be loaded, combined (for more statistics),
122117
# and plotted with the 'lossmaps' package
123-
# _ = coll_manager.lossmap(part, file=Path(path_out,f'lossmap_B{beam}{plane}.json'))
118+
coll_manager.lossmap(part, file=Path(path_out,f'lossmap_B{beam}{plane}.json'))
124119

125120

126121
# Save a summary of the collimator losses to a text file
@@ -129,28 +124,28 @@
129124
print(summary)
130125

131126

132-
# Impacts
133-
# =======
134-
imp = coll_manager.impacts.to_pandas()
135-
outfile = Path(path_out, f'cry_{round(tilt*1e6)}urad_impacts_B{beam}{plane}.json')
136-
imp.to_json(outfile)
127+
# # Impacts
128+
# # =======
129+
# imp = coll_manager.impacts.to_pandas()
130+
# outfile = Path(path_out, f'cry_{round(tilt*1e6)}urad_impacts_B{beam}{plane}.json')
131+
# imp.to_json(outfile)
132+
133+
# # Only keep the first impact
134+
# imp.drop_duplicates(subset=['parent_id'], inplace=True)
135+
# assert np.unique(imp.interaction_type) == ['Enter Jaw']
137136

138-
# Only keep the first impact
139-
imp.drop_duplicates(subset=['parent_id'], inplace=True)
140-
assert np.unique(imp.interaction_type) == ['Enter Jaw']
137+
# # Only keep those first impacts that are on the crystal
138+
# first_impacts = imp[imp.collimator==tcpc].parent_id
139+
# num_first_impacts = len(first_impacts)
140+
# assert num_first_impacts==len(np.unique(first_impacts))
141141

142-
# Only keep those first impacts that are on the crystal
143-
first_impacts = imp[imp.collimator==tcpc].parent_id
144-
num_first_impacts = len(first_impacts)
145-
assert num_first_impacts==len(np.unique(first_impacts))
142+
# ineff = nabs/num_first_impacts
143+
# outfile = Path(path_out, f'cry_{round(tilt*1e6)}urad_ineff_B{beam}{plane}.json')
144+
# with outfile.open('w') as fid:
145+
# json.dump({'first_impacts': num_first_impacts, 'nabs': nabs, 'ineff': ineff}, fid)
146146

147-
ineff = nabs/num_first_impacts
148-
outfile = Path(path_out, f'cry_{round(tilt*1e6)}urad_ineff_B{beam}{plane}.json')
149-
with outfile.open('w') as fid:
150-
json.dump({'first_impacts': num_first_impacts, 'nabs': nabs, 'ineff': ineff}, fid)
147+
# print(f"Out of {num_first_impacts} particles hitting the crystal {tcpc} (angle {round(tilt*1e6)}urad) first, {round(nabs)} are absorbed in the crystal (for an inefficiency of {ineff:5}.")
148+
# print(f"Critical angle is {round(line[tcpc].critical_angle*1.e6, 1)}urad.")
151149

152-
print(f"Out of {num_first_impacts} particles hitting the crystal {tcpc} (angle {round(tilt*1e6)}urad) first, {round(nabs)} are absorbed in the crystal (for an inefficiency of {ineff:5}.")
153-
print(f"Critical angle is {round(line[tcpc].critical_angle*1.e6, 1)}urad.")
154150
print(f"Total calculation time {time.time()-start_time}s")
155151

156-
exit()

0 commit comments

Comments
 (0)