CMS 3D CMS Logo

PairProduction.cc
Go to the documentation of this file.
6 
7 #include <cmath>
8 #include <memory>
9 
10 #include <Math/RotationY.h>
11 #include <Math/RotationZ.h>
12 
17 
19 // Author: Patrick Janot
20 // Date: 24-Dec-2003
21 //
22 // Revision: Class structure modified to match SimplifiedGeometryPropagator
23 // S. Kurz, 29 May 2017
25 
26 namespace fastsim {
28 
32  public:
35 
37  ~PairProduction() override { ; };
38 
40 
46  void interact(fastsim::Particle& particle,
47  const SimplifiedGeometry& layer,
48  std::vector<std::unique_ptr<fastsim::Particle> >& secondaries,
49  const RandomEngineAndDistribution& random) override;
50 
51  private:
53 
60  double gbteth(double ener, double partm, double efrac, const RandomEngineAndDistribution& random) const;
61 
63  double Z_;
64  };
65 } // namespace fastsim
66 
68  : fastsim::InteractionModel(name) {
69  // Set the minimal photon energy for possible conversion
70  minPhotonEnergy_ = cfg.getParameter<double>("photonEnergyCut");
71  // Material properties
72  Z_ = cfg.getParameter<double>("Z");
73 }
74 
76  const SimplifiedGeometry& layer,
77  std::vector<std::unique_ptr<fastsim::Particle> >& secondaries,
78  const RandomEngineAndDistribution& random) {
79  double eGamma = particle.momentum().e();
80  //
81  // only consider photons
82  //
83  if (particle.pdgId() != 22) {
84  return;
85  }
86 
87  double radLengths = layer.getThickness(particle.position(), particle.momentum());
88  //
89  // no material
90  //
91  if (radLengths < 1E-10) {
92  return;
93  }
94 
95  //
96  // The photon has enough energy to create a pair
97  //
98  if (eGamma < minPhotonEnergy_) {
99  return;
100  }
101 
102  //
103  // Probability to convert is 7/9*(dx/X0)
104  //
105  if (-std::log(random.flatShoot()) > (7. / 9.) * radLengths) {
106  return;
107  }
108 
109  double xe = 0;
111  double xm = eMass / eGamma;
112  double weight = 0.;
113 
114  // Generate electron energy between emass and eGamma-emass
115  do {
116  xe = random.flatShoot() * (1. - 2. * xm) + xm;
117  weight = 1. - 4. / 3. * xe * (1. - xe);
118  } while (weight < random.flatShoot());
119 
120  // the electron
121  double eElectron = xe * eGamma;
122  double tElectron = eElectron - eMass;
123  double pElectron = std::sqrt(std::max((eElectron + eMass) * tElectron, 0.));
124 
125  // the positron
126  double ePositron = eGamma - eElectron;
127  double tPositron = ePositron - eMass;
128  double pPositron = std::sqrt((ePositron + eMass) * tPositron);
129 
130  // Generate angles
131  double phi = random.flatShoot() * 2. * M_PI;
132  double sphi = std::sin(phi);
133  double cphi = std::cos(phi);
134 
135  double stheta1, stheta2, ctheta1, ctheta2;
136 
137  if (eElectron > ePositron) {
138  double theta1 = gbteth(eElectron, eMass, xe, random) * eMass / eElectron;
139  stheta1 = std::sin(theta1);
140  ctheta1 = std::cos(theta1);
141  stheta2 = stheta1 * pElectron / pPositron;
142  ctheta2 = std::sqrt(std::max(0., 1.0 - (stheta2 * stheta2)));
143  } else {
144  double theta2 = gbteth(ePositron, eMass, xe, random) * eMass / ePositron;
145  stheta2 = std::sin(theta2);
146  ctheta2 = std::cos(theta2);
147  stheta1 = stheta2 * pPositron / pElectron;
148  ctheta1 = std::sqrt(std::max(0., 1.0 - (stheta1 * stheta1)));
149  }
150 
151  //Rotate to the lab frame
152  double thetaLab = particle.momentum().Theta();
153  double phiLab = particle.momentum().Phi();
154 
155  // Add a electron
156  secondaries.emplace_back(new fastsim::Particle(
157  11,
158  particle.position(),
159  math::XYZTLorentzVector(pElectron * stheta1 * cphi, pElectron * stheta1 * sphi, pElectron * ctheta1, eElectron)));
160  secondaries.back()->momentum() =
161  ROOT::Math::RotationZ(phiLab) * (ROOT::Math::RotationY(thetaLab) * secondaries.back()->momentum());
162 
163  // Add a positron
164  secondaries.emplace_back(new fastsim::Particle(
165  -11,
166  particle.position(),
168  -pPositron * stheta2 * cphi, -pPositron * stheta2 * sphi, pPositron * ctheta2, ePositron)));
169  secondaries.back()->momentum() =
170  ROOT::Math::RotationZ(phiLab) * (ROOT::Math::RotationY(thetaLab) * secondaries.back()->momentum());
171 
172  // The photon converted
173  particle.momentum().SetXYZT(0., 0., 0., 0.);
174 }
175 
176 double fastsim::PairProduction::gbteth(const double ener,
177  const double partm,
178  const double efrac,
179  const RandomEngineAndDistribution& random) const {
180  // Details on implementation here
181  // http://www.dnp.fmph.uniba.sk/cernlib/asdoc/geant_html3/node299.html#GBTETH
182  // http://svn.cern.ch/guest/AliRoot/tags/v3-07-03/GEANT321/gphys/gbteth.F
183 
184  const double alfa = 0.625;
185 
186  const double d = 0.13 * (0.8 + 1.3 / Z_) * (100.0 + (1.0 / ener)) * (1.0 + efrac);
187  const double w1 = 9.0 / (9.0 + d);
188  const double umax = ener * M_PI / partm;
189  double u;
190 
191  do {
192  double beta = (random.flatShoot() <= w1) ? alfa : 3.0 * alfa;
193  u = -std::log(random.flatShoot() * random.flatShoot()) / beta;
194  } while (u >= umax);
195 
196  return u;
197 }
198 
T getParameter(std::string const &) const
Implementation of a generic detector layer (base class for forward/barrel layers).
const math::XYZTLorentzVector & position() const
Return position of the particle.
Definition: Particle.h:140
double flatShoot(double xmin=0.0, double xmax=1.0) const
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
double Z_
Atomic number of material (usually silicon Z=14)
Definition: weight.py:1
int pdgId() const
Return pdgId of the particle.
Definition: Particle.h:134
static double constexpr eMass
Electron mass[GeV].
Definition: Constants.h:13
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
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
Computes the probability for photons to convert into an e+e- pair in the tracker layer.
d
Definition: ztail.py:151
#define M_PI
PairProduction(const std::string &name, const edm::ParameterSet &cfg)
Constructor.
virtual const double getThickness(const math::XYZTLorentzVector &position) const =0
Return thickness of the layer at a given position.
double minPhotonEnergy_
Cut on minimum energy of photons.
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:143
~PairProduction() override
Default destructor.
#define DEFINE_EDM_PLUGIN(factory, type, name)
void interact(fastsim::Particle &particle, const SimplifiedGeometry &layer, std::vector< std::unique_ptr< fastsim::Particle > > &secondaries, const RandomEngineAndDistribution &random) override
Perform the interaction.
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
Definition: Particle.h:16
double gbteth(double ener, double partm, double efrac, const RandomEngineAndDistribution &random) const
A universal angular distribution.