File indexing completed on 2024-05-10 02:21:20
0001
0002
0003
0004
0005
0006
0007 #include "SimG4CMS/Forward/interface/ZdcSD.h"
0008 #include "SimG4CMS/Forward/interface/ZdcShowerLibrary.h"
0009 #include "FWCore/Utilities/interface/Exception.h"
0010 #include "FWCore/ServiceRegistry/interface/Service.h"
0011 #include "FWCore/Utilities/interface/RandomNumberGenerator.h"
0012
0013 #include "G4VPhysicalVolume.hh"
0014 #include "G4Step.hh"
0015 #include "G4Track.hh"
0016 #include "Randomize.hh"
0017 #include <CLHEP/Units/SystemOfUnits.h>
0018
0019 ZdcShowerLibrary::ZdcShowerLibrary(const std::string& name, edm::ParameterSet const& p) {
0020 edm::ParameterSet m_HS = p.getParameter<edm::ParameterSet>("ZdcShowerLibrary");
0021 verbose = m_HS.getUntrackedParameter<int>("Verbosity", 0);
0022
0023 npe = 9;
0024 hits.reserve(npe);
0025 }
0026
0027 void ZdcShowerLibrary::initRun(G4ParticleTable* theParticleTable) {
0028 G4String parName;
0029 emPDG = theParticleTable->FindParticle(parName = "e-")->GetPDGEncoding();
0030 epPDG = theParticleTable->FindParticle(parName = "e+")->GetPDGEncoding();
0031 gammaPDG = theParticleTable->FindParticle(parName = "gamma")->GetPDGEncoding();
0032 pi0PDG = theParticleTable->FindParticle(parName = "pi0")->GetPDGEncoding();
0033 etaPDG = theParticleTable->FindParticle(parName = "eta")->GetPDGEncoding();
0034 nuePDG = theParticleTable->FindParticle(parName = "nu_e")->GetPDGEncoding();
0035 numuPDG = theParticleTable->FindParticle(parName = "nu_mu")->GetPDGEncoding();
0036 nutauPDG = theParticleTable->FindParticle(parName = "nu_tau")->GetPDGEncoding();
0037 anuePDG = theParticleTable->FindParticle(parName = "anti_nu_e")->GetPDGEncoding();
0038 anumuPDG = theParticleTable->FindParticle(parName = "anti_nu_mu")->GetPDGEncoding();
0039 anutauPDG = theParticleTable->FindParticle(parName = "anti_nu_tau")->GetPDGEncoding();
0040 geantinoPDG = theParticleTable->FindParticle(parName = "geantino")->GetPDGEncoding();
0041 edm::LogVerbatim("ZdcShower") << "ZdcShowerLibrary: Particle codes for e- = " << emPDG << ", e+ = " << epPDG
0042 << ", gamma = " << gammaPDG << ", pi0 = " << pi0PDG << ", eta = " << etaPDG
0043 << ", geantino = " << geantinoPDG << "\n nu_e = " << nuePDG
0044 << ", nu_mu = " << numuPDG << ", nu_tau = " << nutauPDG << ", anti_nu_e = " << anuePDG
0045 << ", anti_nu_mu = " << anumuPDG << ", anti_nu_tau = " << anutauPDG;
0046 }
0047
0048 std::vector<ZdcShowerLibrary::Hit>& ZdcShowerLibrary::getHits(const G4Step* aStep, bool& ok) {
0049 G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
0050 G4StepPoint* postStepPoint = aStep->GetPostStepPoint();
0051 G4Track* track = aStep->GetTrack();
0052
0053 const G4DynamicParticle* aParticle = track->GetDynamicParticle();
0054 const G4ThreeVector& momDir = aParticle->GetMomentumDirection();
0055 double energy = preStepPoint->GetKineticEnergy();
0056 G4ThreeVector hitPoint = preStepPoint->GetPosition();
0057 const G4ThreeVector& hitPointOrig = preStepPoint->GetPosition();
0058 G4int parCode = track->GetDefinition()->GetPDGEncoding();
0059
0060 hits.clear();
0061
0062 ok = false;
0063 if (parCode == geantinoPDG)
0064 return hits;
0065 ok = true;
0066
0067 G4ThreeVector pos;
0068 G4ThreeVector posLocal;
0069 double tSlice = (postStepPoint->GetGlobalTime()) / CLHEP::nanosecond;
0070
0071 int nHit = 0;
0072 HcalZDCDetId::Section section;
0073 bool side = false;
0074 int channel = 0;
0075 double xx, yy, zz;
0076 double xxlocal, yylocal, zzlocal;
0077
0078 ZdcShowerLibrary::Hit oneHit;
0079 side = (hitPointOrig.z() > 0.) ? true : false;
0080
0081 float xWidthEM = fabs(theXChannelBoundaries[0] - theXChannelBoundaries[1]);
0082 float zWidthEM = fabs(theZSectionBoundaries[0] - theZSectionBoundaries[1]);
0083 float zWidthHAD = fabs(theZHadChannelBoundaries[0] - theZHadChannelBoundaries[1]);
0084
0085 for (int i = 0; i < npe; i++) {
0086 if (i < 5) {
0087 section = HcalZDCDetId::EM;
0088 channel = i + 1;
0089 xxlocal = theXChannelBoundaries[i] + (xWidthEM / 2.);
0090 xx = xxlocal + X0;
0091 yy = 0.0;
0092 yylocal = yy + Y0;
0093 zzlocal = theZSectionBoundaries[0] + (zWidthEM / 2.);
0094 zz = (hitPointOrig.z() > 0.) ? zzlocal + Z0 : zzlocal - Z0;
0095 pos = G4ThreeVector(xx, yy, zz);
0096 posLocal = G4ThreeVector(xxlocal, yylocal, zzlocal);
0097 }
0098 if (i > 4) {
0099 section = HcalZDCDetId::HAD;
0100 channel = i - 4;
0101 xxlocal = 0.0;
0102 xx = xxlocal + X0;
0103 yylocal = 0;
0104 yy = yylocal + Y0;
0105 zzlocal = (hitPointOrig.z() > 0.) ? theZHadChannelBoundaries[i - 5] + (zWidthHAD / 2.)
0106 : theZHadChannelBoundaries[i - 5] - (zWidthHAD / 2.);
0107 zz = (hitPointOrig.z() > 0.) ? zzlocal + Z0 : zzlocal - Z0;
0108 pos = G4ThreeVector(xx, yy, zz);
0109 posLocal = G4ThreeVector(xxlocal, yylocal, zzlocal);
0110 }
0111
0112 oneHit.position = pos;
0113 oneHit.entryLocal = posLocal;
0114 oneHit.depth = channel;
0115 oneHit.time = tSlice;
0116 oneHit.detID = HcalZDCDetId(section, side, channel);
0117
0118
0119 hitPoint.setX(hitPointOrig.x() - X0);
0120 hitPoint.setY(hitPointOrig.y() - Y0);
0121 double setZ = (hitPointOrig.z() > 0.) ? hitPointOrig.z() - Z0 : fabs(hitPointOrig.z()) - Z0;
0122 hitPoint.setZ(setZ);
0123
0124 int dE = getEnergyFromLibrary(hitPoint, momDir, energy, parCode, section, side, channel);
0125
0126 int iparCode = encodePartID(parCode);
0127 if (iparCode == 0) {
0128 oneHit.DeEM = dE;
0129 oneHit.DeHad = 0.;
0130 } else {
0131 oneHit.DeEM = 0;
0132 oneHit.DeHad = dE;
0133 }
0134
0135 hits.push_back(oneHit);
0136
0137 edm::LogVerbatim("ZdcShower") << "\nZdcShowerLibrary:Generated Hit " << nHit << " orig hit pos " << hitPointOrig
0138 << " orig hit pos local coord" << hitPoint << " new position "
0139 << (hits[nHit].position) << " Channel " << (hits[nHit].depth) << " side " << side
0140 << " Time " << (hits[nHit].time) << " DetectorID " << (hits[nHit].detID)
0141 << " Had Energy " << (hits[nHit].DeHad) << " EM Energy " << (hits[nHit].DeEM)
0142 << "\n";
0143 nHit++;
0144 }
0145 return hits;
0146 }
0147
0148 int ZdcShowerLibrary::getEnergyFromLibrary(const G4ThreeVector& hitPoint,
0149 const G4ThreeVector& momDir,
0150 double energy,
0151 G4int parCode,
0152 HcalZDCDetId::Section section,
0153 bool side,
0154 int channel) {
0155 int nphotons = -1;
0156
0157 energy = energy / CLHEP::GeV;
0158
0159 edm::LogVerbatim("ZdcShower") << "\n ZdcShowerLibrary::getEnergyFromLibrary input/output variables:"
0160 << " phi: " << momDir.phi() / CLHEP::deg << " theta: " << momDir.theta() / CLHEP::deg
0161 << " xin : " << hitPoint.x() << " yin : " << hitPoint.y() << " zin : " << hitPoint.z()
0162 << " track en: " << energy << "(GeV)"
0163 << " section: " << section << " side: " << side << " channel: " << channel
0164 << " partID: " << parCode;
0165
0166
0167
0168
0169
0170
0171
0172
0173 int iparCode = encodePartID(parCode);
0174
0175 double eav = 0.;
0176 double esig = 0.;
0177 double edis = 0.;
0178
0179 float xin = hitPoint.x();
0180 float yin = hitPoint.y();
0181 float fact = 0.;
0182
0183 if (section == 1 && iparCode != 0) {
0184 if (channel < 5)
0185 if (((theXChannelBoundaries[channel - 1]) < (xin + X0)) && ((xin + X0) <= theXChannelBoundaries[channel]))
0186 fact = 0.18;
0187 if (channel == 5)
0188 if (theXChannelBoundaries[channel - 1] < xin + X0)
0189 fact = 0.18;
0190 }
0191
0192 if (section == 2 && iparCode != 0) {
0193 if (channel == 1)
0194 fact = 0.34;
0195 if (channel == 2)
0196 fact = 0.24;
0197 if (channel == 3)
0198 fact = 0.17;
0199 if (channel == 4)
0200 fact = 0.07;
0201 }
0202 if (section == 1 && iparCode == 0) {
0203 if (channel < 5)
0204 if (((theXChannelBoundaries[channel - 1]) < (xin + X0)) && ((xin + X0) <= theXChannelBoundaries[channel]))
0205 fact = 1.;
0206 if (channel == 5)
0207 if (theXChannelBoundaries[channel - 1] < xin + X0)
0208 fact = 1.0;
0209 }
0210
0211
0212 yin = yin / CLHEP::cm;
0213 xin = xin / CLHEP::cm;
0214
0215 if (iparCode == 0) {
0216 eav = ((((((-0.0002 * xin - 2.0e-13) * xin + 0.0022) * xin + 1.0e-11) * xin - 0.0217) * xin - 3.0e-10) * xin +
0217 1.0028) *
0218 (((0.0001 * yin + 0.0056) * yin + 0.0508) * yin + 1.0) * 300.0 * pow((energy / 300.0), 0.99);
0219 esig = ((((((0.0005 * xin - 1.0e-12) * xin - 0.0052) * xin + 5.0e-11) * xin + 0.032) * xin - 2.0e-10) * xin + 1.0) *
0220 (((0.0006 * yin + 0.0071) * yin - 0.031) * yin + 1.0) * 30.0 * pow((energy / 300.0), 0.54);
0221 edis = 1.0;
0222 } else {
0223 eav = ((((((-0.0002 * xin - 2.0e-13) * xin + 0.0022) * xin + 1.0e-11) * xin - 0.0217) * xin - 3.0e-10) * xin +
0224 1.0028) *
0225 (((0.0001 * yin + 0.0056) * yin + 0.0508) * yin + 1.0) * 300.0 * pow((energy / 300.0), 1.12);
0226 esig = ((((((0.0005 * xin - 1.0e-12) * xin - 0.0052) * xin + 5.0e-11) * xin + 0.032) * xin - 2.0e-10) * xin + 1.0) *
0227 (((0.0006 * yin + 0.0071) * yin - 0.031) * yin + 1.0) * 54.0 * pow((energy / 300.0), 0.93);
0228 edis = 3.0;
0229 }
0230
0231 if (eav < 0. || edis < 0.) {
0232 edm::LogVerbatim("ZdcShower") << " Negative everage energy from parametrization \n"
0233 << " xin: " << xin << "(cm)"
0234 << " yin: " << yin << "(cm)"
0235 << " track en: " << energy << "(GeV)"
0236 << " eaverage: " << eav / CLHEP::GeV << " (GeV)"
0237 << " esigma: " << esig / CLHEP::GeV << " (GeV)"
0238 << " edist: " << edis << " (GeV)"
0239 << " dE hit: " << nphotons / CLHEP::GeV << " (GeV)";
0240 return 0;
0241 }
0242
0243
0244 eav = eav * CLHEP::GeV;
0245 esig = esig * CLHEP::GeV;
0246
0247 while (nphotons == -1 || nphotons > int(eav + 5. * esig))
0248 nphotons = static_cast<int>(fact * photonFluctuation(eav, esig, edis));
0249
0250 edm::LogVerbatim("ZdcShower") << " track en: " << energy << "(GeV)"
0251 << " eaverage: " << eav / CLHEP::GeV << " (GeV)"
0252 << " esigma: " << esig / CLHEP::GeV << " (GeV)"
0253 << " edist: " << edis << " (GeV)"
0254 << " dE hit: " << nphotons / CLHEP::GeV << " (GeV)";
0255
0256 return nphotons;
0257 }
0258
0259 int ZdcShowerLibrary::photonFluctuation(double eav, double esig, double edis) {
0260 int nphot = 0;
0261 double efluct = 0.;
0262 if (edis == 1.0)
0263 efluct = eav + esig * CLHEP::RandGaussQ::shoot();
0264 if (edis == 3.0)
0265 efluct = eav + esig * CLHEP::RandLandau::shoot();
0266 nphot = int(efluct);
0267 if (nphot < 0)
0268 nphot = 0;
0269 return nphot;
0270 }
0271
0272 int ZdcShowerLibrary::encodePartID(G4int parCode) {
0273 G4int iparCode = 1;
0274 if (parCode == emPDG || parCode == epPDG || parCode == gammaPDG) {
0275 iparCode = 0;
0276 } else {
0277 return iparCode;
0278 }
0279 return iparCode;
0280 }