15 #include "G4LogicalVolume.hh"
16 #include "G4LogicalVolumeStore.hh"
17 #include "G4Poisson.hh"
20 #include "G4VProcess.hh"
31 #include "G4PhysicalConstants.hh"
32 #include "G4SystemOfUnits.hh"
51 dd4hep_ =
p.getParameter<
bool>(
"g4GeometryDD4hepSource");
55 edm::LogVerbatim(
"EcalSim") <<
"Constructing a DreamSD with name " << GetName()
56 <<
"\nDreamSD:: Use of Birks law is set to " <<
useBirk_
57 <<
" with three constants kB = " <<
birk1_ <<
", C1 = " <<
birk2_ <<
", C2 = " <<
birk3_
58 <<
"\n Slope for Light yield is set to " <<
slopeLY_
59 <<
"\n Parameterization of Cherenkov is set to " <<
doCherenkov_
63 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
65 for (
auto lvcite = lvs->begin(); lvcite != lvs->end(); ++lvcite, ++
k)
77 double edep = aStep->GetTotalEnergyDeposit() *
weight;
84 edm::LogVerbatim(
"EcalSim") <<
"DreamSD:: " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() <<
" Side "
85 <<
side_ <<
" Light Collection Efficiency " <<
weight <<
" Weighted Energy Deposit "
94 DimensionMap::const_iterator ite =
xtalLMap_.begin();
95 const G4LogicalVolume *lv = (ite->first);
96 G4Material *material = lv->GetMaterial();
98 edm::LogVerbatim(
"EcalSim") <<
"DreamSD::initRun: Initializes for material " << material->GetName() <<
" in "
104 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n Material = " << material->GetName();
112 const G4VTouchable *touch = aStep->GetPreStepPoint()->GetTouchable();
113 uint32_t
id = (touch->GetReplicaNumber(1)) * 10 + (touch->GetReplicaNumber(0));
151 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
158 <<
" Parameter 0 = " << paras[0];
164 G4LogicalVolume *lv =
nullptr;
165 for (
auto lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++)
166 if ((*lvcite)->GetName() ==
name) {
178 edm::LogVerbatim(
"EcalSim") <<
"DreamSD: Length Table for ReadOutName = " <<
sd <<
":";
180 DimensionMap::const_iterator ite =
xtalLMap_.begin();
183 G4String
name =
"Unknown";
184 if (ite->first !=
nullptr)
185 name = (ite->first)->GetName();
187 edm::LogVerbatim(
"EcalSim") <<
" " <<
i <<
" " << ite->first <<
" " <<
name <<
" L = " << ite->second.first
188 <<
" W = " << ite->second.second;
195 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
196 edm::LogVerbatim(
"EcalSim") <<
"LV Store with " << lvs->size() <<
" elements";
197 G4LogicalVolume *lv =
nullptr;
198 for (
auto lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
200 if ((*lvcite)->GetName() == static_cast<G4String>(
name)) {
206 edm::LogVerbatim(
"EcalSim") <<
"DreamSD::fillMap (for " <<
name <<
" Logical Volume " << lv <<
" Length " << length
207 <<
" Width " <<
width;
214 auto const stepPoint = aStep->GetPreStepPoint();
215 auto const lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
216 G4String nameVolume = lv->GetName();
219 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(), stepPoint->GetTouchable());
221 double localz = localPoint.x();
222 double dapd = 0.5 * crlength -
flag * localz;
223 if (dapd >= -0.1 || dapd <= crlength + 0.1) {
227 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance "
228 <<
"to APD " << dapd <<
" crlength = " << crlength <<
" crystal name = " << nameVolume
229 <<
" z of localPoint = " << localz <<
" take weight = " <<
weight;
232 edm::LogVerbatim(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd <<
" crlength = " << crlength
233 <<
" crystal name = " << nameVolume <<
" z of localPoint = " << localz
234 <<
" take weight = " <<
weight;
242 DimensionMap::const_iterator ite =
xtalLMap_.find(lv);
244 length = ite->second.first;
251 DimensionMap::const_iterator ite =
xtalLMap_.find(lv);
253 width = ite->second.second;
261 double cherenkovEnergy = 0;
263 return cherenkovEnergy;
264 G4Material *material = aStep->GetTrack()->GetMaterial();
268 if (Rindex ==
nullptr) {
270 return cherenkovEnergy;
275 int Rlength = Rindex->GetVectorLength() - 1;
276 double Pmin = Rindex->Energy(0);
277 double Pmax = Rindex->Energy(Rlength);
282 const G4StepPoint *pPreStepPoint = aStep->GetPreStepPoint();
283 const G4StepPoint *pPostStepPoint = aStep->GetPostStepPoint();
284 const G4ThreeVector &x0 = pPreStepPoint->GetPosition();
285 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
286 const G4DynamicParticle *aParticle = aStep->GetTrack()->GetDynamicParticle();
287 const double charge = aParticle->GetDefinition()->GetPDGCharge();
289 double beta = 0.5 * (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta());
290 double BetaInverse = 1.0 /
beta;
298 if (meanNumberOfPhotons <= 0.0) {
300 edm::LogVerbatim(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons <<
", stopping here";
302 return cherenkovEnergy;
306 meanNumberOfPhotons *= aStep->GetStepLength();
309 int numPhotons = static_cast<int>(G4Poisson(meanNumberOfPhotons));
311 if (numPhotons <= 0) {
313 edm::LogVerbatim(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons <<
", stopping here";
315 return cherenkovEnergy;
320 double maxCos = BetaInverse / (*Rindex)[Rlength];
321 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
324 for (
int iPhoton = 0; iPhoton < numPhotons; ++iPhoton) {
327 double sampledMomentum, sampledRI;
328 double cosTheta, sin2Theta;
332 randomNumber = G4UniformRand();
333 sampledMomentum = Pmin + randomNumber *
dp;
334 sampledRI = Rindex->Value(sampledMomentum);
335 cosTheta = BetaInverse / sampledRI;
337 sin2Theta = (1.0 - cosTheta) * (1.0 + cosTheta);
338 randomNumber = G4UniformRand();
340 }
while (randomNumber * maxSin2 > sin2Theta);
344 randomNumber = G4UniformRand();
346 double phi = twopi * randomNumber;
353 double sinTheta =
sqrt(sin2Theta);
354 double px = sinTheta * cosPhi;
355 double py = sinTheta * sinPhi;
356 double pz = cosTheta;
357 G4ThreeVector photonDirection(
px,
py, pz);
360 photonDirection.rotateUz(p0);
363 randomNumber = G4UniformRand();
364 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
365 G4ThreeVector photonMomentum = sampledMomentum * photonDirection;
370 return cherenkovEnergy;
378 const G4Material *aMaterial,
379 const G4MaterialPropertyVector *Rindex) {
380 const double rFact = 369.81 / (eV * cm);
385 double BetaInverse = 1. /
beta;
392 int Rlength = Rindex->GetVectorLength() - 1;
393 double Pmin = Rindex->Energy(0);
394 double Pmax = Rindex->Energy(Rlength);
397 double nMin = (*Rindex)[0];
398 double nMax = (*Rindex)[Rlength];
403 double dp = 0., ge = 0., CAImin = 0.;
406 if (
nMax < BetaInverse) {
410 else if (
nMin > BetaInverse) {
420 Pmin = Rindex->Value(BetaInverse);
425 ge = CAImax - CAImin;
429 double numPhotons = rFact *
charge / eplus *
charge / eplus * (
dp - ge * BetaInverse * BetaInverse);
431 edm::LogVerbatim(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons\nCAImin = " << CAImin <<
"\nCAImax = " << CAImax
432 <<
"\ndp = " <<
dp <<
", ge = " << ge <<
"\nnumPhotons = " << numPhotons;
441 if (pbWO2Name != aMaterial->GetName()) {
443 <<
"expecting " << pbWO2Name <<
", got " << aMaterial->GetName();
447 G4MaterialPropertiesTable *
table =
new G4MaterialPropertiesTable();
451 const int nEntries = 14;
452 double PhotonEnergy[nEntries] = {1.7712 * eV,
466 double RefractiveIndex[nEntries] = {2.17728,
481 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries);
482 aMaterial->SetMaterialPropertiesTable(
table);
489 double currentRI = RefractiveIndex[
index];
490 double currentPM = PhotonEnergy[
index];
491 double currentCAI = 0.0;
493 double prevPM = currentPM;
494 double prevCAI = currentCAI;
495 double prevRI = currentRI;
496 while (++
index < nEntries) {
497 currentRI = RefractiveIndex[
index];
498 currentPM = PhotonEnergy[
index];
499 currentCAI = 0.5 * (1.0 / (prevRI * prevRI) + 1.0 / (currentRI * currentRI));
500 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
505 prevCAI = currentCAI;
510 edm::LogVerbatim(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
531 G4StepPoint *stepPoint = aStep->GetPreStepPoint();
532 G4LogicalVolume *lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
533 G4String nameVolume = lv->GetName();
537 double dapd = 0.5 * crlength -
x.x();
538 double y =
p.y() /
p.x() * dapd;
541 edm::LogVerbatim(
"EcalSim") <<
"Distance to APD: " << dapd <<
" - y at APD: " <<
y;
548 double waveLength =
p.mag() * 1.239e8;