CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_4_1_8_patch9/src/FastSimulation/MaterialEffects/src/BremsstrahlungSimulator.cc

Go to the documentation of this file.
00001 //FAMOS Headers
00002 #include "FastSimulation/MaterialEffects/interface/BremsstrahlungSimulator.h"
00003 #include "FastSimulation/Utilities/interface/RandomEngine.h"
00004 
00005 #include <cmath>
00006 
00007 BremsstrahlungSimulator::BremsstrahlungSimulator(double photonEnergyCut, 
00008                                                  double photonFractECut,
00009                                                  const RandomEngine* engine) : 
00010   MaterialEffectsSimulator(engine) 
00011 {
00012 
00013   // Set the minimal photon energy for a Brem from e+/-
00014   photonEnergy = photonEnergyCut;
00015   photonFractE = photonFractECut;
00016 
00017 }
00018 
00019 
00020 void 
00021 BremsstrahlungSimulator::compute(ParticlePropagator &Particle)
00022 {
00023 
00024   // Protection : Just stop the electron if more than 1 radiation lengths.
00025   // This case corresponds to an electron entering the layer parallel to 
00026   // the layer axis - no reliable simulation can be done in that case...
00027   // 08/02/06 - pv: increase protection from 1 to 4 X0 for eta>4.8 region
00028   // if ( radLengths > 1. ) Particle.SetXYZT(0.,0.,0.,0.);
00029   if ( radLengths > 4. ) Particle.SetXYZT(0.,0.,0.,0.);
00030 
00031   // Hard brem probability with a photon Energy above photonEnergy.
00032   if (Particle.e()<photonEnergy) return;
00033   xmin = std::max(photonEnergy/Particle.e(),photonFractE);
00034   if ( xmin >=1. || xmin <=0. ) return;
00035 
00036   double bremProba = radLengths * ( 4./3. * std::log(1./xmin)
00037                                   - 4./3. * (1.-xmin)
00038                                   + 1./2. * (1.-xmin*xmin) );
00039 
00040   
00041   // Number of photons to be radiated.
00042   unsigned int nPhotons = poisson(bremProba);
00043   _theUpdatedState.reserve(nPhotons);
00044 
00045   if ( !nPhotons ) return;
00046 
00047   //Rotate to the lab frame
00048   double chi = Particle.theta();
00049   double psi = Particle.phi();
00050   RawParticle::RotationZ rotZ(psi);
00051   RawParticle::RotationY rotY(chi);
00052     
00053   // Energy of these photons
00054   for ( unsigned int i=0; i<nPhotons; ++i ) {
00055 
00056     // Check that there is enough energy left.
00057     if ( Particle.e() < photonEnergy ) break;
00058 
00059     // Add a photon
00060     RawParticle thePhoton(22,brem(Particle));    
00061     thePhoton.rotate(rotY);
00062     thePhoton.rotate(rotZ);
00063     _theUpdatedState.push_back(thePhoton);
00064         
00065     // Update the original e+/-
00066     Particle -= thePhoton.momentum();
00067 
00068   }     
00069 }
00070 
00071 XYZTLorentzVector 
00072 BremsstrahlungSimulator::brem(ParticlePropagator& pp) const {
00073 
00074   // This is a simple version (a la PDG) of a Brem generator.
00075   // It replaces the buggy GEANT3 -> C++ former version.
00076   // Author : Patrick Janot - 25-Dec-2003
00077   double emass = 0.0005109990615;
00078   double xp=0;
00079   double weight = 0.;
00080   
00081   do {
00082     xp = xmin * std::exp ( -std::log(xmin) * random->flatShoot() );
00083     weight = 1. - xp + 3./4.*xp*xp;
00084   } while ( weight < random->flatShoot() );
00085   
00086   
00087   // Have photon energy. Now generate angles with respect to the z axis 
00088   // defined by the incoming particle's momentum.
00089 
00090   // Isotropic in phi
00091   const double phi = random->flatShoot()*2*M_PI;
00092   // theta from universal distribution
00093   const double theta = gbteth(pp.e(),emass,xp)*emass/pp.e(); 
00094   
00095   // Make momentum components
00096   double stheta = std::sin(theta);
00097   double ctheta = std::cos(theta);
00098   double sphi   = std::sin(phi);
00099   double cphi   = std::cos(phi);
00100   
00101   return xp * pp.e() * XYZTLorentzVector(stheta*cphi,stheta*sphi,ctheta,1.);
00102   
00103 }
00104 
00105 double
00106 BremsstrahlungSimulator::gbteth(const double ener,
00107                                 const double partm,
00108                                 const double efrac) const {
00109   const double alfa = 0.625;
00110 
00111   const double d = 0.13*(0.8+1.3/theZ())*(100.0+(1.0/ener))*(1.0+efrac);
00112   const double w1 = 9.0/(9.0+d);
00113   const double umax = ener*M_PI/partm;
00114   double u;
00115   
00116   do {
00117     double beta = (random->flatShoot()<=w1) ? alfa : 3.0*alfa;
00118     u = -std::log(random->flatShoot()*random->flatShoot())/beta;
00119   } while (u>=umax);
00120 
00121   return u;
00122 }
00123 
00124 
00125 unsigned int 
00126 BremsstrahlungSimulator::poisson(double ymu) {
00127 
00128   unsigned int n = 0;
00129   double prob = std::exp(-ymu);
00130   double proba = prob;
00131   double x = random->flatShoot();
00132   
00133   while ( proba <= x ) {
00134     prob *= ymu / double(++n);
00135     proba += prob;
00136   }
00137   
00138   return n;                                                        
00139   
00140 }
00141