G4UniversalFluctuation.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 // $Id$
00027 //
00028 // -------------------------------------------------------------------
00029 //
00030 // GEANT4 Class file
00031 //
00032 //
00033 // File name:     G4UniversalFluctuation
00034 //
00035 // Author:        Laszlo Urban
00036 // 
00037 // Creation date: 03.01.2002
00038 //
00039 // Modifications: 
00040 //
00041 // 28-12-02 add method Dispersion (V.Ivanchenko)
00042 // 07-02-03 change signature (V.Ivanchenko)
00043 // 13-02-03 Add name (V.Ivanchenko)
00044 // 16-10-03 Changed interface to Initialisation (V.Ivanchenko)
00045 // 07-11-03 Fix problem of rounding of double in G4UniversalFluctuations
00046 // 06-02-04 Add control on big sigma > 2*meanLoss (V.Ivanchenko)
00047 // 26-04-04 Comment out the case of very small step (V.Ivanchenko)
00048 // 07-02-05 define problim = 5.e-3 (mma)
00049 // 03-05-05 conditions of Gaussian fluctuation changed (bugfix)
00050 //          + smearing for very small loss (L.Urban)
00051 // 03-10-05 energy dependent rate -> cut dependence of the
00052 //          distribution is much weaker (L.Urban)
00053 // 17-10-05 correction for very small loss (L.Urban)
00054 // 20-03-07 'GLANDZ' part rewritten completely, no 'very small loss'
00055 //          regime any more (L.Urban)
00056 // 03-04-07 correction to get better width of eloss distr.(L.Urban)
00057 // 13-07-07 add protection for very small step or low-density material (VI)
00058 // 19-03-09 new width correction (does not depend on previous steps) (L.Urban)
00059 // 20-03-09 modification in the width correction (L.Urban)
00060 // 14-06-10 fixed tail distribution - do not use uniform function (L.Urban)
00061 // 08-08-10 width correction algorithm has bee modified -->
00062 //          better results for thin targets (L.Urban)
00063 // 06-02-11 correction for very small losses (L.Urban)
00064 //
00065 
00066 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00067 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00068 
00069 #include "G4UniversalFluctuation.hh"
00070 #include "G4PhysicalConstants.hh"
00071 #include "G4SystemOfUnits.hh"
00072 #include "Randomize.hh"
00073 #include "G4Poisson.hh"
00074 #include "G4Step.hh"
00075 #include "G4Material.hh"
00076 #include "G4DynamicParticle.hh"
00077 #include "G4ParticleDefinition.hh"
00078 
00079 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00080 
00081 using namespace std;
00082 
00083 G4UniversalFluctuation::G4UniversalFluctuation(const G4String& nam)
00084  :G4VEmFluctuationModel(nam),
00085   particle(0),
00086   minNumberInteractionsBohr(10.0),
00087   theBohrBeta2(50.0*keV/proton_mass_c2),
00088   minLoss(10.*eV),
00089   nmaxCont(16.),
00090   rate(0.55),
00091   fw(4.)
00092 {
00093   lastMaterial = 0;
00094 
00095   particleMass = chargeSquare = ipotFluct = electronDensity = f1Fluct = f2Fluct 
00096     = e1Fluct = e2Fluct = e1LogFluct = e2LogFluct = ipotLogFluct = e0 = esmall 
00097     = e1 = e2 = 0;
00098 
00099 }
00100 
00101 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00102 
00103 G4UniversalFluctuation::~G4UniversalFluctuation()
00104 {}
00105 
00106 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00107 
00108 void G4UniversalFluctuation::InitialiseMe(const G4ParticleDefinition* part)
00109 {
00110   particle       = part;
00111   particleMass   = part->GetPDGMass();
00112   G4double q     = part->GetPDGCharge()/eplus;
00113   chargeSquare   = q*q;
00114 }
00115 
00116 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00117 
00118 G4double G4UniversalFluctuation::SampleFluctuations(const G4Material* material,
00119                                                     const G4DynamicParticle* dp,
00120                                                     G4double& tmax,
00121                                                     G4double& length,
00122                                                     G4double& averageLoss)
00123 {
00124   // Calculate actual loss from the mean loss.
00125   // The model used to get the fluctuations is essentially the same
00126   // as in Glandz in Geant3 (Cern program library W5013, phys332).
00127   // L. Urban et al. NIM A362, p.416 (1995) and Geant4 Physics Reference Manual
00128 
00129   // shortcut for very small loss or from a step nearly equal to the range
00130   // (out of validity of the model)
00131   //
00132   G4double meanLoss = averageLoss;
00133   G4double tkin  = dp->GetKineticEnergy();
00134   //G4cout<< "Emean= "<< meanLoss<< " tmax= "<< tmax<< " L= "<<length<<G4endl;
00135   if (meanLoss < minLoss) { return meanLoss; }
00136 
00137   if(!particle) { InitialiseMe(dp->GetDefinition()); }
00138   
00139   G4double tau   = tkin/particleMass;
00140   G4double gam   = tau + 1.0;
00141   G4double gam2  = gam*gam;
00142   G4double beta2 = tau*(tau + 2.0)/gam2;
00143 
00144   G4double loss(0.), siga(0.);
00145   
00146   // Gaussian regime
00147   // for heavy particles only and conditions
00148   // for Gauusian fluct. has been changed 
00149   //
00150   if ((particleMass > electron_mass_c2) &&
00151       (meanLoss >= minNumberInteractionsBohr*tmax))
00152   {
00153     G4double massrate = electron_mass_c2/particleMass ;
00154     G4double tmaxkine = 2.*electron_mass_c2*beta2*gam2/
00155                         (1.+massrate*(2.*gam+massrate)) ;
00156     if (tmaxkine <= 2.*tmax)   
00157     {
00158       electronDensity = material->GetElectronDensity();
00159       siga = sqrt((1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
00160                   * electronDensity * chargeSquare);
00161 
00162      
00163       G4double sn = meanLoss/siga;
00164   
00165       // thick target case 
00166       if (sn >= 2.0) {
00167 
00168         G4double twomeanLoss = meanLoss + meanLoss;
00169         do {
00170           loss = G4RandGauss::shoot(meanLoss,siga);
00171         } while (0.0 > loss || twomeanLoss < loss);
00172 
00173         // Gamma distribution
00174       } else {
00175 
00176         G4double neff = sn*sn;
00177         loss = meanLoss*CLHEP::RandGamma::shoot(neff,1.0)/neff;
00178       }
00179       //G4cout << "Gauss: " << loss << G4endl;
00180       return loss;
00181     }
00182   }
00183 
00184   // Glandz regime : initialisation
00185   //
00186   if (material != lastMaterial) {
00187     f1Fluct      = material->GetIonisation()->GetF1fluct();
00188     f2Fluct      = material->GetIonisation()->GetF2fluct();
00189     e1Fluct      = material->GetIonisation()->GetEnergy1fluct();
00190     e2Fluct      = material->GetIonisation()->GetEnergy2fluct();
00191     e1LogFluct   = material->GetIonisation()->GetLogEnergy1fluct();
00192     e2LogFluct   = material->GetIonisation()->GetLogEnergy2fluct();
00193     ipotFluct    = material->GetIonisation()->GetMeanExcitationEnergy();
00194     ipotLogFluct = material->GetIonisation()->GetLogMeanExcEnergy();
00195     e0 = material->GetIonisation()->GetEnergy0fluct();
00196     esmall = 0.5*sqrt(e0*ipotFluct);  
00197     lastMaterial = material;   
00198   }
00199 
00200   // very small step or low-density material
00201   if(tmax <= e0) { return meanLoss; }
00202 
00203   G4double losstot = 0.;
00204   G4int    nstep = 1;
00205   if(meanLoss < 25.*ipotFluct)
00206     {
00207       if(G4UniformRand() < 0.04*meanLoss/ipotFluct)
00208         { nstep = 1; }
00209       else
00210         { 
00211           nstep = 2;
00212           meanLoss *= 0.5; 
00213         }
00214     }
00215 
00216   for (G4int istep=0; istep < nstep; ++istep) {
00217     
00218     loss = 0.;
00219 
00220     G4double a1 = 0. , a2 = 0., a3 = 0. ;
00221 
00222     if(tmax > ipotFluct) {
00223       G4double w2 = log(2.*electron_mass_c2*beta2*gam2)-beta2;
00224 
00225       if(w2 > ipotLogFluct)  {
00226         G4double C = meanLoss*(1.-rate)/(w2-ipotLogFluct);
00227         a1 = C*f1Fluct*(w2-e1LogFluct)/e1Fluct;
00228         if(w2 > e2LogFluct) {
00229           a2 = C*f2Fluct*(w2-e2LogFluct)/e2Fluct;
00230         }
00231         if(a1 < nmaxCont) { 
00232           //small energy loss
00233           G4double sa1 = sqrt(a1);
00234           if(G4UniformRand() < exp(-sa1))
00235             {
00236               e1 = esmall;
00237               a1 = meanLoss*(1.-rate)/e1;
00238               a2 = 0.;
00239               e2 = e2Fluct;
00240             } 
00241           else
00242             {
00243               a1 = sa1 ;    
00244               e1 = sa1*e1Fluct;
00245               e2 = e2Fluct;
00246             }
00247 
00248         } else {
00249             //not small energy loss
00250             //correction to get better fwhm value
00251             a1 /= fw;
00252             e1 = fw*e1Fluct;
00253             e2 = e2Fluct;
00254         }
00255       }   
00256     }
00257 
00258     G4double w1 = tmax/e0;
00259     if(tmax > e0) {
00260       a3 = rate*meanLoss*(tmax-e0)/(e0*tmax*log(w1));
00261     }
00262     //'nearly' Gaussian fluctuation if a1>nmaxCont&&a2>nmaxCont&&a3>nmaxCont  
00263     G4double emean = 0.;
00264     G4double sig2e = 0., sige = 0.;
00265     G4double p1 = 0., p2 = 0., p3 = 0.;
00266  
00267     // excitation of type 1
00268     if(a1 > nmaxCont)
00269       {
00270         emean += a1*e1;
00271         sig2e += a1*e1*e1;
00272       }
00273     else if(a1 > 0.)
00274       {
00275         p1 = G4double(G4Poisson(a1));
00276         loss += p1*e1;
00277         if(p1 > 0.) {
00278           loss += (1.-2.*G4UniformRand())*e1;
00279         }
00280       }
00281 
00282 
00283     // excitation of type 2
00284     if(a2 > nmaxCont)
00285       {
00286         emean += a2*e2;
00287         sig2e += a2*e2*e2;
00288       }
00289     else if(a2 > 0.)
00290       {
00291         p2 = G4double(G4Poisson(a2));
00292         loss += p2*e2;
00293         if(p2 > 0.) 
00294           loss += (1.-2.*G4UniformRand())*e2;
00295       }
00296 
00297     if(emean > 0.)
00298       {
00299         sige   = sqrt(sig2e);
00300         loss += max(0.,G4RandGauss::shoot(emean,sige));
00301       }
00302 
00303     // ionisation 
00304     G4double lossc = 0.;
00305     if(a3 > 0.) {
00306       emean = 0.;
00307       sig2e = 0.;
00308       sige = 0.;
00309       p3 = a3;
00310       G4double alfa = 1.;
00311       if(a3 > nmaxCont)
00312         {
00313           alfa            = w1*(nmaxCont+a3)/(w1*nmaxCont+a3);
00314           G4double alfa1  = alfa*log(alfa)/(alfa-1.);
00315           G4double namean = a3*w1*(alfa-1.)/((w1-1.)*alfa);
00316           emean          += namean*e0*alfa1;
00317           sig2e          += e0*e0*namean*(alfa-alfa1*alfa1);
00318           p3              = a3-namean;
00319         }
00320 
00321       G4double w2 = alfa*e0;
00322       G4double w  = (tmax-w2)/tmax;
00323       G4int nb = G4Poisson(p3);
00324       if(nb > 0) {
00325         for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
00326       }
00327     }
00328 
00329     if(emean > 0.)
00330       {
00331         sige   = sqrt(sig2e);
00332         lossc += max(0.,G4RandGauss::shoot(emean,sige));
00333       }
00334 
00335     loss += lossc;
00336 
00337     losstot += loss;
00338   }
00339   //G4cout << "Vavilov: " << losstot << "  Nstep= " << nstep << G4endl;
00340               
00341   return losstot;
00342 
00343 }
00344 
00345 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
00346 
00347 
00348 G4double G4UniversalFluctuation::Dispersion(
00349                           const G4Material* material,
00350                           const G4DynamicParticle* dp,
00351                                 G4double& tmax,
00352                                 G4double& length)
00353 {
00354   if(!particle) { InitialiseMe(dp->GetDefinition()); }
00355 
00356   electronDensity = material->GetElectronDensity();
00357 
00358   G4double gam   = (dp->GetKineticEnergy())/particleMass + 1.0;
00359   G4double beta2 = 1.0 - 1.0/(gam*gam);
00360 
00361   G4double siga  = (1.0/beta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
00362                  * electronDensity * chargeSquare;
00363 
00364   return siga;
00365 }
00366 
00367 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00368 
00369 void 
00370 G4UniversalFluctuation::SetParticleAndCharge(const G4ParticleDefinition* part,
00371                                              G4double q2)
00372 {
00373   if(part != particle) {
00374     particle       = part;
00375     particleMass   = part->GetPDGMass();
00376   }
00377   chargeSquare = q2;
00378 }
00379 
00380 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......

Generated on Mon May 27 17:50:07 2013 for Geant4 by  doxygen 1.4.7