15 #include "G4LogicalVolume.hh"
16 #include "G4LogicalVolumeStore.hh"
17 #include "G4Poisson.hh"
20 #include "G4VProcess.hh"
31 #include "G4PhysicalConstants.hh"
32 #include "G4SystemOfUnits.hh"
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_
71 double edep = aStep->GetTotalEnergyDeposit() *
weight;
78 edm::LogVerbatim(
"EcalSim") <<
"DreamSD:: " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() <<
" Side "
79 <<
side_ <<
" Light Collection Efficiency " <<
weight <<
" Weighted Energy Deposit "
88 DimensionMap::const_iterator ite =
xtalLMap_.begin();
89 const G4LogicalVolume *lv = (ite->first);
90 G4Material *material = lv->GetMaterial();
91 edm::LogVerbatim(
"EcalSim") <<
"DreamSD::initRun: Initializes for material " << material->GetName() <<
" in "
96 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n Material = " << material->GetName();
104 const G4VTouchable *touch = aStep->GetPreStepPoint()->GetTouchable();
105 uint32_t
id = (touch->GetReplicaNumber(1)) * 10 + (touch->GetReplicaNumber(0));
131 std::sort(paras.begin(), paras.end());
149 <<
" Parameter 0 = " << paras[0];
152 std::sort(paras.begin(), paras.end());
160 edm::LogVerbatim(
"EcalSim") <<
"DreamSD: Length Table for ReadOutName = " <<
sd <<
":";
162 DimensionMap::const_iterator ite =
xtalLMap_.begin();
165 G4String
name =
"Unknown";
166 if (ite->first !=
nullptr)
167 name = (ite->first)->GetName();
169 edm::LogVerbatim(
"EcalSim") <<
" " <<
i <<
" " << ite->first <<
" " <<
name <<
" L = " << ite->second.first
170 <<
" W = " << ite->second.second;
177 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
178 std::vector<G4LogicalVolume *>::const_iterator lvcite;
179 G4LogicalVolume *lv =
nullptr;
180 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
181 if ((*lvcite)->GetName() == static_cast<G4String>(
name)) {
187 edm::LogVerbatim(
"EcalSim") <<
"DreamSD::fillMap (for " <<
name <<
" Logical Volume " << lv <<
" Length " << length
188 <<
" Width " <<
width;
195 auto const stepPoint = aStep->GetPreStepPoint();
196 auto const lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
197 G4String nameVolume = lv->GetName();
200 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(), stepPoint->GetTouchable());
202 double localz = localPoint.x();
203 double dapd = 0.5 * crlength -
flag * localz;
204 if (dapd >= -0.1 || dapd <= crlength + 0.1) {
208 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance "
209 <<
"to APD " << dapd <<
" crlength = " << crlength <<
" crystal name = " << nameVolume
210 <<
" z of localPoint = " << localz <<
" take weight = " <<
weight;
213 edm::LogVerbatim(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd <<
" crlength = " << crlength
214 <<
" crystal name = " << nameVolume <<
" z of localPoint = " << localz
215 <<
" take weight = " <<
weight;
223 DimensionMap::const_iterator ite =
xtalLMap_.find(lv);
225 length = ite->second.first;
232 DimensionMap::const_iterator ite =
xtalLMap_.find(lv);
234 width = ite->second.second;
242 double cherenkovEnergy = 0;
244 return cherenkovEnergy;
245 G4Material *material = aStep->GetTrack()->GetMaterial();
249 if (Rindex ==
nullptr) {
251 return cherenkovEnergy;
256 int Rlength = Rindex->GetVectorLength() - 1;
257 double Pmin = Rindex->Energy(0);
258 double Pmax = Rindex->Energy(Rlength);
263 const G4StepPoint *pPreStepPoint = aStep->GetPreStepPoint();
264 const G4StepPoint *pPostStepPoint = aStep->GetPostStepPoint();
265 const G4ThreeVector &x0 = pPreStepPoint->GetPosition();
266 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
267 const G4DynamicParticle *aParticle = aStep->GetTrack()->GetDynamicParticle();
268 const double charge = aParticle->GetDefinition()->GetPDGCharge();
270 double beta = 0.5 * (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta());
271 double BetaInverse = 1.0 /
beta;
279 if (meanNumberOfPhotons <= 0.0) {
281 edm::LogVerbatim(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons <<
", stopping here";
283 return cherenkovEnergy;
287 meanNumberOfPhotons *= aStep->GetStepLength();
290 int numPhotons = static_cast<int>(G4Poisson(meanNumberOfPhotons));
292 if (numPhotons <= 0) {
294 edm::LogVerbatim(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons <<
", stopping here";
296 return cherenkovEnergy;
301 double maxCos = BetaInverse / (*Rindex)[Rlength];
302 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
305 for (
int iPhoton = 0; iPhoton < numPhotons; ++iPhoton) {
308 double sampledMomentum, sampledRI;
309 double cosTheta, sin2Theta;
313 randomNumber = G4UniformRand();
314 sampledMomentum = Pmin + randomNumber *
dp;
315 sampledRI = Rindex->Value(sampledMomentum);
316 cosTheta = BetaInverse / sampledRI;
318 sin2Theta = (1.0 - cosTheta) * (1.0 + cosTheta);
319 randomNumber = G4UniformRand();
321 }
while (randomNumber * maxSin2 > sin2Theta);
325 randomNumber = G4UniformRand();
327 double phi = twopi * randomNumber;
334 double sinTheta =
sqrt(sin2Theta);
335 double px = sinTheta * cosPhi;
336 double py = sinTheta * sinPhi;
337 double pz = cosTheta;
338 G4ThreeVector photonDirection(
px,
py, pz);
341 photonDirection.rotateUz(p0);
344 randomNumber = G4UniformRand();
345 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
346 G4ThreeVector photonMomentum = sampledMomentum * photonDirection;
351 return cherenkovEnergy;
359 const G4Material *aMaterial,
360 const G4MaterialPropertyVector *Rindex) {
361 const double rFact = 369.81 / (eV * cm);
366 double BetaInverse = 1. /
beta;
373 int Rlength = Rindex->GetVectorLength() - 1;
374 double Pmin = Rindex->Energy(0);
375 double Pmax = Rindex->Energy(Rlength);
378 double nMin = (*Rindex)[0];
379 double nMax = (*Rindex)[Rlength];
384 double dp = 0., ge = 0., CAImin = 0.;
387 if (
nMax < BetaInverse) {
391 else if (
nMin > BetaInverse) {
401 Pmin = Rindex->Value(BetaInverse);
406 ge = CAImax - CAImin;
410 double numPhotons = rFact *
charge / eplus *
charge / eplus * (
dp - ge * BetaInverse * BetaInverse);
413 edm::LogVerbatim(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons\nCAImin = " << CAImin <<
"\nCAImax = " << CAImax
414 <<
"\ndp = " <<
dp <<
", ge = " << ge <<
"\nnumPhotons = " << numPhotons;
424 if (pbWO2Name != aMaterial->GetName()) {
426 <<
"expecting " << pbWO2Name <<
", got " << aMaterial->GetName();
430 G4MaterialPropertiesTable *
table =
new G4MaterialPropertiesTable();
434 const int nEntries = 14;
435 double PhotonEnergy[nEntries] = {1.7712 * eV,
449 double RefractiveIndex[nEntries] = {2.17728,
464 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries);
465 aMaterial->SetMaterialPropertiesTable(
table);
472 double currentRI = RefractiveIndex[
index];
473 double currentPM = PhotonEnergy[
index];
474 double currentCAI = 0.0;
476 double prevPM = currentPM;
477 double prevCAI = currentCAI;
478 double prevRI = currentRI;
479 while (++
index < nEntries) {
480 currentRI = RefractiveIndex[
index];
481 currentPM = PhotonEnergy[
index];
482 currentCAI = 0.5 * (1.0 / (prevRI * prevRI) + 1.0 / (currentRI * currentRI));
483 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
488 prevCAI = currentCAI;
493 edm::LogVerbatim(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
514 G4StepPoint *stepPoint = aStep->GetPreStepPoint();
515 G4LogicalVolume *lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
516 G4String nameVolume = lv->GetName();
520 double dapd = 0.5 * crlength -
x.x();
521 double y =
p.y() /
p.x() * dapd;
524 edm::LogVerbatim(
"EcalSim") <<
"Distance to APD: " << dapd <<
" - y at APD: " <<
y;
531 double waveLength =
p.mag() * 1.239e8;