14 #include "G4LogicalVolume.hh"
15 #include "G4LogicalVolumeStore.hh"
16 #include "G4Poisson.hh"
19 #include "G4VProcess.hh"
28 #include "G4PhysicalConstants.hh"
29 #include "G4SystemOfUnits.hh"
40 :
CaloSD(
name, clg,
p, manager), cpvDDD_(cpvDDD), cpvDD4Hep_(cpvDD4Hep) {
49 dd4hep_ =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
53 edm::LogVerbatim(
"EcalSim") <<
"Constructing a DreamSD with name " << GetName()
54 <<
"\nDreamSD:: Use of Birks law is set to " <<
useBirk_
55 <<
" with three constants kB = " <<
birk1_ <<
", C1 = " <<
birk2_ <<
", C2 = " <<
birk3_
56 <<
"\n Slope for Light yield is set to " <<
slopeLY_
57 <<
"\n Parameterization of Cherenkov is set to " <<
doCherenkov_
61 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
63 for (
auto lvcite = lvs->begin(); lvcite != lvs->end(); ++lvcite, ++
k)
75 double edep = aStep->GetTotalEnergyDeposit() *
weight;
82 edm::LogVerbatim(
"EcalSim") <<
"DreamSD:: " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() <<
" Side "
83 <<
side_ <<
" Light Collection Efficiency " <<
weight <<
" Weighted Energy Deposit "
92 DimensionMap::const_iterator ite =
xtalLMap_.begin();
93 const G4LogicalVolume *lv = (ite->first);
94 G4Material *material = lv->GetMaterial();
96 edm::LogVerbatim(
"EcalSim") <<
"DreamSD::initRun: Initializes for material " << material->GetName() <<
" in "
102 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n Material = " << material->GetName();
110 const G4VTouchable *touch = aStep->GetPreStepPoint()->GetTouchable();
111 uint32_t
id = (touch->GetReplicaNumber(1)) * 10 + (touch->GetReplicaNumber(0));
145 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
152 <<
" Parameter 0 = " << paras[0];
158 G4LogicalVolume *lv =
nullptr;
159 for (
auto lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
160 if ((*lvcite)->GetName() ==
name) {
172 edm::LogVerbatim(
"EcalSim") <<
"DreamSD: Length Table for ReadOutName = " <<
sd <<
":";
174 DimensionMap::const_iterator ite =
xtalLMap_.begin();
177 G4String
name =
"Unknown";
178 if (ite->first !=
nullptr)
179 name = (ite->first)->GetName();
181 edm::LogVerbatim(
"EcalSim") <<
" " <<
i <<
" " << ite->first <<
" " <<
name <<
" L = " << ite->second.first
182 <<
" W = " << ite->second.second;
189 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
190 edm::LogVerbatim(
"EcalSim") <<
"LV Store with " << lvs->size() <<
" elements";
191 G4LogicalVolume *lv =
nullptr;
192 for (
auto lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
194 if ((*lvcite)->GetName() == static_cast<G4String>(
name)) {
200 edm::LogVerbatim(
"EcalSim") <<
"DreamSD::fillMap (for " <<
name <<
" Logical Volume " << lv <<
" Length " << length
201 <<
" Width " <<
width;
208 auto const stepPoint = aStep->GetPreStepPoint();
209 auto const lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
210 G4String nameVolume = lv->GetName();
213 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(), stepPoint->GetTouchable());
215 double localz = localPoint.x();
216 double dapd = 0.5 * crlength -
flag * localz;
217 if (dapd >= -0.1 || dapd <= crlength + 0.1) {
221 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance "
222 <<
"to APD " << dapd <<
" crlength = " << crlength <<
" crystal name = " << nameVolume
223 <<
" z of localPoint = " << localz <<
" take weight = " <<
weight;
226 edm::LogVerbatim(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd <<
" crlength = " << crlength
227 <<
" crystal name = " << nameVolume <<
" z of localPoint = " << localz
228 <<
" take weight = " <<
weight;
236 DimensionMap::const_iterator ite =
xtalLMap_.find(lv);
238 length = ite->second.first;
245 DimensionMap::const_iterator ite =
xtalLMap_.find(lv);
247 width = ite->second.second;
255 double cherenkovEnergy = 0;
257 return cherenkovEnergy;
258 G4Material *material = aStep->GetTrack()->GetMaterial();
262 if (Rindex ==
nullptr) {
264 return cherenkovEnergy;
269 int Rlength = Rindex->GetVectorLength() - 1;
270 double Pmin = Rindex->Energy(0);
271 double Pmax = Rindex->Energy(Rlength);
276 const G4StepPoint *pPreStepPoint = aStep->GetPreStepPoint();
277 const G4StepPoint *pPostStepPoint = aStep->GetPostStepPoint();
278 const G4ThreeVector &x0 = pPreStepPoint->GetPosition();
279 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
280 const G4DynamicParticle *aParticle = aStep->GetTrack()->GetDynamicParticle();
281 const double charge = aParticle->GetDefinition()->GetPDGCharge();
283 double beta = 0.5 * (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta());
284 double BetaInverse = 1.0 /
beta;
292 if (meanNumberOfPhotons <= 0.0) {
294 edm::LogVerbatim(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons <<
", stopping here";
296 return cherenkovEnergy;
300 meanNumberOfPhotons *= aStep->GetStepLength();
303 int numPhotons = static_cast<int>(G4Poisson(meanNumberOfPhotons));
305 if (numPhotons <= 0) {
307 edm::LogVerbatim(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons <<
", stopping here";
309 return cherenkovEnergy;
314 double maxCos = BetaInverse / (*Rindex)[Rlength];
315 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
318 for (
int iPhoton = 0; iPhoton < numPhotons; ++iPhoton) {
321 double sampledMomentum, sampledRI;
322 double cosTheta, sin2Theta;
326 randomNumber = G4UniformRand();
327 sampledMomentum = Pmin + randomNumber *
dp;
328 sampledRI = Rindex->Value(sampledMomentum);
329 cosTheta = BetaInverse / sampledRI;
331 sin2Theta = (1.0 - cosTheta) * (1.0 + cosTheta);
332 randomNumber = G4UniformRand();
334 }
while (randomNumber * maxSin2 > sin2Theta);
338 randomNumber = G4UniformRand();
340 double phi = twopi * randomNumber;
347 double sinTheta =
sqrt(sin2Theta);
350 double pz = cosTheta;
351 G4ThreeVector photonDirection(
px,
py, pz);
354 photonDirection.rotateUz(p0);
357 randomNumber = G4UniformRand();
358 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
359 G4ThreeVector photonMomentum = sampledMomentum * photonDirection;
364 return cherenkovEnergy;
372 const G4Material *aMaterial,
373 const G4MaterialPropertyVector *Rindex) {
374 const double rFact = 369.81 / (eV * cm);
379 double BetaInverse = 1. /
beta;
386 int Rlength = Rindex->GetVectorLength() - 1;
387 double Pmin = Rindex->Energy(0);
388 double Pmax = Rindex->Energy(Rlength);
391 double nMin = (*Rindex)[0];
392 double nMax = (*Rindex)[Rlength];
397 double dp = 0., ge = 0., CAImin = 0.;
400 if (
nMax < BetaInverse) {
404 else if (
nMin > BetaInverse) {
414 Pmin = Rindex->Value(BetaInverse);
419 ge = CAImax - CAImin;
423 double numPhotons = rFact *
charge / eplus *
charge / eplus * (
dp - ge * BetaInverse * BetaInverse);
425 edm::LogVerbatim(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons\nCAImin = " << CAImin <<
"\nCAImax = " << CAImax
426 <<
"\ndp = " <<
dp <<
", ge = " << ge <<
"\nnumPhotons = " << numPhotons;
435 if (pbWO2Name != aMaterial->GetName()) {
437 <<
"expecting " << pbWO2Name <<
", got " << aMaterial->GetName();
441 G4MaterialPropertiesTable *
table =
new G4MaterialPropertiesTable();
445 const int nEntries = 14;
446 double PhotonEnergy[nEntries] = {1.7712 * eV,
460 double RefractiveIndex[nEntries] = {2.17728,
475 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries);
476 aMaterial->SetMaterialPropertiesTable(
table);
483 double currentRI = RefractiveIndex[
index];
484 double currentPM = PhotonEnergy[
index];
485 double currentCAI = 0.0;
487 double prevPM = currentPM;
488 double prevCAI = currentCAI;
489 double prevRI = currentRI;
490 while (++
index < nEntries) {
491 currentRI = RefractiveIndex[
index];
492 currentPM = PhotonEnergy[
index];
493 currentCAI = 0.5 * (1.0 / (prevRI * prevRI) + 1.0 / (currentRI * currentRI));
494 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
499 prevCAI = currentCAI;
504 edm::LogVerbatim(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
525 G4StepPoint *stepPoint = aStep->GetPreStepPoint();
526 G4LogicalVolume *lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
527 G4String nameVolume = lv->GetName();
531 double dapd = 0.5 * crlength -
x.x();
532 double y =
p.y() /
p.x() * dapd;
535 edm::LogVerbatim(
"EcalSim") <<
"Distance to APD: " << dapd <<
" - y at APD: " <<
y;
542 double waveLength =
p.mag() * 1.239e8;