File indexing completed on 2024-04-06 12:30:35
0001
0002
0003
0004
0005 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0006
0007 #include "SimGeneral/GFlash/interface/Gflash3Vector.h"
0008 #include "SimGeneral/GFlash/interface/GflashEMShowerProfile.h"
0009 #include "SimGeneral/GFlash/interface/GflashHistogram.h"
0010 #include "SimGeneral/GFlash/interface/GflashHit.h"
0011 #include "SimGeneral/GFlash/interface/GflashShowino.h"
0012 #include "SimGeneral/GFlash/interface/GflashTrajectory.h"
0013 #include "SimGeneral/GFlash/interface/GflashTrajectoryPoint.h"
0014
0015 #include <CLHEP/GenericFunctions/IncompleteGamma.hh>
0016 #include <CLHEP/Random/RandGaussQ.h>
0017 #include <CLHEP/Random/Randomize.h>
0018 #include <CLHEP/Units/PhysicalConstants.h>
0019
0020 GflashEMShowerProfile::GflashEMShowerProfile(const edm::ParameterSet &parSet) : theParSet(parSet) {
0021 theBField = parSet.getParameter<double>("bField");
0022 theEnergyScaleEB = parSet.getParameter<double>("energyScaleEB");
0023 theEnergyScaleEE = parSet.getParameter<double>("energyScaleEE");
0024
0025 jCalorimeter = Gflash::kNULL;
0026
0027 theShowino = new GflashShowino();
0028
0029 theHisto = GflashHistogram::instance();
0030 }
0031
0032 GflashEMShowerProfile::~GflashEMShowerProfile() {
0033 if (theShowino)
0034 delete theShowino;
0035 }
0036
0037 void GflashEMShowerProfile::initialize(
0038 int showerType, double energy, double globalTime, double charge, Gflash3Vector &position, Gflash3Vector &momentum) {
0039 theShowino->initialize(showerType, energy, globalTime, charge, position, momentum, theBField);
0040 }
0041
0042 void GflashEMShowerProfile::parameterization() {
0043
0044
0045
0046
0047
0048 const double energyCutoff = 0.01;
0049 const int maxNumberOfSpots = 100000;
0050
0051 double incomingEnergy = theShowino->getEnergy();
0052 Gflash3Vector showerStartingPosition = theShowino->getPositionAtShower();
0053
0054
0055 jCalorimeter = Gflash::getCalorimeterNumber(showerStartingPosition);
0056
0057 double logEinc = std::log(incomingEnergy);
0058 double y = incomingEnergy / Gflash::criticalEnergy;
0059 double logY = std::log(y);
0060
0061
0062 double nSpots = 93.0 * std::log(Gflash::Z[jCalorimeter]) * std::pow(incomingEnergy, 0.876);
0063
0064
0065 double pathLength0 = theShowino->getPathLengthAtShower();
0066 double pathLength = pathLength0;
0067
0068
0069
0070 double fluctuatedTmax = std::log(logY - 0.7157);
0071 double fluctuatedAlpha = std::log(0.7996 + (0.4581 + 1.8628 / Gflash::Z[jCalorimeter]) * logY);
0072
0073 double sigmaTmax = 1.0 / (-1.4 + 1.26 * logY);
0074 double sigmaAlpha = 1.0 / (-0.58 + 0.86 * logY);
0075 double rho = 0.705 - 0.023 * logY;
0076 double sqrtPL = std::sqrt((1.0 + rho) / 2.0);
0077 double sqrtLE = std::sqrt((1.0 - rho) / 2.0);
0078
0079 double norm1 = CLHEP::RandGaussQ::shoot();
0080 double norm2 = CLHEP::RandGaussQ::shoot();
0081 double tempTmax = fluctuatedTmax + sigmaTmax * (sqrtPL * norm1 + sqrtLE * norm2);
0082 double tempAlpha = fluctuatedAlpha + sigmaAlpha * (sqrtPL * norm1 - sqrtLE * norm2);
0083
0084
0085 double tmax = std::exp(tempTmax);
0086 double alpha = std::exp(tempAlpha);
0087 double beta = std::max(0.0, (alpha - 1.0) / tmax);
0088
0089
0090 double averageTmax = logY - 0.858;
0091 double averageAlpha = 0.21 + (0.492 + 2.38 / Gflash::Z[jCalorimeter]) * logY;
0092 double spotTmax = averageTmax * (0.698 + .00212 * Gflash::Z[jCalorimeter]);
0093 double spotAlpha = averageAlpha * (0.639 + .00334 * Gflash::Z[jCalorimeter]);
0094 double spotBeta = std::max(0.0, (spotAlpha - 1.0) / spotTmax);
0095
0096 if (theHisto->getStoreFlag()) {
0097 theHisto->em_incE->Fill(incomingEnergy);
0098 theHisto->em_ssp_rho->Fill(showerStartingPosition.rho());
0099 theHisto->em_ssp_z->Fill(showerStartingPosition.z());
0100 }
0101
0102
0103 double z1 = 0.0251 + 0.00319 * logEinc;
0104 double z2 = 0.1162 - 0.000381 * Gflash::Z[jCalorimeter];
0105
0106 double k1 = 0.659 - 0.00309 * Gflash::Z[jCalorimeter];
0107 double k2 = 0.645;
0108 double k3 = -2.59;
0109 double k4 = 0.3585 + 0.0421 * logEinc;
0110
0111 double p1 = 2.623 - 0.00094 * Gflash::Z[jCalorimeter];
0112 double p2 = 0.401 + 0.00187 * Gflash::Z[jCalorimeter];
0113 double p3 = 1.313 - 0.0686 * logEinc;
0114
0115
0116
0117
0118
0119
0120 double e25Scale = 1.0;
0121 if (jCalorimeter == Gflash::kESPM)
0122 e25Scale = theEnergyScaleEB;
0123 else if (jCalorimeter == Gflash::kENCA)
0124 e25Scale = theEnergyScaleEE;
0125
0126
0127 p1 *= 0.965;
0128
0129
0130 double stepLengthLeft = getDistanceToOut(jCalorimeter);
0131
0132 int nSpots_sd = 0;
0133 double zInX0 = 0.0;
0134 double deltaZInX0 = 0.0;
0135 double deltaZ = 0.0;
0136 double stepLengthLeftInX0 = 0.0;
0137
0138 const double divisionStepInX0 = 0.1;
0139 double energy = incomingEnergy;
0140
0141 Genfun::IncompleteGamma gammaDist;
0142
0143 double energyInGamma = 0.0;
0144 double preEnergyInGamma = 0.0;
0145 double sigmaInGamma = 0.;
0146
0147 double preSigmaInGamma = 0.0;
0148
0149
0150 double deltaEnergy = 0.0;
0151 int spotCounter = 0;
0152
0153
0154 double deltaStep = 0.0;
0155
0156 theGflashHitList.clear();
0157
0158
0159 while (energy > 0.0 && stepLengthLeft > 0.0) {
0160 stepLengthLeftInX0 = stepLengthLeft / Gflash::radLength[jCalorimeter];
0161
0162 if (stepLengthLeftInX0 < divisionStepInX0) {
0163 deltaZInX0 = stepLengthLeftInX0;
0164 deltaZ = deltaZInX0 * Gflash::radLength[jCalorimeter];
0165 stepLengthLeft = 0.0;
0166 } else {
0167 deltaZInX0 = divisionStepInX0;
0168 deltaZ = deltaZInX0 * Gflash::radLength[jCalorimeter];
0169 stepLengthLeft -= deltaZ;
0170 }
0171
0172 zInX0 += deltaZInX0;
0173
0174 int nSpotsInStep = 0;
0175
0176 if (energy > energyCutoff) {
0177 preEnergyInGamma = energyInGamma;
0178 gammaDist.a().setValue(alpha);
0179 energyInGamma = gammaDist(beta * zInX0);
0180 double energyInDeltaZ = energyInGamma - preEnergyInGamma;
0181 deltaEnergy = std::min(energy, incomingEnergy * energyInDeltaZ);
0182
0183 preSigmaInGamma = sigmaInGamma;
0184 gammaDist.a().setValue(spotAlpha);
0185 sigmaInGamma = gammaDist(spotBeta * zInX0);
0186 nSpotsInStep = std::max(1, int(nSpots * (sigmaInGamma - preSigmaInGamma)));
0187 } else {
0188 deltaEnergy = energy;
0189 preSigmaInGamma = sigmaInGamma;
0190 nSpotsInStep = std::max(1, int(nSpots * (1.0 - preSigmaInGamma)));
0191 }
0192
0193 if (deltaEnergy > energy || (energy - deltaEnergy) < energyCutoff)
0194 deltaEnergy = energy;
0195
0196 energy -= deltaEnergy;
0197
0198 if (spotCounter + nSpotsInStep > maxNumberOfSpots) {
0199 nSpotsInStep = maxNumberOfSpots - spotCounter;
0200 if (nSpotsInStep < 1) {
0201 edm::LogInfo("SimGeneralGFlash") << "GflashEMShowerProfile: Too Many Spots ";
0202 edm::LogInfo("SimGeneralGFlash") << " - break to regenerate nSpotsInStep ";
0203 break;
0204 }
0205 }
0206
0207
0208 deltaStep += 0.5 * deltaZ;
0209 pathLength += deltaStep;
0210 deltaStep = 0.5 * deltaZ;
0211
0212
0213 double tScale = tmax * alpha / (alpha - 1.0) * (std::exp(fluctuatedAlpha) - 1.0) / std::exp(fluctuatedAlpha);
0214 double tau = std::min(10.0, (zInX0 - 0.5 * deltaZInX0) / tScale);
0215 double rCore = z1 + z2 * tau;
0216 double rTail = k1 * (std::exp(k3 * (tau - k2)) + std::exp(k4 * (tau - k2)));
0217 double p23 = (p2 - tau) / p3;
0218 double probabilityWeight = p1 * std::exp(p23 - std::exp(p23));
0219
0220
0221
0222
0223 double hitEnergy = deltaEnergy / nSpotsInStep * e25Scale * CLHEP::GeV;
0224 double hitTime = theShowino->getGlobalTime() * CLHEP::nanosecond + (pathLength - pathLength0) / 30.0;
0225
0226 GflashHit aHit;
0227
0228 for (int ispot = 0; ispot < nSpotsInStep; ispot++) {
0229 spotCounter++;
0230
0231
0232
0233
0234 double incrementPath = (deltaZ / nSpotsInStep) * (ispot + 0.5 - 0.5 * nSpotsInStep);
0235
0236
0237
0238 GflashTrajectoryPoint trajectoryPoint;
0239 theShowino->getHelix()->getGflashTrajectoryPoint(trajectoryPoint, pathLength + incrementPath);
0240
0241 double rShower = 0.0;
0242 Gflash3Vector hitPosition = locateHitPosition(trajectoryPoint, rCore, rTail, probabilityWeight, rShower);
0243
0244
0245 hitPosition *= CLHEP::cm;
0246
0247 if (std::fabs(hitPosition.getZ() / CLHEP::cm) > Gflash::Zmax[Gflash::kHE])
0248 continue;
0249
0250
0251 aHit.setTime(hitTime);
0252 aHit.setEnergy(hitEnergy);
0253 aHit.setPosition(hitPosition);
0254 theGflashHitList.push_back(aHit);
0255
0256 double zInX0_spot = std::abs(pathLength + incrementPath - pathLength0) / Gflash::radLength[jCalorimeter];
0257
0258 nSpots_sd++;
0259
0260
0261 if (theHisto->getStoreFlag()) {
0262 theHisto->em_long->Fill(zInX0_spot, hitEnergy / CLHEP::GeV);
0263 theHisto->em_lateral->Fill(zInX0_spot, rShower / Gflash::rMoliere[jCalorimeter], hitEnergy / CLHEP::GeV);
0264 theHisto->em_long_sd->Fill(zInX0_spot, hitEnergy / CLHEP::GeV);
0265 theHisto->em_lateral_sd->Fill(zInX0_spot, rShower / Gflash::rMoliere[jCalorimeter], hitEnergy / CLHEP::GeV);
0266 }
0267
0268 }
0269
0270 }
0271
0272 if (theHisto->getStoreFlag()) {
0273 theHisto->em_nSpots_sd->Fill(nSpots_sd);
0274 }
0275
0276
0277 }
0278
0279 double GflashEMShowerProfile::getDistanceToOut(Gflash::CalorimeterNumber kCalor) {
0280 double stepLengthLeft = 0.0;
0281 if (kCalor == Gflash::kESPM) {
0282 stepLengthLeft = theShowino->getHelix()->getPathLengthAtRhoEquals(Gflash::Rmax[Gflash::kESPM]) -
0283 theShowino->getPathLengthAtShower();
0284 } else if (kCalor == Gflash::kENCA) {
0285 double zsign = (theShowino->getPosition()).getEta() > 0 ? 1.0 : -1.0;
0286 stepLengthLeft = theShowino->getHelix()->getPathLengthAtZ(zsign * Gflash::Zmax[Gflash::kENCA]) -
0287 theShowino->getPathLengthAtShower();
0288 }
0289 return stepLengthLeft;
0290 }
0291
0292 Gflash3Vector GflashEMShowerProfile::locateHitPosition(
0293 GflashTrajectoryPoint &point, double rCore, double rTail, double probability, double &rShower) {
0294 double u1 = CLHEP::HepUniformRand();
0295 double u2 = CLHEP::HepUniformRand();
0296 double rInRM = 0.0;
0297
0298 if (u1 < probability) {
0299 rInRM = rCore * std::sqrt(u2 / (1.0 - u2));
0300 } else {
0301 rInRM = rTail * std::sqrt(u2 / (1.0 - u2));
0302 }
0303
0304 rShower = rInRM * Gflash::rMoliere[jCalorimeter];
0305
0306
0307 double azimuthalAngle = CLHEP::twopi * CLHEP::HepUniformRand();
0308
0309
0310 Gflash3Vector position = point.getPosition() + rShower * std::cos(azimuthalAngle) * point.getOrthogonalUnitVector() +
0311 rShower * std::sin(azimuthalAngle) * point.getCrossUnitVector();
0312
0313 return position;
0314 }