File indexing completed on 2024-05-10 02:21:16
0001 #include "SimG4CMS/Calo/interface/HFGflash.h"
0002
0003 #include "G4VPhysicalVolume.hh"
0004 #include "G4Step.hh"
0005 #include "G4Track.hh"
0006 #include "G4Navigator.hh"
0007 #include "G4NavigationHistory.hh"
0008 #include <CLHEP/Units/PhysicalConstants.h>
0009 #include <CLHEP/Units/SystemOfUnits.h>
0010
0011 #include "Randomize.hh"
0012 #include "G4TransportationManager.hh"
0013 #include "G4VPhysicalVolume.hh"
0014 #include "G4LogicalVolume.hh"
0015 #include "G4VSensitiveDetector.hh"
0016 #include "G4EventManager.hh"
0017 #include "G4SteppingManager.hh"
0018 #include "G4FastTrack.hh"
0019 #include "G4ParticleTable.hh"
0020
0021 #include "CLHEP/GenericFunctions/IncompleteGamma.hh"
0022
0023 #include "SimG4Core/Application/interface/SteppingAction.h"
0024 #include "SimGeneral/GFlash/interface/GflashEMShowerProfile.h"
0025 #include "SimGeneral/GFlash/interface/GflashTrajectoryPoint.h"
0026
0027 #include "FWCore/ServiceRegistry/interface/Service.h"
0028 #include "CommonTools/UtilAlgos/interface/TFileService.h"
0029
0030 #include <cmath>
0031
0032 using CLHEP::cm;
0033 using CLHEP::degree;
0034 using CLHEP::GeV;
0035 using CLHEP::nanosecond;
0036 using CLHEP::twopi;
0037
0038
0039
0040 HFGflash::HFGflash(edm::ParameterSet const& p) {
0041 edm::ParameterSet m_HF = p.getParameter<edm::ParameterSet>("HFGflash");
0042 theBField = m_HF.getUntrackedParameter<double>("BField", 3.8);
0043 theWatcherOn = m_HF.getUntrackedParameter<bool>("WatcherOn", true);
0044 theFillHisto = m_HF.getUntrackedParameter<bool>("FillHisto", true);
0045 edm::LogVerbatim("HFShower") << "HFGFlash:: Set B-Field to " << theBField << ", WatcherOn to " << theWatcherOn
0046 << " and FillHisto to " << theFillHisto;
0047
0048 theHelix = std::make_unique<GflashTrajectory>();
0049 theGflashStep = std::make_unique<G4Step>();
0050 theGflashNavigator = std::make_unique<G4Navigator>();
0051 theGflashTouchableHandle = std::make_unique<G4TouchableHistory>();
0052
0053 #ifdef EDM_ML_DEBUG
0054 if (theFillHisto) {
0055 edm::Service<TFileService> tfile;
0056 if (tfile.isAvailable()) {
0057 TFileDirectory showerDir = tfile->mkdir("GflashEMShowerProfile");
0058
0059 em_incE = showerDir.make<TH1F>("em_incE", "Incoming energy (GeV)", 500, 0, 500.);
0060 em_ssp_rho =
0061 showerDir.make<TH1F>("em_ssp_rho", "Shower starting position;#rho (cm);Number of Events", 100, 100.0, 200.0);
0062 em_ssp_z =
0063 showerDir.make<TH1F>("em_ssp_z", "Shower starting position;z (cm);Number of Events", 2000, 0.0, 2000.0);
0064 em_long =
0065 showerDir.make<TH1F>("em_long", "Longitudinal Profile;Radiation Length;Number of Spots", 800, 800.0, 1600.0);
0066 em_lateral = showerDir.make<TH1F>("em_lateral", "Lateral Profile;Radiation Length;Moliere Radius", 100, 0.0, 5.0);
0067 em_2d = showerDir.make<TH2F>("em_2d",
0068 "Lateral Profile vs. Shower Depth;Radiation Length;Moliere Radius",
0069 800,
0070 800.0,
0071 1600.0,
0072 100,
0073 0.0,
0074 5.0);
0075 em_long_sd = showerDir.make<TH1F>("em_long_sd",
0076 "Longitudinal Profile in Sensitive Detector;Radiation Length;Number of Spots",
0077 800,
0078 800.0,
0079 1600.0);
0080 em_lateral_sd =
0081 showerDir.make<TH1F>("em_lateral_sd",
0082 "Lateral Profile vs. Shower Depth in Sensitive Detector;Radiation Length;Moliere Radius",
0083 100,
0084 0.0,
0085 5.0);
0086 em_2d_sd =
0087 showerDir.make<TH2F>("em_2d_sd",
0088 "Lateral Profile vs. Shower Depth in Sensitive Detector;Radiation Length;Moliere Radius",
0089 800,
0090 800.0,
0091 1600.0,
0092 100,
0093 0.0,
0094 5.0);
0095 em_ze = showerDir.make<TH2F>(
0096 "em_ze", "Profile vs. Energy;Radiation Length;Moliere Radius", 800, 800.0, 1600.0, 1000, 0.0, 1.0);
0097 em_ratio = showerDir.make<TH2F>(
0098 "em_ratio", "Profile vs. Energy;Radiation Length;Moliere Radius", 800, 800.0, 1600.0, 1000, 0.0, 100.0);
0099 em_ratio_selected = showerDir.make<TH2F>("em_ratio_selected",
0100 "Profile vs. Energy;Radiation Length;Moliere Radius",
0101 800,
0102 800.0,
0103 1600.0,
0104 1000,
0105 0.0,
0106 100.0);
0107 em_nSpots_sd =
0108 showerDir.make<TH1F>("em_nSpots_sd",
0109 "Number of Gflash Spots in Sensitive Detector;Number of Spots;Number of Events",
0110 100,
0111 0.0,
0112 100);
0113 em_ze_ratio = showerDir.make<TH1F>("em_ze_ratio", "Ratio of Energy and Z Position", 1000, 0.0, 0.001);
0114 } else {
0115 theFillHisto = false;
0116 edm::LogVerbatim("HFShower") << "HFGFlash::No file is available for saving"
0117 << " histos so the flag is set to false";
0118 }
0119 }
0120 #endif
0121 jCalorimeter = Gflash::kHF;
0122 }
0123
0124 HFGflash::~HFGflash() {}
0125
0126 std::vector<HFGflash::Hit> HFGflash::gfParameterization(const G4Step* aStep, bool onlyLong) {
0127 double tempZCalo = 26;
0128 double hfcriticalEnergy = 0.021;
0129
0130 std::vector<HFGflash::Hit> hit;
0131 HFGflash::Hit oneHit;
0132
0133 auto const preStepPoint = aStep->GetPreStepPoint();
0134 auto const track = aStep->GetTrack();
0135
0136
0137
0138
0139 const G4double energyCutoff = 1;
0140 const G4int maxNumberOfSpots = 10000000;
0141
0142 G4ThreeVector showerStartingPosition = track->GetPosition() / cm;
0143 G4ThreeVector showerMomentum = preStepPoint->GetMomentum() / GeV;
0144 jCalorimeter = Gflash::kHF;
0145
0146 const G4double invgev = 1.0 / CLHEP::GeV;
0147 G4double energy = preStepPoint->GetTotalEnergy() * invgev;
0148 G4double logEinc = std::log(energy);
0149
0150 G4double y = energy / hfcriticalEnergy;
0151 G4double logY = std::log(y);
0152
0153 G4double nSpots = 93.0 * std::log(tempZCalo) * energy;
0154 if (energy < 1.6)
0155 nSpots = 140.4 * std::log(tempZCalo) * std::pow(energy, 0.876);
0156
0157
0158 double charge = track->GetStep()->GetPreStepPoint()->GetCharge();
0159 theHelix->initializeTrajectory(showerMomentum, showerStartingPosition, charge, theBField);
0160
0161 G4double pathLength0 = theHelix->getPathLengthAtZ(showerStartingPosition.getZ());
0162 G4double pathLength = pathLength0;
0163
0164
0165
0166 G4double fluctuatedTmax = std::log(logY - 0.7157);
0167 G4double fluctuatedAlpha = std::log(0.7996 + (0.4581 + 1.8628 / tempZCalo) * logY);
0168
0169 G4double sigmaTmax = 1.0 / (-1.4 + 1.26 * logY);
0170 G4double sigmaAlpha = 1.0 / (-0.58 + 0.86 * logY);
0171 G4double rho = 0.705 - 0.023 * logY;
0172 G4double sqrtPL = std::sqrt((1.0 + rho) / 2.0);
0173 G4double sqrtLE = std::sqrt((1.0 - rho) / 2.0);
0174
0175 G4double norm1 = G4RandGauss::shoot();
0176 G4double norm2 = G4RandGauss::shoot();
0177 G4double tempTmax = fluctuatedTmax + sigmaTmax * (sqrtPL * norm1 + sqrtLE * norm2);
0178 G4double tempAlpha = fluctuatedAlpha + sigmaAlpha * (sqrtPL * norm1 - sqrtLE * norm2);
0179
0180
0181 G4double tmax = std::exp(tempTmax);
0182 G4double alpha = std::exp(tempAlpha);
0183 G4double beta = (alpha - 1.0) / tmax;
0184
0185 if (!alpha)
0186 return hit;
0187 if (!beta)
0188 return hit;
0189 if (alpha < 0.00001)
0190 return hit;
0191 if (beta < 0.00001)
0192 return hit;
0193
0194
0195 G4double averageTmax = logY - 0.858;
0196 G4double averageAlpha = 0.21 + (0.492 + 2.38 / tempZCalo) * logY;
0197 G4double spotTmax = averageTmax * (0.698 + .00212 * tempZCalo);
0198 G4double spotAlpha = averageAlpha * (0.639 + .00334 * tempZCalo);
0199 G4double spotBeta = (spotAlpha - 1.0) / spotTmax;
0200
0201 if (!spotAlpha)
0202 return hit;
0203 if (!spotBeta)
0204 return hit;
0205 if (spotAlpha < 0.00001)
0206 return hit;
0207 if (spotBeta < 0.00001)
0208 return hit;
0209
0210 #ifdef EDM_ML_DEBUG
0211 edm::LogVerbatim("HFShower") << "HFGflash: Incoming energy = " << energy << " Position (rho,z) = ("
0212 << showerStartingPosition.rho() << ", " << showerStartingPosition.z() << ")";
0213
0214 if (theFillHisto) {
0215 em_incE->Fill(energy);
0216 em_ssp_rho->Fill(showerStartingPosition.rho());
0217 em_ssp_z->Fill(std::abs(showerStartingPosition.z()));
0218 }
0219 #endif
0220
0221 G4double z1 = 0.0251 + 0.00319 * logEinc;
0222 G4double z2 = 0.1162 - 0.000381 * tempZCalo;
0223
0224 G4double k1 = 0.659 - 0.00309 * tempZCalo;
0225 G4double k2 = 0.645;
0226 G4double k3 = -2.59;
0227 G4double k4 = 0.3585 + 0.0421 * logEinc;
0228
0229 G4double p1 = 2.623 - 0.00094 * tempZCalo;
0230 G4double p2 = 0.401 + 0.00187 * tempZCalo;
0231 G4double p3 = 1.313 - 0.0686 * logEinc;
0232
0233
0234
0235 const G4double e25Scale = 1.03551;
0236 z1 *= 9.76972e-01 - 3.85026e-01 * std::tanh(1.82790e+00 * std::log(energy) - 3.66237e+00);
0237 p1 *= 0.96;
0238
0239 #ifdef EDM_ML_DEBUG
0240 G4int nSpots_sd = 0;
0241 #endif
0242
0243 G4double stepLengthLeft = 10000;
0244 G4double zInX0 = 0.0;
0245 G4double deltaZInX0 = 0.0;
0246 G4double deltaZ = 0.0;
0247 G4double stepLengthLeftInX0 = 0.0;
0248
0249 const G4double divisionStepInX0 = 0.1;
0250
0251 Genfun::IncompleteGamma gammaDist;
0252
0253 G4double energyInGamma = 0.0;
0254 G4double preEnergyInGamma = 0.0;
0255 G4double sigmaInGamma = 0.;
0256 G4double preSigmaInGamma = 0.0;
0257
0258
0259 G4double deltaEnergy = 0.0;
0260 G4int spotCounter = 0;
0261
0262
0263 G4double deltaStep = 0.0;
0264
0265
0266 G4double timeGlobal = preStepPoint->GetGlobalTime();
0267
0268 theGflashNavigator->SetWorldVolume(
0269 G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking()->GetWorldVolume());
0270
0271
0272
0273 #ifdef EDM_ML_DEBUG
0274 edm::LogVerbatim("HFShower") << "HFGflash: Energy = " << energy << " Step Length Left = " << stepLengthLeft;
0275 #endif
0276 while (energy > 0.0 && stepLengthLeft > 0.0) {
0277 stepLengthLeftInX0 = stepLengthLeft / Gflash::radLength[jCalorimeter];
0278
0279 if (stepLengthLeftInX0 < divisionStepInX0) {
0280 deltaZInX0 = stepLengthLeftInX0;
0281 deltaZ = deltaZInX0 * Gflash::radLength[jCalorimeter];
0282 stepLengthLeft = 0.0;
0283 } else {
0284 deltaZInX0 = divisionStepInX0;
0285 deltaZ = deltaZInX0 * Gflash::radLength[jCalorimeter];
0286 stepLengthLeft -= deltaZ;
0287 }
0288
0289 zInX0 += deltaZInX0;
0290
0291 #ifdef EDM_ML_DEBUG
0292 edm::LogVerbatim("HFShower") << "HFGflash: zInX0 = " << zInX0 << " spotBeta*zInX0 = " << spotBeta * zInX0;
0293 #endif
0294 if ((!zInX0) || (!(spotBeta * zInX0 != 0)) || (zInX0 < 0.01) || (spotBeta * zInX0 < 0.00001) ||
0295 (!(zInX0 * beta != 0)) || (zInX0 * beta < 0.00001))
0296 return hit;
0297
0298 G4int nSpotsInStep = 0;
0299
0300 #ifdef EDM_ML_DEBUG
0301 edm::LogVerbatim("HFShower") << "HFGflash: Energy - Energy Cut off = " << energy - energyCutoff;
0302 #endif
0303
0304 if (energy > energyCutoff) {
0305 preEnergyInGamma = energyInGamma;
0306 gammaDist.a().setValue(alpha);
0307
0308 energyInGamma = gammaDist(beta * zInX0);
0309 G4double energyInDeltaZ = energyInGamma - preEnergyInGamma;
0310 deltaEnergy = std::min(energy, energy * energyInDeltaZ);
0311
0312 preSigmaInGamma = sigmaInGamma;
0313 gammaDist.a().setValue(spotAlpha);
0314 sigmaInGamma = gammaDist(spotBeta * zInX0);
0315 nSpotsInStep = std::max(1, int(nSpots * (sigmaInGamma - preSigmaInGamma)));
0316 } else {
0317 deltaEnergy = energy;
0318 preSigmaInGamma = sigmaInGamma;
0319 nSpotsInStep = std::max(1, int(nSpots * (1.0 - preSigmaInGamma)));
0320 }
0321
0322 if (deltaEnergy > energy || (energy - deltaEnergy) < energyCutoff)
0323 deltaEnergy = energy;
0324
0325 energy -= deltaEnergy;
0326
0327 if (spotCounter + nSpotsInStep > maxNumberOfSpots) {
0328 nSpotsInStep = maxNumberOfSpots - spotCounter;
0329 if (nSpotsInStep < 1)
0330 nSpotsInStep = 1;
0331 }
0332
0333
0334 deltaStep += 0.5 * deltaZ;
0335 pathLength += deltaStep;
0336 deltaStep = 0.5 * deltaZ;
0337
0338
0339 G4double tScale = tmax * alpha / (alpha - 1.0) * (1.0 - std::exp(-fluctuatedAlpha));
0340 G4double tau = std::min(10.0, (zInX0 - 0.5 * deltaZInX0) / tScale);
0341 G4double rCore = z1 + z2 * tau;
0342 G4double rTail = k1 * (std::exp(k3 * (tau - k2)) + std::exp(k4 * (tau - k2)));
0343 G4double p23 = (p2 - tau) / p3;
0344 G4double probabilityWeight = p1 * std::exp(p23 - std::exp(p23));
0345
0346
0347
0348
0349 G4double emSpotEnergy = deltaEnergy / (nSpotsInStep * e25Scale * GeV);
0350
0351 #ifdef EDM_ML_DEBUG
0352 edm::LogVerbatim("HFShower") << "HFGflash: nSpotsInStep = " << nSpotsInStep;
0353 #endif
0354
0355 for (G4int ispot = 0; ispot < nSpotsInStep; ispot++) {
0356 spotCounter++;
0357 G4double u1 = G4UniformRand();
0358 G4double u2 = G4UniformRand();
0359 G4double rInRM = 0.0;
0360
0361 if (u1 < probabilityWeight) {
0362 rInRM = rCore * std::sqrt(u2 / (1.0 - u2));
0363 } else {
0364 rInRM = rTail * std::sqrt(u2 / (1.0 - u2));
0365 }
0366
0367 G4double rShower = rInRM * Gflash::rMoliere[jCalorimeter];
0368
0369
0370 G4double azimuthalAngle = twopi * G4UniformRand();
0371
0372
0373
0374 G4double incrementPath = (deltaZ / nSpotsInStep) * (ispot + 0.5 - 0.5 * nSpotsInStep);
0375
0376
0377 GflashTrajectoryPoint trajectoryPoint;
0378 theHelix->getGflashTrajectoryPoint(trajectoryPoint, pathLength + incrementPath);
0379
0380 G4ThreeVector SpotPosition0 = trajectoryPoint.getPosition() +
0381 rShower * std::cos(azimuthalAngle) * trajectoryPoint.getOrthogonalUnitVector() +
0382 rShower * std::sin(azimuthalAngle) * trajectoryPoint.getCrossUnitVector();
0383
0384
0385
0386 SpotPosition0 *= cm;
0387
0388
0389
0390
0391
0392
0393 timeGlobal += 0.0001 * nanosecond;
0394
0395
0396
0397 G4double zInX0_spot = std::abs(pathLength + incrementPath - pathLength0) / Gflash::radLength[jCalorimeter];
0398
0399 #ifdef EDM_ML_DEBUG
0400 edm::LogVerbatim("HFShower") << "HFGflash: zInX0_spot,emSpotEnergy/GeV =" << zInX0_spot << " , "
0401 << emSpotEnergy / GeV << "emSpotEnergy/GeV =" << emSpotEnergy / GeV;
0402 #endif
0403
0404 if (zInX0_spot <= 0)
0405 continue;
0406 if (emSpotEnergy <= 0)
0407 continue;
0408 if (rShower / Gflash::rMoliere[jCalorimeter] <= 0)
0409 continue;
0410
0411 oneHit.depth = 1;
0412
0413 #ifdef EDM_ML_DEBUG
0414 if (theFillHisto) {
0415 em_long->Fill(SpotPosition0.z() / cm, emSpotEnergy * invgev);
0416 em_lateral->Fill(rShower / Gflash::rMoliere[jCalorimeter], emSpotEnergy * invgev);
0417 em_2d->Fill(SpotPosition0.z() / cm, rShower / Gflash::rMoliere[jCalorimeter], emSpotEnergy * invgev);
0418 }
0419 #endif
0420
0421
0422
0423
0424 double energyratio = emSpotEnergy / (preStepPoint->GetTotalEnergy() / (nSpots * e25Scale));
0425
0426 if (emSpotEnergy / GeV < 0.0001)
0427 continue;
0428 if (energyratio > 80)
0429 continue;
0430
0431 double zshift = 0;
0432 if (SpotPosition0.z() > 0)
0433 zshift = 18;
0434 if (SpotPosition0.z() < 0)
0435 zshift = -18;
0436
0437 G4ThreeVector gfshift(0, 0, zshift * (pow(100, 0.1) / pow(energy, 0.1)));
0438
0439 G4ThreeVector SpotPosition = gfshift + SpotPosition0;
0440
0441 double LengthWeight = std::fabs(std::pow(SpotPosition0.z() / 11370, 1));
0442 if (G4UniformRand() > 0.0021 * energyratio * LengthWeight)
0443 continue;
0444
0445 oneHit.position = SpotPosition;
0446 oneHit.time = timeGlobal;
0447 oneHit.edep = emSpotEnergy * invgev;
0448 hit.push_back(oneHit);
0449 #ifdef EDM_ML_DEBUG
0450 nSpots_sd++;
0451 #endif
0452
0453 }
0454
0455 }
0456 #ifdef EDM_ML_DEBUG
0457 if (theFillHisto) {
0458 em_nSpots_sd->Fill(nSpots_sd);
0459 }
0460 #endif
0461 return hit;
0462 }