CMS 3D CMS Logo

MuonBremsstrahlung.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 #include <TMath.h>
19 #include <TF1.h>
20 
21 
23 // Authors: Sandro Fonseca de Souza and Andre Sznajder (UERJ/Brazil)
24 // Date: 23-Nov-2010
25 //
26 // Revision: Class structure modified to match SimplifiedGeometryPropagator
27 // S. Sekmen, 18 May 2017
28 //
29 // Revision: Code very buggy, PetrukhinFunc return negative values, double bremProba wasn't properly defined etc.
30 // Should be all fixed by now
31 // S. Kurz, 23 May 2017
33 
34 
35 namespace fastsim
36 {
38 
43  {
44  public:
47 
49  ~MuonBremsstrahlung() override{;};
50 
52 
58  void interact(Particle & particle, const SimplifiedGeometry & layer, std::vector<std::unique_ptr<Particle> > & secondaries, const RandomEngineAndDistribution & random) override;
59 
60  private:
62 
69  double xmin,
70  const RandomEngineAndDistribution & random) const;
71 
73 
80  double gbteth(const double ener,
81  const double partm,
82  const double efrac,
83  const RandomEngineAndDistribution & random) const;
84 
86  static double PetrukhinFunc(double *x, double *p);
87 
88  TF1* Petrfunc;
91  double density_;
92  double radLenInCm_;
93  double A_;
94  double Z_;
95  };
96 }
97 
99  : fastsim::InteractionModel(name)
100 {
101  // Set the minimal photon energy for a Brem from mu+/-
102  minPhotonEnergy_ = cfg.getParameter<double>("minPhotonEnergy");
103  minPhotonEnergyFraction_ = cfg.getParameter<double>("minPhotonEnergyFraction");
104  // Material properties
105  A_ = cfg.getParameter<double>("A");
106  Z_ = cfg.getParameter<double>("Z");
107  density_ = cfg.getParameter<double>("density");
108  radLenInCm_ = cfg.getParameter<double>("radLen");
109 }
110 
111 
113  const SimplifiedGeometry & layer,
114  std::vector<std::unique_ptr<fastsim::Particle> > & secondaries,
116 {
117  // only consider muons
118  if(std::abs(particle.pdgId())!=13)
119  {
120  return;
121  }
122 
123  double radLengths = layer.getThickness(particle.position(),particle.momentum());
124  //
125  // no material
126  //
127  if(radLengths < 1E-10)
128  {
129  return;
130  }
131 
132  // Protection : Just stop the electron if more than 1 radiation lengths.
133  // This case corresponds to an electron entering the layer parallel to
134  // the layer axis - no reliable simulation can be done in that case...
135  if(radLengths > 4.)
136  {
137  particle.momentum().SetXYZT(0.,0.,0.,0.);
138  return;
139  }
140 
141  // muon must have more energy than minimum photon energy
142  if(particle.momentum().E() - particle.momentum().mass() < minPhotonEnergy_)
143  {
144  return;
145  }
146 
147  // Min fraction of muon's energy transferred to the photon
149  // Hard brem probability with a photon Energy above threshold.
150  if(xmin >=1. || xmin <=0.)
151  {
152  return;
153  }
154 
155  // Max fraction of muon's energy transferred to the photon
156  double xmax = 1.;
157 
158  // create TF1 using a free C function
159  Petrfunc = new TF1("Petrfunc", PetrukhinFunc, xmin, xmax, 3);
160  // Setting parameters
161  Petrfunc->SetParameters(particle.momentum().E(), A_, Z_);
162  // d = distance for several materials
163  // X0 = radLen
164  // d = radLengths * X0 (for tracker, yoke, ECAL and HCAL)
165  double distance = radLengths * radLenInCm_;
166 
167  // Integration
168  // Fixed previous version which used Petrfunc->Integral(0.,1.) -> does not make sense
169  double bremProba = density_ * distance * (fastsim::Constants::NA / A_) * (Petrfunc->Integral(xmin, xmax));
170  if(bremProba < 1E-10)
171  {
172  return;
173  }
174 
175 
176  // Number of photons to be radiated.
177  unsigned int nPhotons = random.poissonShoot(bremProba);
178  if(nPhotons == 0)
179  {
180  return;
181  }
182 
183  //Rotate to the lab frame
184  double theta = particle.momentum().Theta();
185  double phi = particle.momentum().Phi();
186 
187  // Energy of these photons
188  for(unsigned int i=0; i<nPhotons; ++i)
189  {
190  // Throw momentum of the photon
191  math::XYZTLorentzVector photonMom = brem(particle, xmin, random);
192 
193  // Check that there is enough energy left.
194  if(particle.momentum().E() - particle.momentum().mass() < photonMom.E()) break;
195 
196  // Rotate to the lab frame
197  photonMom = ROOT::Math::RotationZ(phi) * (ROOT::Math::RotationY(theta) * photonMom);
198 
199  // Add a photon
200  secondaries.emplace_back(new fastsim::Particle(22, particle.position(), photonMom));
201 
202  // Update the original e+/-
203  particle.momentum() -= photonMom;
204  }
205 }
206 
207 
210  double xmin,
211  const RandomEngineAndDistribution & random) const
212 {
213  // This is a simple version of a Muon Brem using Petrukhin model.
214  // Ref: http://pdg.lbl.gov/2008/AtomicNuclearProperties/adndt.pdf
215  double xp = Petrfunc->GetRandom();
216 
217  // Have photon energy. Now generate angles with respect to the z axis
218  // defined by the incoming particle's momentum.
219 
220  // Isotropic in phi
221  const double phi = random.flatShoot() * 2. * M_PI;
222  // theta from universal distribution
223  const double theta = gbteth(particle.momentum().E(), fastsim::Constants::muMass, xp, random)
224  * fastsim::Constants::muMass / particle.momentum().E();
225 
226  // Make momentum components
227  double stheta = std::sin(theta);
228  double ctheta = std::cos(theta);
229  double sphi = std::sin(phi);
230  double cphi = std::cos(phi);
231 
232  return xp * particle.momentum().E() * math::XYZTLorentzVector(stheta*cphi, stheta*sphi, ctheta, 1.);
233 }
234 
235 double
237  const double partm,
238  const double efrac,
239  const RandomEngineAndDistribution & random) const
240 {
241  // Details on implementation here
242  // http://www.dnp.fmph.uniba.sk/cernlib/asdoc/geant_html3/node299.html#GBTETH
243  // http://svn.cern.ch/guest/AliRoot/tags/v3-07-03/GEANT321/gphys/gbteth.F
244 
245  const double alfa = 0.625;
246 
247  const double d = 0.13*(0.8+1.3/Z_)*(100.0+(1.0/ener))*(1.0+efrac);
248  const double w1 = 9.0/(9.0+d);
249  const double umax = ener*M_PI/partm;
250  double u;
251 
252  do
253  {
254  double beta = (random.flatShoot()<=w1) ? alfa : 3.0*alfa;
255  u = -std::log(random.flatShoot()*random.flatShoot())/beta;
256  }while (u >= umax);
257 
258  return u;
259 }
260 
261 double
263 
264  // Function independent variable
265  double nu = x[0]; // fraction of muon's energy transferred to the photon
266 
267  // Parameters
268  double E=p[0]; // Muon Energy (in GeV)
269  double A=p[1]; // Atomic weight
270  double Z=p[2]; // Atomic number
271 
272  /*
274  // Function of Muom Brem using nuclear screening correction
275  // Ref: http://pdg.lbl.gov/2008/AtomicNuclearProperties/adndt.pdf
276  // http://geant4.cern.ch/G4UsersDocuments/UsersGuides/PhysicsReferenceManual/html/node48.html
277 
278  // Physical constants
279  double B = 182.7;
280  double ee = sqrt(2.7181) ; // sqrt(e)
281  double ZZ= pow( Z,-1./3.); // Z^-1/3
283  double emass = 0.0005109990615; // electron mass (GeV/c^2)
284  double mumass = 0.105658367;//mu mass (GeV/c^2)
285 
286  double re = 2.817940285e-13;// Classical electron radius (Units: cm)
287  double alpha = 1./137.03599976; // fine structure constant
288  double Dn = 1.54* (pow(A,0.27));
289  double constant = pow((2.0 * Z * emass/mumass * re ),2.0);
291 
292  double delta = (mumass * mumass * nu) /(2.* E * (1.- nu));
293 
294  double Delta_n = TMath::Log(Dn / (1.+ delta *( Dn * ee -2.)/ mumass)); //nuclear screening correction
295 
296  double Phi = TMath::Log((B * mumass * ZZ / emass)/ (1.+ delta * ee * B * ZZ / emass)) - Delta_n;//phi(delta)
297 
298  // Diff. Cross Section for Muon Brem from a screened nuclear (Equation 16: REF: LBNL-44742)
299  double f = alpha * constant *(4./3.-4./3.*nu + nu*nu)*Phi/nu;
300  */
301 
303  // Function for Muon Brem Xsec from G4
305 
306  // Physical constants
307  double B = 183.;
308  double Bl = 1429.;
309  double ee = 1.64872 ; // sqrt(e)
310  double Z13 = pow(Z, -1./3.); // Z^-1/3
311  double Z23 = pow(Z, -2./3.); // Z^-2/3
312 
313  // Original values of paper
314  double emass = 0.0005109990615; // electron mass (GeV/c^2)
315  double mumass = 0.105658367; // muon mass (GeV/c^2)
316  // double re = 2.817940285e-13; // Classical electron radius (Units: cm)
317  double alpha = 0.00729735; // 1./137.03599976; // fine structure constant
318  double constant = 1.85736e-30; // pow( ( emass / mumass * re ) , 2.0);
319 
320  // Use nomenclature from reference -> Follow those formula step by step
321  if(nu * E >= E - mumass) return 0;
322 
323  double Dn = 1.54 * (pow(A,0.27));
324  double Dnl = pow(Dn, (1. - 1./Z));
325 
326  double delta = (mumass * mumass * nu) / (2.* E * (1.- nu));
327 
328  double Phi_n = TMath::Log(B * Z13 *(mumass + delta * ( Dnl * ee - 2))
329  / (Dnl * (emass + delta * ee * B * Z13)));
330  if(Phi_n < 0) Phi_n = 0;
331 
332  double Phi_e = TMath::Log((Bl * Z23 * mumass)
333  / (1.+ delta * mumass / (emass*emass * ee))
334  / (emass + delta *ee * Bl * Z23));
335  if(Phi_e < 0 || nu * E >= E / (1. + (mumass * mumass / (2. * emass * E)))) Phi_e = 0;
336 
337 
338  // Diff. Cross Section for Muon Brem from G4 (without NA/A factor)
339  double f = 16./3. * alpha * constant * Z * (Z * Phi_n + Phi_e) * (1./nu) * (1. - nu + 0.75 * nu * nu) ;
340 
341  return f;
342 }
343 
344 
348  "fastsim::MuonBremsstrahlung"
349  );
350 
dbl * delta
Definition: mlp_gen.cc:36
static double constexpr NA
Avogadro&#39;s number.
Definition: Constants.h:20
T getParameter(std::string const &) const
float alpha
Definition: AMPTWrapper.h:95
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
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
Geom::Theta< T > theta() const
double minPhotonEnergyFraction_
Cut on minimum fraction of particle&#39;s energy which has to be carried by photon.
static double constexpr muMass
Muon mass [GeV].
Definition: Constants.h:18
int pdgId() const
Return pdgId of the particle.
Definition: Particle.h:136
TRandom random
Definition: MVATrainer.cc:138
double radLenInCm_
Radiation length of material (usually silicon X0=9.360)
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.
double density_
Density of material (usually silicon rho=2.329)
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
double minPhotonEnergy_
Cut on minimum energy of bremsstrahlung photons.
Implementation of Bremsstrahlung from mu+/mu- in the tracker layers based on a Petrukhin Model (nucle...
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
static const std::string B
~MuonBremsstrahlung() override
Default destructor.
TF1 * Petrfunc
The Petrukhin Function.
#define M_PI
static double PetrukhinFunc(double *x, double *p)
Petrukhin Function: Returns cross section using nuclear-electron screening correction from G4 style...
virtual const double getThickness(const math::XYZTLorentzVector &position) const =0
Return thickness of the layer at a given position.
MuonBremsstrahlung(const std::string &name, const edm::ParameterSet &cfg)
Constructor.
double gbteth(const double ener, const double partm, const double efrac, const RandomEngineAndDistribution &random) const
A universal angular distribution.
unsigned int poissonShoot(double mean) const
const math::XYZTLorentzVector & momentum() const
Return momentum of the particle.
Definition: Particle.h:145
void interact(Particle &particle, const SimplifiedGeometry &layer, std::vector< std::unique_ptr< Particle > > &secondaries, const RandomEngineAndDistribution &random) override
Perform the interaction.
#define DEFINE_EDM_PLUGIN(factory, type, name)
double A_
Atomic weight of material (usually silicon A=28.0855)
double Z_
Atomic number of material (usually silicon Z=14)
Definition of a generic FastSim Particle which can be propagated through the detector (formerly Parti...
Definition: Particle.h:19
math::XYZTLorentzVector brem(Particle &particle, double xmin, const RandomEngineAndDistribution &random) const
Compute Brem photon energy and angles, if any.
Power< A, B >::type pow(const A &a, const B &b)
Definition: Power.h:40