CMS 3D CMS Logo

Bremsstrahlung.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 
18 
20 // Author: Patrick Janot
21 // Date: 25-Dec-2003
22 //
23 // Revision: Class structure modified to match SimplifiedGeometryPropagator
24 // Fixed a bug in which particles could radiate more energy than they have
25 // S. Kurz, 29 May 2017
27 
28 
29 namespace fastsim
30 {
32 
37  {
38  public:
41 
43  ~Bremsstrahlung() override{;};
44 
46 
52  void interact(Particle & particle, const SimplifiedGeometry & layer, std::vector<std::unique_ptr<Particle> > & secondaries, const RandomEngineAndDistribution & random) override;
53 
54  private:
56 
62  math::XYZTLorentzVector brem(Particle & particle, double xmin, const RandomEngineAndDistribution & random) const;
63 
65 
72  double gbteth(const double ener,
73  const double partm,
74  const double efrac,
75  const RandomEngineAndDistribution & random) const ;
76 
79  double Z_;
80  };
81 }
82 
84  : fastsim::InteractionModel(name)
85 {
86  // Set the minimal photon energy for a Brem from e+/-
87  minPhotonEnergy_ = cfg.getParameter<double>("minPhotonEnergy");
88  minPhotonEnergyFraction_ = cfg.getParameter<double>("minPhotonEnergyFraction");
89  // Material properties
90  Z_ = cfg.getParameter<double>("Z");
91 }
92 
93 
94 void fastsim::Bremsstrahlung::interact(fastsim::Particle & particle, const SimplifiedGeometry & layer,std::vector<std::unique_ptr<fastsim::Particle> > & secondaries,const RandomEngineAndDistribution & random)
95 {
96  // only consider electrons and positrons
97  if(std::abs(particle.pdgId())!=11)
98  {
99  return;
100  }
101 
102  double radLengths = layer.getThickness(particle.position(),particle.momentum());
103  //
104  // no material
105  //
106  if(radLengths < 1E-10)
107  {
108  return;
109  }
110 
111  // Protection : Just stop the electron if more than 1 radiation lengths.
112  // This case corresponds to an electron entering the layer parallel to
113  // the layer axis - no reliable simulation can be done in that case...
114  if(radLengths > 4.)
115  {
116  particle.momentum().SetXYZT(0.,0.,0.,0.);
117  return;
118  }
119 
120  // electron must have more energy than minimum photon energy
121  if(particle.momentum().E() - particle.momentum().mass() < minPhotonEnergy_)
122  {
123  return;
124  }
125 
126  // Hard brem probability with a photon Energy above threshold.
128  if(xmin >=1. || xmin <=0.)
129  {
130  return;
131  }
132 
133  // probability to radiate a photon
134  double bremProba = radLengths * (4./3. * std::log(1./xmin)
135  - 4./3. * (1.-xmin)
136  + 1./2. * (1.-xmin*xmin));
137 
138 
139  // Number of photons to be radiated.
140  unsigned int nPhotons = random.poissonShoot(bremProba);
141  if(nPhotons == 0)
142  {
143  return;
144  }
145 
146  // Needed to rotate photons to the lab frame
147  double theta = particle.momentum().Theta();
148  double phi = particle.momentum().Phi();
149 
150  // Calculate energy of these photons and add them to the event
151  for(unsigned int i=0; i<nPhotons; ++i)
152  {
153  // Throw momentum of the photon
154  math::XYZTLorentzVector photonMom = brem(particle, xmin, random);
155 
156  // Check that there is enough energy left.
157  if(particle.momentum().E() - particle.momentum().mass() < photonMom.E()) break;
158 
159  // Rotate to the lab frame
160  photonMom = ROOT::Math::RotationZ(phi) * (ROOT::Math::RotationY(theta) * photonMom);
161 
162  // Add a photon
163  secondaries.emplace_back(new fastsim::Particle(22, particle.position(), photonMom));
164 
165  // Update the original e+/-
166  particle.momentum() -= photonMom;
167  }
168 }
169 
170 
173 {
174  double xp=0;
175  double weight = 0.;
176 
177  do{
178  xp = xmin * std::exp ( -std::log(xmin) * random.flatShoot() );
179  weight = 1. - xp + 3./4.*xp*xp;
180  }while(weight < random.flatShoot());
181 
182 
183  // Have photon energy. Now generate angles with respect to the z axis
184  // defined by the incoming particle's momentum.
185 
186  // Isotropic in phi
187  const double phi = random.flatShoot() * 2. * M_PI;
188  // theta from universal distribution
189  const double theta = gbteth(particle.momentum().E(), fastsim::Constants::eMass, xp, random)
190  * fastsim::Constants::eMass / particle.momentum().E();
191 
192  // Make momentum components
193  double stheta = std::sin(theta);
194  double ctheta = std::cos(theta);
195  double sphi = std::sin(phi);
196  double cphi = std::cos(phi);
197 
198  return xp * particle.momentum().E() * math::XYZTLorentzVector(stheta*cphi, stheta*sphi, ctheta, 1.);
199 }
200 
201 double
203  const double partm,
204  const double efrac,
205  const RandomEngineAndDistribution & random) const
206 {
207  // Details on implementation here
208  // http://www.dnp.fmph.uniba.sk/cernlib/asdoc/geant_html3/node299.html#GBTETH
209  // http://svn.cern.ch/guest/AliRoot/tags/v3-07-03/GEANT321/gphys/gbteth.F
210 
211  const double alfa = 0.625;
212 
213  const double d = 0.13*(0.8+1.3/Z_)*(100.0+(1.0/ener))*(1.0+efrac);
214  const double w1 = 9.0/(9.0+d);
215  const double umax = ener*M_PI/partm;
216  double u;
217 
218  do
219  {
220  double beta = (random.flatShoot()<=w1) ? alfa : 3.0*alfa;
221  u = -std::log(random.flatShoot()*random.flatShoot())/beta;
222  }while (u >= umax);
223 
224  return u;
225 }
226 
230  "fastsim::Bremsstrahlung"
231  );
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:142
double flatShoot(double xmin=0.0, double xmax=1.0) const
double minPhotonEnergy_
Cut on minimum energy of bremsstrahlung photons.
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
Geom::Theta< T > theta() const
void interact(Particle &particle, const SimplifiedGeometry &layer, std::vector< std::unique_ptr< Particle > > &secondaries, const RandomEngineAndDistribution &random) override
Perform the interaction.
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:136
TRandom random
Definition: MVATrainer.cc:138
static double constexpr eMass
Electron mass[GeV].
Definition: Constants.h:17
Bremsstrahlung(const std::string &name, const edm::ParameterSet &cfg)
Constructor.
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.
~Bremsstrahlung() override
Default destructor.
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
#define M_PI
double gbteth(const double ener, const double partm, const double efrac, const RandomEngineAndDistribution &random) const
A universal angular distribution.
Implementation of Bremsstrahlung from e+/e- in the tracker layers.
virtual const double getThickness(const math::XYZTLorentzVector &position) const =0
Return thickness of the layer at a given position.
unsigned int poissonShoot(double mean) const
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:145
#define DEFINE_EDM_PLUGIN(factory, type, name)
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
Definition: Particle.h:19
double minPhotonEnergyFraction_
Cut on minimum fraction of particle&#39;s energy which has to be carried by photon.
math::XYZTLorentzVector brem(Particle &particle, double xmin, const RandomEngineAndDistribution &random) const
Compute Brem photon energy and angles, if any.