15 #include "G4SDManager.hh"
18 #include "G4VProcess.hh"
21 #include "G4Cerenkov.hh"
22 #include "G4LogicalVolumeStore.hh"
24 #include "CLHEP/Units/GlobalSystemOfUnits.h"
25 #include "CLHEP/Units/GlobalPhysicalConstants.h"
26 #include "Randomize.hh"
27 #include "G4Poisson.hh"
56 edm::LogVerbatim(
"ForwardSim") <<
"********************************************************\n"
57 <<
"* Constructing a CastorSD with name " << GetName() <<
"\n"
59 <<
"********************************************************";
61 const G4LogicalVolumeStore* lvs = G4LogicalVolumeStore::GetInstance();
62 for (
auto lv : *lvs) {
63 if (strcmp((lv->GetName()).c_str(),
"C3EF") == 0) {
66 if (strcmp((lv->GetName()).c_str(),
"C3HF") == 0) {
69 if (strcmp((lv->GetName()).c_str(),
"C4EF") == 0) {
72 if (strcmp((lv->GetName()).c_str(),
"C4HF") == 0) {
75 if (strcmp((lv->GetName()).c_str(),
"CAST") == 0) {
82 LogDebug(
"ForwardSim") <<
"CastorSD:: LogicalVolume pointers\n"
84 <<
" for C4HF; " <<
lvCAST <<
" for CAST. ";
94 double NCherPhot = 0.;
97 auto const theTrack = aStep->GetTrack();
100 auto const preStepPoint = aStep->GetPreStepPoint();
101 auto const currentPV = preStepPoint->GetPhysicalVolume();
102 auto const currentLV = currentPV->GetLogicalVolume();
106 <<
"\n CurrentStepNumber , TrackID , ParentID, Particle , VertexPosition ,"
107 <<
" LogicalVolumeAtVertex , PV, Time"
108 <<
"\n TRACKINFO: " << theTrack->GetCurrentStepNumber() <<
" , "
109 << theTrack->GetTrackID() <<
" , " << theTrack->GetParentID() <<
" , "
110 << theTrack->GetDefinition()->GetParticleName() <<
" , "
111 << theTrack->GetVertexPosition() <<
" , "
112 << theTrack->GetLogicalVolumeAtVertex()->GetName() <<
" , " << currentPV->GetName()
113 <<
" , " << theTrack->GetGlobalTime();
117 const G4ThreeVector& hit_mom = preStepPoint->GetMomentumDirection();
118 const G4ThreeVector& hitPoint = preStepPoint->GetPosition();
119 double zint = hitPoint.z();
122 G4int parCode = theTrack->GetDefinition()->GetPDGEncoding();
125 double meanNCherPhot = 0;
126 G4double
charge = preStepPoint->GetCharge();
129 return meanNCherPhot;
132 G4double
beta = preStepPoint->GetBeta();
133 const double bThreshold = 0.67;
135 if (
beta < bThreshold) {
136 return meanNCherPhot;
145 G4double stepl = aStep->GetStepLength() / cm;
166 edm::LogVerbatim(
"ForwardSim") <<
"CastorSD::getEnergyDeposit: for ID=" << theTrack->GetTrackID()
167 <<
" LV: " << currentLV->GetName() <<
" isHad:" << isHad <<
" pdg=" << parCode
169 <<
" Edep= " << aStep->GetTotalEnergyDeposit();
172 const double nMedium = 1.4925;
176 const double photEnSpectrDE = 1.24;
185 const double thFullRefl = 23.;
186 const double thFullReflRad = thFullRefl *
pi / 180.;
189 const double thFibDir = 45.;
195 const double thFibDirRad = thFibDir *
pi / 180.;
199 hit_mom.z() /
sqrt(hit_mom.x() * hit_mom.x() + hit_mom.y() * hit_mom.y() + hit_mom.z() * hit_mom.z());
209 double costhcher = 1. / (nMedium *
beta);
210 double thcher = acos(
std::min(
std::max(costhcher,
double(-1.)),
double(1.)));
213 double DelFibPart =
std::abs(th - thFibDirRad);
218 double a =
tan(thFibDirRad) +
tan(
std::abs(thFibDirRad - thFullReflRad));
226 if (DelFibPart > (thFullReflRad + thcher)) {
229 if ((th + thcher) < (thFibDirRad + thFullReflRad) && (th - thcher) > (thFibDirRad - thFullReflRad)) {
235 if ((thFibDirRad + thFullReflRad) < (th + thcher) && (thFibDirRad - thFullReflRad) > (th - thcher)) {
246 double arg_arcos = 0.;
247 double tan_arcos = 2. *
a *
d;
249 arg_arcos = (
r *
r -
a *
a -
d *
d) / tan_arcos;
252 d_qz =
std::abs(th_arcos / CLHEP::twopi);
259 meanNCherPhot = 370. *
charge *
charge * (1. - 1. / (nMedium * nMedium *
beta *
beta)) * photEnSpectrDE * stepl;
263 int poissNCherPhot =
std::max(0, (
int)G4Poisson(meanNCherPhot *
scale));
265 const double effPMTandTransport = 0.19;
266 const double ReflPower = 0.1;
267 double proba = d_qz + (1 - d_qz) * ReflPower;
268 NCherPhot = poissNCherPhot * effPMTandTransport * proba * 0.307;
270 edm::LogVerbatim(
"ForwardSim") <<
" Nph= " << NCherPhot <<
" Np= " << poissNCherPhot
271 <<
" eff= " << effPMTandTransport <<
" pb= " << proba <<
" Nmean= " << meanNCherPhot
272 <<
" q=" <<
charge <<
" beta=" <<
beta <<
" nMedium= " << nMedium <<
" sl= " << stepl
273 <<
" Nde=" << photEnSpectrDE;
289 edm::LogVerbatim(
"ForwardSim") <<
"CastorSD: updates numbering scheme for " << GetName();
312 showerPhi += 2 *
M_PI;
317 int showerOctSector = (
int)(showerPhi / (
M_PI / 4));
320 uint32_t
sec = ((unitID >> 4) & 0xF);
321 uint32_t complement = (unitID & 0xFFFFFF0F);
324 double trackZ =
track->GetPosition().z();
327 int dSec = 2 * (trackOctSector - showerOctSector);
330 int sec1 =
sec - dSec;
336 sec = (uint32_t)(sec1);
345 newUnitID = complement |
sec;
348 if (newUnitID != unitID) {
349 LogDebug(
"ForwardSim") <<
"\n CastorSD::rotateUnitID: "
350 <<
"\n unitID = " << unitID <<
"\n newUnitID = " << newUnitID;
368 auto const theTrack = aStep->GetTrack();
369 auto parCode = theTrack->GetDefinition()->GetPDGEncoding();
384 auto const preStepPoint = aStep->GetPreStepPoint();
385 auto const currentPV = preStepPoint->GetPhysicalVolume();
386 auto const currentLV = currentPV->GetLogicalVolume();
389 edm::LogVerbatim(
"ForwardSim") <<
"CastorSD::getFromLibrary: for ID=" << theTrack->GetTrackID()
390 <<
" parentID= " << theTrack->GetParentID() <<
" "
391 << theTrack->GetDefinition()->GetParticleName() <<
" LV: " << currentLV->GetName()
392 <<
" PV: " << currentPV->GetName() <<
"\n eta= " << theTrack->GetPosition().eta()
393 <<
" phi= " << theTrack->GetPosition().phi()
394 <<
" z(cm)= " << theTrack->GetPosition().z() / cm
395 <<
" time(ns)= " << theTrack->GetGlobalTime()
396 <<
" E(GeV)= " << theTrack->GetTotalEnergy() /
GeV;
400 const G4ThreeVector& hitPoint = preStepPoint->GetPosition();
401 const G4ThreeVector& hit_mom = preStepPoint->GetMomentumDirection();
402 double zint = hitPoint.z();
403 double pz = hit_mom.z();
406 bool backward = (pz * zint < 0.) ?
true :
false;
409 bool aboveThreshold = (theTrack->GetKineticEnergy() >
energyThresholdSL) ?
true :
false;
416 double theta_max =
M_PI - 3.1305;
417 double R_mom =
sqrt(hit_mom.x() * hit_mom.x() + hit_mom.y() * hit_mom.y());
419 bool angleok = (
theta < theta_max) ?
true :
false;
422 double R =
sqrt(hitPoint.x() * hitPoint.x() + hitPoint.y() * hitPoint.y());
423 bool dot = (zint < -14450. &&
R < 45.) ?
true :
false;
424 bool inRange = (zint < -14700. ||
R > 193.) ?
false :
true;
427 bool particleWithinShowerLibrary =
428 aboveThreshold && (isEM || isHad) && (!backward) && inRange && !
dot && angleok && currentLV ==
lvCAST;
431 edm::LogVerbatim(
"ForwardSim") <<
"CastorSD::getFromLibrary: ID= " << theTrack->GetTrackID() <<
" E>E0 "
432 << aboveThreshold <<
" isEM " << isEM <<
" isHad " << isHad <<
" backword " << backward
433 <<
" Ok " << (inRange && !
dot) <<
" angle " << angleok
434 <<
" LV: " << currentLV->GetName() <<
" " << (currentLV ==
lvCAST) <<
" "
435 << particleWithinShowerLibrary <<
" Edep= " << aStep->GetTotalEnergyDeposit();
440 if (!particleWithinShowerLibrary) {
455 edm::LogVerbatim(
"ForwardSim") <<
"CastorSD::getFromLibrary: " <<
hits.getNhit() <<
" hits for " << GetName()
456 <<
" from " << theTrack->GetDefinition()->GetParticleName() <<
" of "
457 << preStepPoint->GetKineticEnergy() /
GeV <<
" GeV and trackID "
458 << theTrack->GetTrackID() <<
" isHad: " << isHad;
462 double E_track = preStepPoint->GetTotalEnergy();
464 double scale = E_track / E_SLhit;
471 for (
unsigned int i = 0;
i <
hits.getNhit(); ++
i) {
473 double nPhotoElectrons =
hits.getNphotons(
i) *
scale;
487 unsigned int unitID =
hits.getDetID(
i);