File indexing completed on 2026-07-13 08:21:03
0001
0002 #include "G4HepEmElectronEnergyLossFluctuation.hh"
0003
0004
0005 #include "G4HepEmRandomEngine.hh"
0006
0007 #include "G4HepEmConstants.hh"
0008 #include "G4HepEmMath.hh"
0009
0010
0011 double G4HepEmElectronEnergyLossFluctuation::SampleEnergyLossFLuctuation(double , double tcut, double ,
0012 double excEner, double , double meanELoss, G4HepEmRandomEngine* rnge) {
0013 const double scaling = G4HepEmMin(1. + 5.E-4/tcut, 1.5);
0014 const double meanLoss = meanELoss/scaling;
0015
0016 const double kFluctParRate = 0.56;
0017 const double kFluctParE0 = 1.E-5;
0018 const double kFluctParNMaxCont = 8.;
0019
0020 const double w1 = tcut/kFluctParE0;
0021 double a3 = meanLoss*(tcut - kFluctParE0)/(kFluctParE0*tcut*G4HepEmLog(w1));
0022 double a1 = 0.;
0023 double e1 = excEner;
0024 double eloss = 0.0;
0025
0026 if (tcut > excEner) {
0027 const double a1Tmp = meanLoss*(1. - kFluctParRate)/excEner;
0028
0029 const double kFluctParA0 = 42.;
0030 const double kFluctParFw = 4.;
0031 const double dum0 = a1Tmp < kFluctParA0
0032 ? .1 + (kFluctParFw - .1)*std::sqrt(a1Tmp/kFluctParA0)
0033 : kFluctParFw;
0034
0035
0036
0037
0038
0039
0040 a1 = a1Tmp/dum0;
0041 e1 *= dum0;
0042 a3 *= kFluctParRate;
0043
0044
0045 if (a1 > kFluctParNMaxCont) {
0046
0047 const double emean = a1*e1;
0048 const double sig2e = emean*e1;
0049 eloss = SampleGaussianLoss(emean, sig2e, rnge);
0050 } else {
0051
0052 const int p = rnge->Poisson(a1);
0053 eloss = p > 0 ? ((p + 1) - 2.*rnge->flat())*e1 : 0.;
0054 }
0055 }
0056
0057
0058 if (a3 > 0.) {
0059 double p3 = a3;
0060 double alfa = 1.;
0061 if (a3 > kFluctParNMaxCont) {
0062 alfa = w1*(kFluctParNMaxCont + a3)/(w1*kFluctParNMaxCont + a3);
0063 const double alfa1 = alfa*G4HepEmLog(alfa)/(alfa - 1.);
0064 const double namean = a3*w1*(alfa - 1.)/((w1 - 1.)*alfa);
0065 const double emean = namean*kFluctParE0*alfa1;
0066 const double sig2e = kFluctParE0*kFluctParE0*namean*(alfa - alfa1*alfa1);
0067 eloss += SampleGaussianLoss(emean, sig2e, rnge);
0068 p3 = a3 - namean;
0069 }
0070
0071 const double w3 = alfa*kFluctParE0;
0072 if (tcut > w3) {
0073 const double w = (tcut - w3)/tcut;
0074 const int nnb = rnge->Poisson(p3);
0075 if (nnb > 0) {
0076 const int kBlockSize = 8;
0077 const int nBlocks = nnb/kBlockSize;
0078
0079 double rndm[kBlockSize];
0080 for (int ib=0; ib<nBlocks; ++ib) {
0081 rnge->flatArray(kBlockSize, rndm);
0082 for (int i=0; i<kBlockSize; ++i) {
0083 eloss += w3/(1.-w*rndm[i]);
0084 }
0085 }
0086 const int nTail = nnb - nBlocks*kBlockSize;
0087 rnge->flatArray(nTail, rndm);
0088 for (int i=0; i<nTail; ++i) {
0089 eloss += w3/(1.-w*rndm[i]);
0090 }
0091 }
0092 }
0093 }
0094
0095
0096 return eloss*scaling;
0097 }
0098
0099
0100 double G4HepEmElectronEnergyLossFluctuation::SampleGaussianLoss(double meane, double sig2e, G4HepEmRandomEngine* rnge) {
0101 const double twom = 2.*meane;
0102 if (meane*meane < 0.0625*sig2e) {
0103 return twom*rnge->flat();
0104 }
0105 const double sig = std::sqrt(sig2e);
0106 double eloss;
0107 do {
0108 eloss = rnge->Gauss(meane, sig);
0109 } while (eloss < 0. || eloss > twom);
0110 return eloss;
0111 }