-
Notifications
You must be signed in to change notification settings - Fork 26
Touschek #191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
gbrogginess
wants to merge
61
commits into
xsuite:main
Choose a base branch
from
gbrogginess:touschek
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Touschek #191
Changes from all commits
Commits
Show all changes
61 commits
Select commit
Hold shift + click to select a range
49b473e
Touschek!
gbrogginess d366006
Return particle object.
gbrogginess 43c8b87
Return a scalar.
gbrogginess 8300520
Configure correct s-location.
gbrogginess 0b67070
Use ELEGANT's random number generator.
gbrogginess 9642c41
Clean-up.
gbrogginess 204d05d
Include ELEGANT and SDDS credits.
gbrogginess c828fbe
Move third party notice to `contributors_and_credits.txt`.
gbrogginess 0cbc053
Add myself as contributor.
gbrogginess ea07b3c
Add README for touschek.
gbrogginess 7069a69
Add link to ELEGANT.
gbrogginess 30cffd1
Fix.
gbrogginess 6903936
Cleanup headers.
gbrogginess 5b59ddb
Cleanup contributors_and_credits.txt
gbrogginess a411d27
Add NOTICE
gbrogginess 11a3cbf
Add LAPACK license in third_party
gbrogginess 91b7ecc
Cleanup touschek readme.
gbrogginess 74b85a2
Take momentum aperture based on s instead of element_name.
gbrogginess c345044
Add back momentum_aperture attribute.
gbrogginess 60ad9bc
Line table not suitable when lines come from MAD-X conversion.
gbrogginess a8483e4
Speed up Piwinski integral.
gbrogginess 2da379b
Momentum aperture selection based on s instead of element_name.
gbrogginess ca69ce3
Inherit some warning prints from ELEGANT for safety.
gbrogginess 9d6e53e
Remove typo.
gbrogginess 35843b1
Change momentum aperture handling.
gbrogginess cdb7b6a
Introduce theta_min and theta_max as user_defined parameters.
gbrogginess 3a01e68
theta_min and theta_max must not be set by the user.
gbrogginess e2329eb
Touschek: clamp δ sampling to LMA (k=0.9).
gbrogginess 6212f50
Touschek: safety factor from LMA 0.9 --> 0.85.
gbrogginess b9044f5
Touschek: center Touschek scattered particles around the closed orbit.
gbrogginess 60d333f
Touschek: remove ignoredRate.
gbrogginess 48568a3
Restore original epsabs and epsrel in Piwinski integral.
gbrogginess c43d013
Merge branch 'xsuite:main' into touschek
gbrogginess a3c6e51
Merge branch 'xsuite:main' into touschek
gbrogginess 413892b
Merge branch 'xsuite:main' into touschek
gbrogginess 43912eb
Merge branch 'xsuite:main' into touschek
gbrogginess 0de6fa2
Use the include header facility of Xobjects
gbrogginess 929efcd
Touschek example!
gbrogginess 37ac2bd
Merge branch 'touschek' of https://github.com/gbrogginess/xfields int…
gbrogginess f1a473d
Clean up Touschek example.
gbrogginess 728a7be
Touschek test draft.
gbrogginess 879797d
Merge branch 'xsuite:main' into touschek
gbrogginess e36ea7e
Merge branch 'xsuite:main' into touschek
gbrogginess cccabf0
More efficient insertion of TouschekScattering centers.
gbrogginess 8aa481d
Momentum aperture --> local momentum acceptance
gbrogginess e767828
Clean-up example.
gbrogginess 1d5b777
API takes xt.Table and not pandas dataframe
gbrogginess cf4cff0
Remove third party LICENSE
gbrogginess 68a4d20
Better explain example.
gbrogginess 53713fc
Clean headers.
gbrogginess a01d351
Remove unnecessary underscored variables.
gbrogginess 48a2416
Docstring drafts.
gbrogginess 4499173
Update.
gbrogginess 7e4e14d
Remove: will go in Xsuite doc.
gbrogginess be52500
Fix.
gbrogginess be51855
Fix.
gbrogginess a0379d5
Fix typo causing errors.
gbrogginess e4c77dd
T_rev0 is deprecated.
gbrogginess 053cd68
Improved Touschek test.
gbrogginess f58e950
Merge branch 'main' into touschek
gbrogginess b52907d
Cleanup docstrings.
gbrogginess File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| This package incorporates portions adapted from Argonne National Laboratory’s “Elegant” | ||
| and from the SDDS Toolkit. © 2002 The University of Chicago; © 2002 The Regents of the | ||
| University of California. Distributed under their respective Software License Agreements. | ||
| See: xfields/third_party/elegant/LICENSE and xfields/third_party/SDDS/LICENSE. | ||
|
|
||
| This package also incorporates LAPACK’s DLARAN algorithm (modified BSD license). | ||
| See: xfields/third_party/lapack/LICENSE. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,231 @@ | ||
| # copyright ############################### # | ||
| # This file is part of the Xtrack Package. # | ||
| # Copyright (c) CERN, 2025. # | ||
| # ######################################### # | ||
| import numpy as np | ||
| import matplotlib.pyplot as plt | ||
|
|
||
| import xobjects as xo | ||
| import xtrack as xt | ||
| import xfields as xf | ||
|
|
||
| ###################################################### | ||
| # Beam parameters | ||
| ###################################################### | ||
| nemitt_x = 1e-5 | ||
| nemitt_y = 1e-7 | ||
|
|
||
| sigma_z = 4e-3 | ||
| sigma_delta = 1e-3 | ||
|
|
||
| bunch_population = 4e9 | ||
|
|
||
| ###################################################### | ||
| # Build a toy ring | ||
| ###################################################### | ||
| lbend = 3 | ||
| angle = np.pi / 2 | ||
|
|
||
| lquad = 0.3 | ||
| k1qf = 0.1 | ||
| k1qd = 0.7 | ||
|
|
||
| # Create environment | ||
| env = xt.Environment() | ||
|
|
||
| # Define the line (toy ring) | ||
| line = env.new_line(components=[ | ||
| env.new('mqf.1', xt.Quadrupole, length=lquad, k1=k1qf), | ||
| env.new('d1.1', xt.Drift, length=1), | ||
| env.new('mb1.1', xt.Bend, length=lbend, angle=angle), | ||
| env.new('d2.1', xt.Drift, length=1), | ||
|
|
||
| env.new('mqd.1', xt.Quadrupole, length=lquad, k1=-k1qd), | ||
| env.new('d3.1', xt.Drift, length=1), | ||
| env.new('mb2.1', xt.Bend, length=lbend, angle=angle), | ||
| env.new('d4.1', xt.Drift, length=1), | ||
|
|
||
| env.new('mqf.2', xt.Quadrupole, length=lquad, k1=k1qf), | ||
| env.new('d1.2', xt.Drift, length=1), | ||
| env.new('mb1.2', xt.Bend, length=lbend, angle=angle), | ||
| env.new('d2.2', xt.Drift, length=1), | ||
|
|
||
| env.new('mqd.2', xt.Quadrupole, length=lquad, k1=-k1qd), | ||
| env.new('d3.2', xt.Drift, length=1), | ||
| env.new('mb2.2', xt.Bend, length=lbend, angle=angle), | ||
| env.new('d4.2', xt.Drift, length=1), | ||
| ]) | ||
|
|
||
| # Set the reference particle | ||
| line.set_particle_ref('electron', p0c=1e9) | ||
|
|
||
| # Configure the bend model | ||
| line.configure_bend_model(core='full', edge=None) | ||
|
|
||
| ###################################################### | ||
| # Insert Touschek scattering centers | ||
| ###################################################### | ||
| # We insert Touschek scattering centers in the middle of each magnet | ||
| # to have good coverage of variations of the optical functions | ||
| tab = line.get_table() | ||
| tab_bends_quads = tab.rows[(tab.element_type == 'Bend') | (tab.element_type == 'Quadrupole')] | ||
|
|
||
| placements = [] | ||
| for ii, nn in enumerate(tab_bends_quads.name): | ||
| tscatter_name = f'TScatter.{ii}' | ||
| env.elements[tscatter_name] = xf.TouschekScattering() | ||
| placements.append(env.place(tscatter_name, at=0.0, from_=nn)) | ||
|
|
||
| # The last TouschekScattering element has to be placed at the end of the line | ||
| tscatter_name = f'TScatter.{ii+1}' | ||
| env.elements[tscatter_name] = xf.TouschekScattering() | ||
| placements.append(env.place(tscatter_name, at=tab.s[-1])) | ||
|
|
||
| line.insert(placements) | ||
|
|
||
| ###################################################### | ||
| # Install apertures | ||
| ###################################################### | ||
| tab = line.get_table() | ||
| needs_aperture = tab.rows.match_not(element_type='Drift.*|Marker|').name | ||
|
|
||
| aper_size = 0.040 # m | ||
|
|
||
| placements = [] | ||
| for nn in needs_aperture: | ||
| env.new( | ||
| f'{nn}_aper_entry', xt.LimitRect, | ||
| min_x=-aper_size, max_x=aper_size, | ||
| min_y=-aper_size, max_y=aper_size | ||
| ) | ||
| placements.append(env.place(f'{nn}_aper_entry', at=f'{nn}@start')) | ||
|
|
||
| env.new( | ||
| f'{nn}_aper_exit', xt.LimitRect, | ||
| min_x=-aper_size, max_x=aper_size, | ||
| min_y=-aper_size, max_y=aper_size | ||
| ) | ||
| placements.append(env.place(f'{nn}_aper_exit', at=f'{nn}@end')) | ||
|
|
||
| line.insert(placements) | ||
|
|
||
| ###################################################### | ||
| # Evaluate local momentum acceptance profile | ||
| ###################################################### | ||
| # Evaluate local momentum aperture at the touschek scattering centers | ||
| tab = line.get_table() | ||
| elements = tab.rows.match(element_type="TouschekScattering").name | ||
| lma = line.get_local_momentum_acceptance( | ||
| # twiss=tw, | ||
| elements=elements, | ||
| nemitt_x=nemitt_x, | ||
| nemitt_y=nemitt_y, | ||
| y_offset=1e-9, | ||
| delta_negative_limit=-0.012, | ||
| delta_positive_limit=0.012, | ||
| delta_step_size=1e-4, | ||
| n_turns=1000, | ||
| method="4d" | ||
| ) | ||
|
|
||
| ###################################################### | ||
| # Plot | ||
| ###################################################### | ||
| plt.plot(lma.s, lma.deltan*100, c='r') | ||
| plt.plot(lma.s, lma.deltap*100, c='r') | ||
| plt.title('Toy ring: local momentum acceptance profile') | ||
| plt.xlabel('s [m]') | ||
| plt.ylabel(r'$\delta$ [%]') | ||
| plt.grid() | ||
| plt.show() | ||
|
|
||
| ###################################################### | ||
| # Touschek simulation | ||
| ###################################################### | ||
| # Parameters | ||
| local_momentum_acceptance_scale = 0.85 # scaling factor for local momentum acceptance | ||
| n_simulated = 5e6 # number of simulated scattering events with delta > delta_min | ||
| nturns = 1000 # number of turns to simulate | ||
|
|
||
| touschek_manager = xf.TouschekManager( | ||
| line, | ||
| local_momentum_acceptance=lma, | ||
| local_momentum_acceptance_scale=local_momentum_acceptance_scale, | ||
| nemitt_x=nemitt_x, | ||
| nemitt_y=nemitt_y, | ||
| sigma_z=sigma_z, | ||
| sigma_delta=sigma_delta, | ||
| bunch_population=bunch_population, | ||
| n_simulated=n_simulated, | ||
| nx=3, ny=3, nz=3, | ||
| ignored_portion=0.01, | ||
| seed=1997, | ||
| method='4d' | ||
| ) | ||
|
|
||
| # Initialise the Touschek simulation. | ||
| # Computes the integrated Piwinski scattering rate over each lattice section | ||
| # between consecutive TouschekScattering elements (using the trapezoidal rule), | ||
| # and configures each element with its local optics, beam parameters, and | ||
| # momentum acceptance. The integrated rate is later used to assign the | ||
| # correct weights to the Touschek-scattered macro-particles. | ||
| touschek_manager.initialise_touschek() | ||
|
|
||
| # Get the list of TouschekScattering elements in the line | ||
| touschek_elements = tab.rows[tab.element_type == 'TouschekScattering'].name | ||
|
|
||
| # Build a CPU tracker with OpenMP multithreading to speed up tracking | ||
| line.discard_tracker() | ||
| line.build_tracker(_context=xo.ContextCpu(omp_num_threads='auto')) | ||
|
|
||
| # For each TouschekScattering element: | ||
| # 1. Generate Touschek-scattered macro-particles at that element | ||
| # 2. Track them around the ring for `nturns` turns, starting and ending at that element | ||
| particles_list = [] | ||
| for ii, element in enumerate(touschek_elements): | ||
| s_start_elem = tab.rows[tab.name == element].s[0] | ||
|
|
||
| # Generate Touschek-scattered macro-particles | ||
| particles = line[element].scatter() | ||
|
|
||
| # Track | ||
| print(f"\nTracking particles scattered at {element} (s = {s_start_elem:.2f} m)") | ||
| line.track(particles, ele_start=element, ele_stop=element, num_turns=nturns, with_progress=1) | ||
|
|
||
| particles_list.append(particles) | ||
|
|
||
| # Merge the macro-particle sets from all scattering elements into a single collection | ||
| particles = xt.Particles.merge(particles_list) | ||
|
gbrogginess marked this conversation as resolved.
|
||
|
|
||
| # Optional: Refine loss location to improve loss map accuracy | ||
| loss_loc_refinement = xt.LossLocationRefinement(line, | ||
| n_theta = 360, # Angular resolution in the polygonal approximation of the aperture | ||
| r_max = 0.5, # Maximum transverse aperture in m | ||
| dr = 50e-6, # Transverse loss refinement accuracy [m] | ||
| ds = 0.1, # Longitudinal loss refinement accuracy [m] | ||
| ) | ||
|
|
||
| loss_loc_refinement.refine_loss_location(particles) | ||
|
|
||
| ###################################################### | ||
| # Compute Touschek lifetime | ||
| ###################################################### | ||
| # Keep lost particles only | ||
| particles = particles.filter(particles.state == 0) | ||
| # Compute total Touschek loss rate | ||
| loss_rate = sum(particles.weight) | ||
| # Compute Touschek lifetime | ||
| touschek_lifetime = bunch_population / loss_rate | ||
|
|
||
| ###################################################### | ||
| # Plot: Toy ring Touschek loss map | ||
| ###################################################### | ||
| circumference = line.get_length() | ||
| binwidth = 0.1 # m | ||
|
|
||
| plt.title(f'Toy ring Touschek loss map (Touschek lifetime: {touschek_lifetime/60:.2f} min)') | ||
| plt.hist(particles.s, bins=np.arange(0, circumference + binwidth, binwidth), weights=particles.weight*1e-3) | ||
| plt.xlabel('s [m]') | ||
| plt.ylabel('Loss rate [kHz]') | ||
| plt.grid() | ||
| plt.show() | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.