CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_5/src/SimTracker/Common/src/SiG4UniversalFluctuation.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * DISCLAIMER                                                       *
00004 // *                                                                  *
00005 // * The following disclaimer summarizes all the specific disclaimers *
00006 // * of contributors to this software. The specific disclaimers,which *
00007 // * govern, are listed with their locations in:                      *
00008 // *   http://cern.ch/geant4/license                                  *
00009 // *                                                                  *
00010 // * Neither the authors of this software system, nor their employing *
00011 // * institutes,nor the agencies providing financial support for this *
00012 // * work  make  any representation or  warranty, express or implied, *
00013 // * regarding  this  software system or assume any liability for its *
00014 // * use.                                                             *
00015 // *                                                                  *
00016 // * This  code  implementation is the  intellectual property  of the *
00017 // * GEANT4 collaboration.                                            *
00018 // * By copying,  distributing  or modifying the Program (or any work *
00019 // * based  on  the Program)  you indicate  your  acceptance of  this *
00020 // * statement, and all its terms.                                    *
00021 // ********************************************************************
00022 //
00023 // $Id: SiG4UniversalFluctuation.cc,v 1.9 2013/04/25 18:17:07 civanch Exp $
00024 // GEANT4 tag $Name: CMSSW_6_2_0 $
00025 //
00026 // -------------------------------------------------------------------
00027 //
00028 // GEANT4 Class file
00029 //
00030 //
00031 // File name:     G4UniversalFluctuation
00032 //
00033 // Author:        Vladimir Ivanchenko 
00034 // 
00035 // Creation date: 03.01.2002
00036 //
00037 // Modifications: 
00038 //
00039 // 28-12-02 add method Dispersion (V.Ivanchenko)
00040 // 07-02-03 change signature (V.Ivanchenko)
00041 // 13-02-03 Add name (V.Ivanchenko)
00042 // 16-10-03 Changed interface to Initialisation (V.Ivanchenko)
00043 // 07-11-03 Fix problem of rounding of double in G4UniversalFluctuations
00044 // 06-02-04 Add control on big sigma > 2*meanLoss (V.Ivanchenko)
00045 // 26-04-04 Comment out the case of very small step (V.Ivanchenko)
00046 // 07-02-05 define problim = 5.e-3 (mma)
00047 // 03-05-05 conditions of Gaussian fluctuation changed (bugfix)
00048 //          + smearing for very small loss (L.Urban)
00049 //  
00050 // Modified for standalone use in CMSSW. danek k. 2/06        
00051 // 25-04-13 Used vdt::log, added check a3>0 (V.Ivanchenko & D. Nikolopoulos)         
00052 
00053 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00054 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00055 
00056 #include "SimTracker/Common/interface/SiG4UniversalFluctuation.h"
00057 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00058 #include "CLHEP/Units/GlobalPhysicalConstants.h"
00059 #include "CLHEP/Random/RandGaussQ.h"
00060 #include "CLHEP/Random/RandPoissonQ.h"
00061 #include "CLHEP/Random/RandFlat.h"
00062 #include <math.h>
00063 #include "vdt/log.h"
00064 //#include "G4UniversalFluctuation.hh"
00065 //#include "Randomize.hh"
00066 //#include "G4Poisson.hh"
00067 //#include "G4Step.hh"
00068 //#include "G4Material.hh"
00069 //#include "G4DynamicParticle.hh"
00070 //#include "G4ParticleDefinition.hh"
00071 
00072 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00073 
00074 using namespace std;
00075 
00076 SiG4UniversalFluctuation::SiG4UniversalFluctuation(CLHEP::HepRandomEngine& eng)
00077   :rndEngine(eng),
00078    gaussQDistribution(0),
00079    poissonQDistribution(0),
00080    flatDistribution(0),
00081    minNumberInteractionsBohr(10.0),
00082    theBohrBeta2(50.0*keV/proton_mass_c2),
00083    minLoss(10.*eV),
00084    problim(5.e-3),  
00085    alim(10.),
00086    nmaxCont1(4.),
00087    nmaxCont2(16.)
00088 {
00089   sumalim = -log(problim);
00090   //lastMaterial = 0;
00091   
00092   // Add these definitions d.k.
00093   chargeSquare   = 1.;  //Assume all particles have charge 1
00094   // Taken from Geant4 printout, HARDWIRED for Silicon.
00095   ipotFluct = 0.0001736; //material->GetIonisation()->GetMeanExcitationEnergy();  
00096   electronDensity = 6.797E+20; // material->GetElectronDensity();
00097   f1Fluct      = 0.8571; // material->GetIonisation()->GetF1fluct();
00098   f2Fluct      = 0.1429; //material->GetIonisation()->GetF2fluct();
00099   e1Fluct      = 0.000116;// material->GetIonisation()->GetEnergy1fluct();
00100   e2Fluct      = 0.00196; //material->GetIonisation()->GetEnergy2fluct();
00101   e1LogFluct   = -9.063;  //material->GetIonisation()->GetLogEnergy1fluct();
00102   e2LogFluct   = -6.235;  //material->GetIonisation()->GetLogEnergy2fluct();
00103   rateFluct    = 0.4;     //material->GetIonisation()->GetRateionexcfluct();
00104   ipotLogFluct = -8.659;  //material->GetIonisation()->GetLogMeanExcEnergy();
00105   e0 = 1.E-5;             //material->GetIonisation()->GetEnergy0fluct();
00106   
00107   gaussQDistribution = new CLHEP::RandGaussQ(rndEngine);
00108   poissonQDistribution = new CLHEP::RandPoissonQ(rndEngine);
00109   flatDistribution = new CLHEP::RandFlat(rndEngine);
00110 
00111   //cout << " init new fluct +++++++++++++++++++++++++++++++++++++++++"<<endl;
00112 }
00113 
00114 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00115 // The main dedx fluctuation routine.
00116 // Arguments: momentum in MeV/c, mass in MeV, delta ray cut (tmax) in
00117 // MeV, silicon thickness in mm, mean eloss in MeV.
00118 
00119 SiG4UniversalFluctuation::~SiG4UniversalFluctuation()
00120 {
00121   delete gaussQDistribution;
00122   delete poissonQDistribution;
00123   delete flatDistribution;
00124 
00125 }
00126 
00127 
00128 double SiG4UniversalFluctuation::SampleFluctuations(const double momentum,
00129                                                     const double mass,
00130                                                     double& tmax,
00131                                                     const double length,
00132                                                     const double meanLoss)
00133 {
00134 // Calculate actual loss from the mean loss.
00135 // The model used to get the fluctuations is essentially the same
00136 // as in Glandz in Geant3 (Cern program library W5013, phys332).
00137 // L. Urban et al. NIM A362, p.416 (1995) and Geant4 Physics Reference Manual
00138 
00139   // shortcut for very very small loss (out of validity of the model)
00140   //
00141   if (meanLoss < minLoss) return meanLoss;
00142 
00143   //if(!particle) InitialiseMe(dp->GetDefinition());
00144   //G4double tau   = dp->GetKineticEnergy()/particleMass;
00145   //G4double gam   = tau + 1.0;
00146   //G4double gam2  = gam*gam;
00147   //G4double beta2 = tau*(tau + 2.0)/gam2;
00148 
00149   particleMass   = mass; // dp->GetMass();
00150   double gam2   = (momentum*momentum)/(particleMass*particleMass) + 1.0;
00151   double beta2 = 1.0 - 1.0/gam2;
00152   double gam = sqrt(gam2);
00153 
00154   double loss(0.), siga(0.);
00155   
00156   // Gaussian regime
00157   // for heavy particles only and conditions
00158   // for Gauusian fluct. has been changed 
00159   //
00160   if ((particleMass > electron_mass_c2) &&
00161       (meanLoss >= minNumberInteractionsBohr*tmax))
00162   {
00163     double massrate = electron_mass_c2/particleMass ;
00164     double tmaxkine = 2.*electron_mass_c2*beta2*gam2/
00165       (1.+massrate*(2.*gam+massrate)) ;
00166     if (tmaxkine <= 2.*tmax)   
00167     {
00168       //electronDensity = material->GetElectronDensity();
00169       siga  = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
00170                                 * electronDensity * chargeSquare;
00171       siga = sqrt(siga);
00172       double twomeanLoss = meanLoss + meanLoss;
00173       if (twomeanLoss < siga) {
00174         double x;
00175         do {
00176           loss = twomeanLoss*flatDistribution->fire();
00177           x = (loss - meanLoss)/siga;
00178         } while (1.0 - 0.5*x*x < flatDistribution->fire());
00179       } else {
00180         do {
00181           loss = gaussQDistribution->fire(meanLoss,siga);
00182         } while (loss < 0. || loss > twomeanLoss);
00183       }
00184       return loss;
00185     }
00186   }
00187 
00188   // Glandz regime : initialisation
00189   //
00190 //   if (material != lastMaterial) {
00191 //     f1Fluct      = material->GetIonisation()->GetF1fluct();
00192 //     f2Fluct      = material->GetIonisation()->GetF2fluct();
00193 //     e1Fluct      = material->GetIonisation()->GetEnergy1fluct();
00194 //     e2Fluct      = material->GetIonisation()->GetEnergy2fluct();
00195 //     e1LogFluct   = material->GetIonisation()->GetLogEnergy1fluct();
00196 //     e2LogFluct   = material->GetIonisation()->GetLogEnergy2fluct();
00197 //     rateFluct    = material->GetIonisation()->GetRateionexcfluct();
00198 //     ipotFluct    = material->GetIonisation()->GetMeanExcitationEnergy();
00199 //     ipotLogFluct = material->GetIonisation()->GetLogMeanExcEnergy();
00200 //     lastMaterial = material;
00201 //   }
00202 
00203   double a1 = 0. , a2 = 0., a3 = 0. ;
00204   double p1,p2,p3;
00205   double rate = rateFluct ;
00206 
00207   double w1 = tmax/ipotFluct;
00208   double w2 = vdt::fast_log(2.*electron_mass_c2*beta2*gam2)-beta2;
00209 
00210   if(w2 > ipotLogFluct)
00211   {
00212     double C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct);
00213     a1 = C*f1Fluct*(w2-e1LogFluct)/e1Fluct;
00214     a2 = C*f2Fluct*(w2-e2LogFluct)/e2Fluct;
00215     if(a2 < 0.)
00216     {
00217       a1 = 0. ;
00218       a2 = 0. ;
00219       rate = 1. ;  
00220     }
00221   }
00222   else
00223   {
00224     rate = 1. ;
00225   }
00226 
00227   // added
00228   if(tmax > ipotFluct) {
00229     a3 = rate*meanLoss*(tmax-ipotFluct)/(ipotFluct*tmax*vdt::fast_log(w1));
00230   }
00231   double suma = a1+a2+a3;
00232   
00233   // Glandz regime
00234   //
00235   if (suma > sumalim)
00236   {
00237     p1 = 0., p2 = 0 ;
00238     if((a1+a2) > 0.)
00239     {
00240       // excitation type 1
00241       if (a1>alim) {
00242         siga=sqrt(a1) ;
00243         p1 = max(0.,gaussQDistribution->fire(a1,siga)+0.5);
00244       } else {
00245         p1 = double(poissonQDistribution->fire(a1));
00246       }
00247     
00248       // excitation type 2
00249       if (a2>alim) {
00250         siga=sqrt(a2) ;
00251         p2 = max(0.,gaussQDistribution->fire(a2,siga)+0.5);
00252       } else {
00253         p2 = double(poissonQDistribution->fire(a2));
00254       }
00255     
00256       loss = p1*e1Fluct+p2*e2Fluct;
00257  
00258       // smearing to avoid unphysical peaks
00259       if (p2 > 0.)
00260         loss += (1.-2.*flatDistribution->fire())*e2Fluct;
00261       else if (loss>0.)
00262         loss += (1.-2.*flatDistribution->fire())*e1Fluct;   
00263       if (loss < 0.) loss = 0.0;
00264     }
00265 
00266     // ionisation
00267     if (a3 > 0.) {
00268       if (a3>alim) {
00269         siga=sqrt(a3) ;
00270         p3 = max(0.,gaussQDistribution->fire(a3,siga)+0.5);
00271       } else {
00272         p3 = double(poissonQDistribution->fire(a3));
00273       }
00274       double lossc = 0.;
00275       if (p3 > 0) {
00276         double na = 0.; 
00277         double alfa = 1.;
00278         if (p3 > nmaxCont2) {
00279           double rfac   = p3/(nmaxCont2+p3);
00280           double namean = p3*rfac;
00281           double sa     = nmaxCont1*rfac;
00282           na              = gaussQDistribution->fire(namean,sa);
00283           if (na > 0.) {
00284             alfa   = w1*(nmaxCont2+p3)/(w1*nmaxCont2+p3);
00285             double alfa1  = alfa*vdt::fast_log(alfa)/(alfa-1.);
00286             double ea     = na*ipotFluct*alfa1;
00287             double sea    = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
00288             lossc += gaussQDistribution->fire(ea,sea);
00289           }
00290         }
00291 
00292         if (p3 > na) {
00293           w2 = alfa*ipotFluct;
00294           double w  = (tmax-w2)/tmax;
00295           int    nb = int(p3-na);
00296           for (int k=0; k<nb; k++) lossc += w2/(1.-w*flatDistribution->fire());
00297         }
00298       }        
00299       loss += lossc;  
00300     }
00301     return loss;
00302   }
00303   
00304   // suma < sumalim;  very small energy loss;  
00305   //
00306   //double e0 = material->GetIonisation()->GetEnergy0fluct();
00307 
00308   a3 = meanLoss*(tmax-e0)/(tmax*e0*vdt::fast_log(tmax/e0));
00309   if (a3 > alim)
00310   {
00311     siga=sqrt(a3);
00312     p3 = max(0.,gaussQDistribution->fire(a3,siga)+0.5);
00313   } else {
00314     p3 = double(poissonQDistribution->fire(a3));
00315   }
00316   if (p3 > 0.) {
00317     double w = (tmax-e0)/tmax;
00318     double corrfac = 1.;
00319     if (p3 > nmaxCont2) {
00320       corrfac = p3/nmaxCont2;
00321       p3 = nmaxCont2;
00322     } 
00323     int ip3 = (int)p3;
00324     for (int i=0; i<ip3; i++) loss += 1./(1.-w*flatDistribution->fire());
00325     loss *= e0*corrfac;
00326     // smearing for losses near to e0
00327     if(p3 <= 2.)
00328       loss += e0*(1.-2.*flatDistribution->fire()) ;
00329    }
00330     
00331    return loss;
00332 }
00333 
00334 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00335 // G4double SiG4UniversalFluctuation::Dispersion(
00336 //                           const G4Material* material,
00337 //                           const G4DynamicParticle* dp,
00338 //                              G4double& tmax,
00339 //                              G4double& length)
00340 // {
00341 //   if(!particle) InitialiseMe(dp->GetDefinition());
00342 
00343 //   electronDensity = material->GetElectronDensity();
00344 
00345 //   G4double gam   = (dp->GetKineticEnergy())/particleMass + 1.0;
00346 //   G4double beta2 = 1.0 - 1.0/(gam*gam);
00347 
00348 //   G4double siga  = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
00349 //                  * electronDensity * chargeSquare;
00350 
00351 //   return siga;
00352 // }
00353 
00354 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......