@@ -408,6 +408,69 @@ def apply(self, p_array, dz):
408
408
beam_matching (p_array , self .bounds , self .x_opt , self .y_opt , self .remove_offsets , self .slice )
409
409
410
410
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
+
411
474
class SpontanRadEffects (PhysProc ):
412
475
"""
413
476
Effects of the spontaneous radiation:
0 commit comments