Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
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
00065
00066
00067
00068
00069
00070
00071
00072
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
00091
00092
00093 chargeSquare = 1.;
00094
00095 ipotFluct = 0.0001736;
00096 electronDensity = 6.797E+20;
00097 f1Fluct = 0.8571;
00098 f2Fluct = 0.1429;
00099 e1Fluct = 0.000116;
00100 e2Fluct = 0.00196;
00101 e1LogFluct = -9.063;
00102 e2LogFluct = -6.235;
00103 rateFluct = 0.4;
00104 ipotLogFluct = -8.659;
00105 e0 = 1.E-5;
00106
00107 gaussQDistribution = new CLHEP::RandGaussQ(rndEngine);
00108 poissonQDistribution = new CLHEP::RandPoissonQ(rndEngine);
00109 flatDistribution = new CLHEP::RandFlat(rndEngine);
00110
00111
00112 }
00113
00114
00115
00116
00117
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
00135
00136
00137
00138
00139
00140
00141 if (meanLoss < minLoss) return meanLoss;
00142
00143
00144
00145
00146
00147
00148
00149 particleMass = mass;
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
00157
00158
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
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
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
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
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
00234
00235 if (suma > sumalim)
00236 {
00237 p1 = 0., p2 = 0 ;
00238 if((a1+a2) > 0.)
00239 {
00240
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
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
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
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
00305
00306
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
00327 if(p3 <= 2.)
00328 loss += e0*(1.-2.*flatDistribution->fire()) ;
00329 }
00330
00331 return loss;
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354