Skip to content

Commit c7ec550

Browse files
committed
added slotted foil physics process
1 parent 73274ca commit c7ec550

File tree

2 files changed

+65
-2
lines changed

2 files changed

+65
-2
lines changed

demos/ipython_tutorials/2_tracking.ipynb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@
560560
"metadata": {
561561
"anaconda-cloud": {},
562562
"kernelspec": {
563-
"display_name": "Python 3",
563+
"display_name": "Python 3 (ipykernel)",
564564
"language": "python",
565565
"name": "python3"
566566
},
@@ -574,7 +574,7 @@
574574
"name": "python",
575575
"nbconvert_exporter": "python",
576576
"pygments_lexer": "ipython3",
577-
"version": "3.8.3"
577+
"version": "3.9.7"
578578
},
579579
"name": ""
580580
},

ocelot/cpbd/physics_proc.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,69 @@ def apply(self, p_array, dz):
408408
beam_matching(p_array, self.bounds, self.x_opt, self.y_opt, self.remove_offsets, self.slice)
409409

410410

411+
class SlottedFoil(PhysProc):
412+
"""
413+
Class to simulate a slotted foil
414+
415+
:param dx: thickness of foil [um]
416+
:param X0: radiation length of the foil material in [cm]
417+
418+
:param xmin: -np.inf left position of the foil slot [m]
419+
:param xmax: np.inf right position of the foil slot [m]
420+
421+
:param ymin: -np.inf lower position of the foil slot [m]
422+
:param ymax: np.inf upper position of the foil slot [m]
423+
"""
424+
def __init__(self, dx, X0, xmin=-np.inf, xmax=np.inf, ymin=-np.inf, ymax=np.inf, step=1):
425+
PhysProc.__init__(self, step)
426+
self.xmin = xmin # in m
427+
self.xmax = xmax # in m
428+
429+
self.ymin = ymin # in m
430+
self.ymax = ymax # in m
431+
self.z = 1 # charge number of the incident particle
432+
self.dx = dx # thickness of the foil in [um]
433+
self.X0 = X0 # radiation length in [cm]
434+
435+
def scattered_particles(self, p_array):
436+
x = p_array.x()
437+
inds = np.argwhere(np.logical_or(x < self.xmin, x > self.xmax))
438+
inds_x = inds.reshape(inds.shape[0])
439+
440+
y = p_array.y()
441+
inds = np.argwhere(np.logical_or(y < self.ymin, y > self.ymax))
442+
inds_y = inds.reshape(inds.shape[0])
443+
indeces = np.append(inds_x, inds_y)
444+
return indeces
445+
446+
def get_scattering_angle(self, p_array):
447+
"""
448+
formula from The Review of Particle Physics https://pdg.lbl.gov
449+
450+
:param p_array: ParticleArray
451+
:return: theta - rms scattering angle
452+
"""
453+
p = np.sqrt(p_array.E**2 - m_e_GeV**2) * 1000 # MeV/c momentum of the particles
454+
gamma = p_array.E / m_e_GeV
455+
igamma2 = 0.
456+
if gamma != 0:
457+
igamma2 = 1. / (gamma * gamma)
458+
beta = np.sqrt(1. - igamma2)
459+
theta_rms = 13.6 / (beta * p) * self.z * np.sqrt(self.dx * 1e-4 / self.X0) * (1 + 0.038 * np.log(self.dx*1e-4 / self.X0))
460+
return theta_rms
461+
462+
def apply(self, p_array, dz):
463+
_logger.debug(" SlottedFoil applied")
464+
465+
theta_rms = self.get_scattering_angle(p_array)
466+
indeces = self.scattered_particles(p_array)
467+
n = len(indeces)
468+
thetas = np.random.normal(0, theta_rms, n)
469+
alphas = np.random.uniform(0, 2*np.pi, n)
470+
p_array.px()[indeces] += np.cos(alphas) * thetas
471+
p_array.py()[indeces] += np.sin(alphas) * thetas
472+
473+
411474
class SpontanRadEffects(PhysProc):
412475
"""
413476
Effects of the spontaneous radiation:

0 commit comments

Comments
 (0)