Skip to content

Conversation

@Ritu-Bharadwaj
Copy link
Collaborator

These are the files to model the Intrabeam Scattering effect written purely in python but we intend to convert the passmethod in C in future.

@Ritu-Bharadwaj Ritu-Bharadwaj added the WIP work in progress label Jul 10, 2025
@carmignani carmignani marked this pull request as draft July 10, 2025 14:32
@lcarver
Copy link
Contributor

lcarver commented Jul 16, 2025

Hello @Ritu-Bharadwaj , thank you for this work!

Can you make an example script showing how to use it? I recommend that you put it in pyat/examples/CollectiveEffects/. Typically for the examples you need to use a lattice from the machine_data sub directory. We usually go for the old ESRF lattice.

This will make it much easier to understand and provide feedback.

Copy link
Contributor

@swhite2401 swhite2401 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice work! I added a few comments with possible simplifications.

bunch object that is being tracked.
"""

d = 4 * np.std(bunch[2, :])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here to simplify you may just run the std command on the full bunch array and return it directly as an array after modifying the values when needed

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Simon that doing an std on the whole particle array may be more efficient. In addition, d=4sigma_y is the most common case. But in the case you have a bunch with horizontal emittance smaller than the vertical one, the d parameter will be d=4sigma_y. I know that in mbtrack2, it's probably also 4sigma_y, but physically it should probably be min(4sigma_x, 4*sigma_y).


def initialize(bunch, ring):
"""
calculates bunch parameters at each turn.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is better to document all input argument, there is also a format to respect such that the docstring appear correctly in the AT documentation

):
"""
Calculates emittances and derived parameters (a, b, q, sigma_H) based on the selected Intrabeam Scattering (IBS) model.
These computations are performed every 500 turns by default, or at user-defined intervals specified by the update_turns variable,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment on documentation

"""

sigma = at.sigma_matrix(beam=bunch)
eigs, _ = np.linalg.eig(sigma @ at.jmat(3))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A function get_emittance() could be useful in general

emitx = emits[1]
emity = emits[0]

if model == "PS":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may create an Enum class to handle cases

s_points = np.linspace(0, self.circumference, self.n_points, endpoint=False)
self.ring = self.ring.sbreak(s_points, marker_list)
refpts = self.ring.get_uint32_index("ibs*")
elemdata, avebeta, _, avedisp, avespos, tune, chrom = self.ring.disable_6d(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here is there a problem with 6d optics?

).avlinopt(dp=0.0, refpts=refpts + 1)
self.beta_x = avebeta[:, 0]
self.beta_y = avebeta[:, 1]
self.alphaX = [e.alpha[0] for e in elemdata]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why a loop here and not on the other parameters?

bunch, n_bin, sigma_p, sigma_px, sigma_py, revolution_frequency, T_x, T_y, T_p
):
"""
Applies IBS-induced momentum kicks to the bunch every turn, scaled by growth rates,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation

Rho = 1.0

N_mp = len(bunch[0, :])
Delta_pz = (
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same calculation could be factorized

)

T_x, T_y, T_p = ibs.get_scatter_T(
vabq=vabq,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for this functions you may just pass a dictionary instead of all arguments separately

Copy link
Collaborator

@gubaidulinvadim gubaidulinvadim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, nice work. I see that you kept most of what Salah (M1 intern at SOLEIL from last year) did and adapted it to be run with pyAT. I must say that his mbtrack2 IBS class is not written in a very straightforward way (there are many cases and many optional arguments for different functions). We will likely change it in mbtrack2 at some point. If you make some changes in that for pyAT, I will happily adopt it to mbtrack2.

@@ -0,0 +1,293 @@
"""
IBS module for Acclerator toolbox(AT) inspired from mbtrack2
from Alexin Gamelin , Vadim Gubaidulin (SOLEIL)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from Alexin Gamelin , Vadim Gubaidulin (SOLEIL)
from Salah Eddine Feddaoui Dellalou, Alexis Gamelin , Vadim Gubaidulin (SOLEIL)

The majority of the IBS code was written by Salah (M1 intern) last year

@@ -0,0 +1,165 @@
"""
IBS element for Acclerator toolbox(AT) inspired from mbtrack2
from Alexin Gamelin , Vadim Gubaidulin (SOLEIL)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from Alexin Gamelin , Vadim Gubaidulin (SOLEIL)
from Alexis Gamelin , Vadim Gubaidulin, Salah Eddine Feddaoui Dellalou (SOLEIL)

@@ -0,0 +1,241 @@
"""
IBS passmethod for Acclerator toolbox(AT) inspired from mbtrack2
from Alexin Gamelin , Vadim Gubaidulin (SOLEIL)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from Alexin Gamelin , Vadim Gubaidulin (SOLEIL)
from Alexis Gamelin , Vadim Gubaidulin, Salah Eddine Feddaoui Dellalou (SOLEIL)


n_points (int, optional):
Number of points at which optics is computed.
Default is 10000.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a tip: in mbtrack2 we also have a large number of points set as a default, but in practice, the relevant parameter -- IBS growth rate converges for a much lower amount of sampled points.

bunch object that is being tracked.
"""

d = 4 * np.std(bunch[2, :])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with Simon that doing an std on the whole particle array may be more efficient. In addition, d=4sigma_y is the most common case. But in the case you have a bunch with horizontal emittance smaller than the vertical one, the d parameter will be d=4sigma_y. I know that in mbtrack2, it's probably also 4sigma_y, but physically it should probably be min(4sigma_x, 4*sigma_y).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

WIP work in progress

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants