CMS 3D CMS Logo

MultipleScattering.cc
Go to the documentation of this file.
7 
8 #include <cmath>
9 #include <memory>
10 
11 #include <Math/AxisAngle.h>
12 
17 
19 // Author: Patrick Janot
20 // Date: 8-Jan-2004
21 //
22 // Revision: Class structure modified to match SimplifiedGeometryPropagator
23 // Fixed a bug in which particles could no longer be on the layer after scattering
24 // S. Kurz, 29 May 2017
26 
28 
29 namespace fastsim {
31 
35  public:
38 
40  ~MultipleScattering() override { ; };
41 
43 
49  void interact(Particle& particle,
51  std::vector<std::unique_ptr<Particle> >& secondaries,
52  const RandomEngineAndDistribution& random) override;
53 
54  private:
56  XYZVector orthogonal(const XYZVector& aVector) const;
57 
58  double minPt_;
59  double radLenInCm_;
60  };
61 } // namespace fastsim
62 
65  // Set the minimal pT for interaction
66  minPt_ = cfg.getParameter<double>("minPt");
67  // Material properties
68  radLenInCm_ = cfg.getParameter<double>("radLen");
69 }
70 
73  std::vector<std::unique_ptr<fastsim::Particle> >& secondaries,
74  const RandomEngineAndDistribution& random) {
75  //
76  // only charged particles
77  //
78  if (particle.charge() == 0) {
79  return;
80  }
81 
82  double radLengths = layer.getThickness(particle.position(), particle.momentum());
83  //
84  // no material
85  //
86  if (radLengths < 1E-10) {
87  return;
88  }
89 
90  // particle must have minimum pT
91  if (particle.momentum().Pt() < minPt_) {
92  return;
93  }
94 
95  double p2 = particle.momentum().Vect().Mag2();
96  double m2 = particle.momentum().mass2();
97  double e = std::sqrt(p2 + m2);
98 
99  // This is p*beta
100  double pbeta = p2 / e;
101 
102  // Average multiple scattering angle from Moliere radius
103  // The sqrt(2) factor is because of the *space* angle
104  double theta0 = 0.0136 / pbeta * particle.charge() * std::sqrt(2. * radLengths) * (1. + 0.038 * std::log(radLengths));
105 
106  // Generate multiple scattering space angle perpendicular to the particle motion
107  double theta = random.gaussShoot(0., theta0);
108  // Plus a random rotation angle around the particle motion
109  double phi = 2. * M_PI * random.flatShoot();
110 
111  // The two rotations
112  ROOT::Math::AxisAngle rotation1(orthogonal(particle.momentum().Vect()), theta);
113  ROOT::Math::AxisAngle rotation2(particle.momentum().Vect(), phi);
114  // Rotate!
115  XYZVector rotated = rotation2((rotation1(particle.momentum().Vect())));
116  particle.momentum().SetXYZT(rotated.X(), rotated.Y(), rotated.Z(), particle.momentum().E());
117 
118  // Generate mutiple scattering displacements in cm (assuming the detectors
119  // are silicon only to determine the thickness) in the directions orthogonal
120  // to the vector normal to the surface
121  double xp = (cos(phi) * theta / 2. + random.gaussShoot(0., theta0) / sqrt(12.)) * radLengths * radLenInCm_;
122  double yp = (sin(phi) * theta / 2. + random.gaussShoot(0., theta0) / sqrt(12.)) * radLengths * radLenInCm_;
123 
124  // Determine a unitary vector tangent to the surface
125  XYZVector normal;
126  if (layer.isForward()) {
127  normal = XYZVector(0., 0., particle.momentum().Pz() > 0. ? 1. : -1.);
128  } else {
129  double norm = particle.position().Rho();
130  normal = XYZVector(particle.position().X() / norm, particle.position().Y() / norm, 0.);
131  }
132  XYZVector tangent = orthogonal(normal);
133  // The total displacement
134  XYZVector delta = xp * tangent + yp * normal.Cross(tangent);
135  // Translate!
136  particle.position().SetXYZT(particle.position().X() + delta.X(),
137  particle.position().Y() + delta.Y(),
138  particle.position().Z() + delta.Z(),
139  particle.position().T());
140 
141  // Make sure particle is still physically on the layer (particle moved on a tangent but a barrel layer is bent)
142  // Happens only in very very few cases
143  if (!layer.isForward() && std::abs(layer.getGeomProperty() - particle.position().Rho()) > 1e-2) {
144  // Scale positions so the radii agree
145  double scalePos = layer.getGeomProperty() / particle.position().Rho();
146  particle.position().SetXYZT(particle.position().X() * scalePos,
147  particle.position().Y() * scalePos,
148  particle.position().Z(),
149  particle.position().T());
150 
151  // Add a protection in case something goes wrong
152  if (std::abs(layer.getGeomProperty() - particle.position().Rho()) > 1e-2) {
153  throw cms::Exception("fastsim::MultipleScattering") << "particle no longer on layer's surface";
154  }
155  }
156 }
157 
159  double x = fabs(aVector.X());
160  double y = fabs(aVector.Y());
161  double z = fabs(aVector.Z());
162 
163  if (x < y)
164  return x < z ? XYZVector(0., aVector.Z(), -aVector.Y()) : XYZVector(aVector.Y(), -aVector.X(), 0.);
165  else
166  return y < z ? XYZVector(-aVector.Z(), 0., aVector.X()) : XYZVector(aVector.Y(), -aVector.X(), 0.);
167 }
168 
Implementation of a generic detector layer (base class for forward/barrel layers).
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
const math::XYZTLorentzVector & position() const
Return position of the particle.
Definition: Particle.h:140
~MultipleScattering() override
Default destructor.
constexpr std::array< uint8_t, layerIndexSize > layer
Base class for any interaction model between a particle and a tracker layer.
T sqrt(T t)
Definition: SSEVec.h:19
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double gaussShoot(double mean=0.0, double sigma=1.0) const
#define M_PI
XYZVector orthogonal(const XYZVector &aVector) const
Return an orthogonal vector.
XYZVectorD XYZVector
spatial vector with cartesian internal representation
Definition: Vector3D.h:31
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:143
MultipleScattering(const std::string &name, const edm::ParameterSet &cfg)
Constructor.
double charge() const
Return charge of the particle.
Definition: Particle.h:137
double radLenInCm_
Radiation length of material (usually silicon X0=9.360)
math::XYZVector XYZVector
float x
Implementation of multiple scattering in the tracker layers.
#define DEFINE_EDM_PLUGIN(factory, type, name)
double flatShoot(double xmin=0.0, double xmax=1.0) const
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
Definition: Particle.h:16
math::XYZVector XYZVector
Definition: RawParticle.h:26
void interact(Particle &particle, const SimplifiedGeometry &layer, std::vector< std::unique_ptr< Particle > > &secondaries, const RandomEngineAndDistribution &random) override
Perform the interaction.
Geom::Theta< T > theta() const
double minPt_
Cut on minimum pT of particle.