CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_5_3_14/src/SimRomanPot/SimFP420/src/LandauFP420.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 // -------------------------------------------------------------------
00024 //
00025 // GEANT4 Class file
00026 //
00027 //
00028 // File name:     G4UniversalFluctuation
00029 //
00030 // Author:        Vladimir Ivanchenko 
00031 // 
00032 // Creation date: 03.01.2002
00033 //
00034 // Modifications: 
00035 //
00036 // 28-12-02 add method Dispersion (V.Ivanchenko)
00037 // 07-02-03 change signature (V.Ivanchenko)
00038 // 13-02-03 Add name (V.Ivanchenko)
00039 // Modified for standalone use in ORCA. d.k. 6/04
00040 //
00041 // -------------------------------------------------------------------
00042  
00043 #include "SimRomanPot/SimFP420/interface/LandauFP420.h"
00044 #include "CLHEP/Units/GlobalSystemOfUnits.h"
00045 #include "CLHEP/Units/GlobalPhysicalConstants.h"
00046 #include "CLHEP/Random/RandGaussQ.h"
00047 #include "CLHEP/Random/RandPoisson.h"
00048 #include "CLHEP/Random/RandFlat.h"
00049 
00050 #include <stdio.h>
00051 #include <gsl/gsl_fit.h>
00052 #include <cmath>
00053 #include<vector>
00054 
00055 //#include "Randomize.hh"
00056 //#include "G4Poisson.hh"
00057 //#include "G4Step.hh"
00058 //#include "G4Material.hh"
00059 //#include "G4DynamicParticle.hh"
00060 //#include "G4ParticleDefinition.hh"
00061 using namespace std;
00062 
00063 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00064 // The constructor setups various constants pluc eloss parameters
00065 // for silicon.   
00066 LandauFP420::LandauFP420()
00067  :minNumberInteractionsBohr(10.0),
00068   theBohrBeta2(50.0*keV/proton_mass_c2),
00069   minLoss(0.000001*eV),
00070   problim(0.01),
00071   alim(10.),
00072   nmaxCont1(4),
00073   nmaxCont2(16)
00074 {
00075   sumalim = -log(problim);
00076 
00077   chargeSquare   = 1.;  //Assume all particles have charge 1
00078   // Taken from Geant4 printout, HARDWIRED for Silicon.
00079   ipotFluct = 0.0001736; //material->GetIonisation()->GetMeanExcitationEnergy();
00080   electronDensity = 6.797E+20; // material->GetElectronDensity();
00081   f1Fluct      = 0.8571; // material->GetIonisation()->GetF1fluct();
00082   f2Fluct      = 0.1429; //material->GetIonisation()->GetF2fluct();
00083   e1Fluct      = 0.000116;// material->GetIonisation()->GetEnergy1fluct();
00084   e2Fluct      = 0.00196; //material->GetIonisation()->GetEnergy2fluct();
00085   e1LogFluct   = -9.063;  //material->GetIonisation()->GetLogEnergy1fluct();
00086   e2LogFluct   = -6.235;  //material->GetIonisation()->GetLogEnergy2fluct();
00087   rateFluct    = 0.4;     //material->GetIonisation()->GetRateionexcfluct();
00088   ipotLogFluct = -8.659;  //material->GetIonisation()->GetLogMeanExcEnergy();
00089   e0 = 1.E-5;             //material->GetIonisation()->GetEnergy0fluct();
00090 
00091 }
00092 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00093 LandauFP420::~LandauFP420()
00094 {}
00095 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00096 // The main dedx fluctuation routine.
00097 // Arguments: momentum in MeV/c, mass in MeV, delta ray cut (tmax) in
00098 // MeV, silicon thickness in mm, mean eloss in MeV. 
00099 double LandauFP420::SampleFluctuations(const double momentum,
00100                                                          const double mass,
00101                                                          double& tmax,
00102                                                          const double length,
00103                                                          const double meanLoss)
00104 {
00105 //  calculate actual loss from the mean loss
00106 //  The model used to get the fluctuation is essentially the same
00107 // as in Glandz in Geant3.
00108   
00109   // shortcut for very very small loss 
00110   if(meanLoss < minLoss) return meanLoss;
00111 
00112   //if(dp->GetDefinition() != particle) {
00113   particleMass   = mass; // dp->GetMass();
00114   //G4double q     = dp->GetCharge(); 
00115   //chargeSquare   = q*q;
00116   //}
00117 
00118   //double gam   = (dp->GetKineticEnergy())/particleMass + 1.0;
00119   //double gam2  = gam*gam; 
00120   double gam2   = (momentum*momentum)/(particleMass*particleMass) + 1.0;
00121   double beta2 = 1.0 - 1.0/gam2;
00122  
00123   // Validity range for delta electron cross section
00124   double loss, siga;
00125   // Gaussian fluctuation 
00126   if(meanLoss >= minNumberInteractionsBohr*tmax || 
00127      tmax <= ipotFluct*minNumberInteractionsBohr)
00128   {
00129     siga  = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length 
00130                               * electronDensity * chargeSquare ;
00131     siga = sqrt(siga);
00132     do {
00133      //loss = G4RandGauss::shoot(meanLoss,siga);
00134      loss = CLHEP::RandGaussQ::shoot(meanLoss,siga);
00135     } while (loss < 0. || loss > 2.*meanLoss);
00136 
00137     return loss;
00138   }
00139 
00140   // Non Gaussian fluctuation 
00141   double suma,w1,w2,C,lossc,w;
00142   double a1,a2,a3;
00143   int p1,p2,p3;
00144   int nb;
00145   double corrfac, na,alfa,rfac,namean,sa,alfa1,ea,sea;
00146   double dp3;
00147 
00148   w1 = tmax/ipotFluct;
00149   w2 = log(2.*electron_mass_c2*(gam2 - 1.0));
00150 
00151   C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
00152 
00153   a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
00154   a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
00155   a3 = rateFluct*meanLoss*(tmax-ipotFluct)/(ipotFluct*tmax*log(w1));
00156   if(a1 < 0.) a1 = 0.;
00157   if(a2 < 0.) a2 = 0.;
00158   if(a3 < 0.) a3 = 0.;
00159 
00160   suma = a1+a2+a3;
00161 
00162   loss = 0. ;
00163 
00164   if(suma < sumalim)             // very small Step
00165     {
00166       //e0 = material->GetIonisation()->GetEnergy0fluct();//Hardwired in const
00167       if(tmax == ipotFluct)
00168       {
00169         a3 = meanLoss/e0;
00170 
00171         if(a3>alim)
00172         {
00173           siga=sqrt(a3) ;
00174           //p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
00175           p3 = std::max(0,int(CLHEP::RandGaussQ::shoot(a3,siga)+0.5));
00176         }
00177         else
00178           p3 = CLHEP::RandPoisson::shoot(a3);
00179         //p3 = G4Poisson(a3);
00180 
00181         loss = p3*e0 ;
00182 
00183         if(p3 > 0)
00184           //loss += (1.-2.*G4UniformRand())*e0 ;
00185           loss += (1.-2.*CLHEP::RandFlat::shoot())*e0 ;
00186 
00187       }
00188       else
00189       {
00190         tmax = tmax-ipotFluct+e0 ;
00191         a3 = meanLoss*(tmax-e0)/(tmax*e0*log(tmax/e0));
00192 
00193         if(a3>alim)
00194         {
00195           siga=sqrt(a3) ;
00196           //p3 = G4std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
00197           p3 = std::max(0,int(CLHEP::RandGaussQ::shoot(a3,siga)+0.5));
00198         }
00199         else
00200           p3 = CLHEP::RandPoisson::shoot(a3);
00201         //p3 = G4Poisson(a3);
00202 
00203         if(p3 > 0)
00204         {
00205           w = (tmax-e0)/tmax ;
00206           if(p3 > nmaxCont2)
00207           {
00208             dp3 = float(p3) ;
00209             corrfac = dp3/float(nmaxCont2) ;
00210             p3 = nmaxCont2 ;
00211           }
00212           else
00213             corrfac = 1. ;
00214 
00215           //for(int i=0; i<p3; i++) loss += 1./(1.-w*G4UniformRand()) ;
00216           for(int i=0; i<p3; i++) loss += 1./(1.-w*CLHEP::RandFlat::shoot()) ;
00217           loss *= e0*corrfac ;  
00218         }        
00219       }
00220     }
00221     
00222   else                              // not so small Step
00223     {
00224       // excitation type 1
00225       if(a1>alim)
00226       {
00227         siga=sqrt(a1) ;
00228         //p1 = std::max(0,int(G4RandGauss::shoot(a1,siga)+0.5));
00229         p1 = std::max(0,int(CLHEP::RandGaussQ::shoot(a1,siga)+0.5));
00230       }
00231       else
00232        p1 = CLHEP::RandPoisson::shoot(a1);
00233       //p1 = G4Poisson(a1);
00234 
00235       // excitation type 2
00236       if(a2>alim)
00237       {
00238         siga=sqrt(a2) ;
00239         //p2 = std::max(0,int(G4RandGauss::shoot(a2,siga)+0.5));
00240         p2 = std::max(0,int(CLHEP::RandGaussQ::shoot(a2,siga)+0.5));
00241       }
00242       else
00243         p2 = CLHEP::RandPoisson::shoot(a2);
00244       //p2 = G4Poisson(a2);
00245 
00246       loss = p1*e1Fluct+p2*e2Fluct;
00247  
00248       // smearing to avoid unphysical peaks
00249       if(p2 > 0)
00250         //loss += (1.-2.*G4UniformRand())*e2Fluct;   
00251         loss += (1.-2.*CLHEP::RandFlat::shoot())*e2Fluct;   
00252       else if (loss>0.)
00253         loss += (1.-2.*CLHEP::RandFlat::shoot())*e1Fluct;   
00254 
00255       // ionisation .......................................
00256      if(a3 > 0.)
00257      {
00258       if(a3>alim)
00259       {
00260         siga=sqrt(a3) ;
00261         p3 = std::max(0,int(CLHEP::RandGaussQ::shoot(a3,siga)+0.5));
00262       }
00263       else
00264         p3 = CLHEP::RandPoisson::shoot(a3);
00265 
00266       lossc = 0.;
00267       if(p3 > 0)
00268       {
00269         na = 0.; 
00270         alfa = 1.;
00271         if (p3 > nmaxCont2)
00272         {
00273           dp3        = float(p3);
00274           rfac       = dp3/(float(nmaxCont2)+dp3);
00275           namean     = float(p3)*rfac;
00276           sa         = float(nmaxCont1)*rfac;
00277           na         = CLHEP::RandGaussQ::shoot(namean,sa);
00278           if (na > 0.)
00279           {
00280             alfa   = w1*float(nmaxCont2+p3)/
00281                     (w1*float(nmaxCont2)+float(p3));
00282             alfa1  = alfa*log(alfa)/(alfa-1.);
00283             ea     = na*ipotFluct*alfa1;
00284             sea    = ipotFluct*sqrt(na*(alfa-alfa1*alfa1));
00285             lossc += CLHEP::RandGaussQ::shoot(ea,sea);
00286           }
00287         }
00288 
00289         nb = int(float(p3)-na);
00290         if (nb > 0)
00291         {
00292           w2 = alfa*ipotFluct;
00293           w  = (tmax-w2)/tmax;      
00294           for (int k=0; k<nb; k++) lossc += w2/(1.-w*CLHEP::RandFlat::shoot());
00295         }
00296       }        
00297       loss += lossc;  
00298      }
00299     } 
00300 
00301   return loss;
00302 }
00303 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....