13 #include "G4LogicalVolume.hh"
14 #include "G4LogicalVolumeStore.hh"
15 #include "G4Poisson.hh"
18 #include "G4VProcess.hh"
29 #include "G4PhysicalConstants.hh"
30 #include "G4SystemOfUnits.hh"
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_
69 double edep = aStep->GetTotalEnergyDeposit() *
weight;
76 edm::LogVerbatim(
"EcalSim") <<
"DreamSD:: " << aStep->GetPreStepPoint()->GetPhysicalVolume()->GetName() <<
" Side "
77 <<
side_ <<
" Light Collection Efficiency " <<
weight <<
" Weighted Energy Deposit "
86 DimensionMap::const_iterator ite =
xtalLMap_.begin();
87 const G4LogicalVolume *lv = (ite->first);
88 G4Material *material = lv->GetMaterial();
89 edm::LogVerbatim(
"EcalSim") <<
"DreamSD::initRun: Initializes for material " << material->GetName() <<
" in "
94 edm::LogWarning(
"EcalSim") <<
"Couldn't retrieve material properties table\n Material = " << material->GetName();
102 const G4VTouchable *touch = aStep->GetPreStepPoint()->GetTouchable();
103 uint32_t
id = (touch->GetReplicaNumber(1)) * 10 + (touch->GetReplicaNumber(0));
129 std::sort(paras.begin(), paras.end());
147 <<
" Parameter 0 = " << paras[0];
150 std::sort(paras.begin(), paras.end());
158 edm::LogVerbatim(
"EcalSim") <<
"DreamSD: Length Table for ReadOutName = " <<
sd <<
":";
160 DimensionMap::const_iterator ite =
xtalLMap_.begin();
163 G4String
name =
"Unknown";
164 if (ite->first !=
nullptr)
165 name = (ite->first)->GetName();
167 edm::LogVerbatim(
"EcalSim") <<
" " <<
i <<
" " << ite->first <<
" " <<
name <<
" L = " << ite->second.first
168 <<
" W = " << ite->second.second;
175 const G4LogicalVolumeStore *lvs = G4LogicalVolumeStore::GetInstance();
176 std::vector<G4LogicalVolume *>::const_iterator lvcite;
177 G4LogicalVolume *lv =
nullptr;
178 for (lvcite = lvs->begin(); lvcite != lvs->end(); lvcite++) {
179 if ((*lvcite)->GetName() == static_cast<G4String>(
name)) {
185 edm::LogVerbatim(
"EcalSim") <<
"DreamSD::fillMap (for " <<
name <<
" Logical Volume " << lv <<
" Length " << length
186 <<
" Width " <<
width;
193 auto const stepPoint = aStep->GetPreStepPoint();
194 auto const lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
195 G4String nameVolume = lv->GetName();
198 G4ThreeVector localPoint =
setToLocal(stepPoint->GetPosition(), stepPoint->GetTouchable());
200 double localz = localPoint.x();
201 double dapd = 0.5 * crlength -
flag * localz;
202 if (dapd >= -0.1 || dapd <= crlength + 0.1) {
206 edm::LogWarning(
"EcalSim") <<
"DreamSD: light coll curve : wrong distance "
207 <<
"to APD " << dapd <<
" crlength = " << crlength <<
" crystal name = " << nameVolume
208 <<
" z of localPoint = " << localz <<
" take weight = " <<
weight;
211 edm::LogVerbatim(
"EcalSim") <<
"DreamSD, light coll curve : " << dapd <<
" crlength = " << crlength
212 <<
" crystal name = " << nameVolume <<
" z of localPoint = " << localz
213 <<
" take weight = " <<
weight;
221 DimensionMap::const_iterator ite =
xtalLMap_.find(lv);
223 length = ite->second.first;
230 DimensionMap::const_iterator ite =
xtalLMap_.find(lv);
232 width = ite->second.second;
240 double cherenkovEnergy = 0;
242 return cherenkovEnergy;
243 G4Material *material = aStep->GetTrack()->GetMaterial();
247 if (Rindex ==
nullptr) {
249 return cherenkovEnergy;
254 int Rlength = Rindex->GetVectorLength() - 1;
255 double Pmin = Rindex->Energy(0);
256 double Pmax = Rindex->Energy(Rlength);
261 const G4StepPoint *pPreStepPoint = aStep->GetPreStepPoint();
262 const G4StepPoint *pPostStepPoint = aStep->GetPostStepPoint();
263 const G4ThreeVector &x0 = pPreStepPoint->GetPosition();
264 G4ThreeVector p0 = aStep->GetDeltaPosition().unit();
265 const G4DynamicParticle *aParticle = aStep->GetTrack()->GetDynamicParticle();
266 const double charge = aParticle->GetDefinition()->GetPDGCharge();
268 double beta = 0.5 * (pPreStepPoint->GetBeta() + pPostStepPoint->GetBeta());
269 double BetaInverse = 1.0 /
beta;
277 if (meanNumberOfPhotons <= 0.0) {
279 edm::LogVerbatim(
"EcalSim") <<
"Mean number of photons is zero: " << meanNumberOfPhotons <<
", stopping here";
281 return cherenkovEnergy;
285 meanNumberOfPhotons *= aStep->GetStepLength();
288 int numPhotons = static_cast<int>(G4Poisson(meanNumberOfPhotons));
290 if (numPhotons <= 0) {
292 edm::LogVerbatim(
"EcalSim") <<
"Poission number of photons is zero: " << numPhotons <<
", stopping here";
294 return cherenkovEnergy;
299 double maxCos = BetaInverse / (*Rindex)[Rlength];
300 double maxSin2 = (1.0 - maxCos) * (1.0 + maxCos);
303 for (
int iPhoton = 0; iPhoton < numPhotons; ++iPhoton) {
306 double sampledMomentum, sampledRI;
307 double cosTheta, sin2Theta;
311 randomNumber = G4UniformRand();
312 sampledMomentum = Pmin + randomNumber *
dp;
313 sampledRI = Rindex->Value(sampledMomentum);
314 cosTheta = BetaInverse / sampledRI;
316 sin2Theta = (1.0 - cosTheta) * (1.0 + cosTheta);
317 randomNumber = G4UniformRand();
319 }
while (randomNumber * maxSin2 > sin2Theta);
323 randomNumber = G4UniformRand();
325 double phi = twopi * randomNumber;
332 double sinTheta =
sqrt(sin2Theta);
333 double px = sinTheta * cosPhi;
334 double py = sinTheta * sinPhi;
335 double pz = cosTheta;
336 G4ThreeVector photonDirection(
px,
py, pz);
339 photonDirection.rotateUz(p0);
342 randomNumber = G4UniformRand();
343 G4ThreeVector photonPosition = x0 + randomNumber * aStep->GetDeltaPosition();
344 G4ThreeVector photonMomentum = sampledMomentum * photonDirection;
349 return cherenkovEnergy;
357 const G4Material *aMaterial,
358 const G4MaterialPropertyVector *Rindex) {
359 const double rFact = 369.81 / (eV * cm);
364 double BetaInverse = 1. /
beta;
371 int Rlength = Rindex->GetVectorLength() - 1;
372 double Pmin = Rindex->Energy(0);
373 double Pmax = Rindex->Energy(Rlength);
376 double nMin = (*Rindex)[0];
377 double nMax = (*Rindex)[Rlength];
382 double dp = 0., ge = 0., CAImin = 0.;
385 if (
nMax < BetaInverse) {
389 else if (
nMin > BetaInverse) {
399 Pmin = Rindex->Value(BetaInverse);
404 ge = CAImax - CAImin;
408 double numPhotons = rFact *
charge / eplus *
charge / eplus * (
dp - ge * BetaInverse * BetaInverse);
411 edm::LogVerbatim(
"EcalSim") <<
"@SUB=getAverageNumberOfPhotons\nCAImin = " << CAImin <<
"\nCAImax = " << CAImax
412 <<
"\ndp = " <<
dp <<
", ge = " << ge <<
"\nnumPhotons = " << numPhotons;
422 if (pbWO2Name != aMaterial->GetName()) {
424 <<
"expecting " << pbWO2Name <<
", got " << aMaterial->GetName();
428 G4MaterialPropertiesTable *
table =
new G4MaterialPropertiesTable();
432 const int nEntries = 14;
433 double PhotonEnergy[nEntries] = {1.7712 * eV,
447 double RefractiveIndex[nEntries] = {2.17728,
462 table->AddProperty(
"RINDEX", PhotonEnergy, RefractiveIndex, nEntries);
463 aMaterial->SetMaterialPropertiesTable(
table);
470 double currentRI = RefractiveIndex[
index];
471 double currentPM = PhotonEnergy[
index];
472 double currentCAI = 0.0;
474 double prevPM = currentPM;
475 double prevCAI = currentCAI;
476 double prevRI = currentRI;
477 while (++
index < nEntries) {
478 currentRI = RefractiveIndex[
index];
479 currentPM = PhotonEnergy[
index];
480 currentCAI = 0.5 * (1.0 / (prevRI * prevRI) + 1.0 / (currentRI * currentRI));
481 currentCAI = prevCAI + (currentPM - prevPM) * currentCAI;
486 prevCAI = currentCAI;
491 edm::LogVerbatim(
"EcalSim") <<
"Material properties set for " << aMaterial->GetName();
512 G4StepPoint *stepPoint = aStep->GetPreStepPoint();
513 G4LogicalVolume *lv = stepPoint->GetTouchable()->GetVolume(0)->GetLogicalVolume();
514 G4String nameVolume = lv->GetName();
518 double dapd = 0.5 * crlength -
x.x();
519 double y =
p.y() /
p.x() * dapd;
522 edm::LogVerbatim(
"EcalSim") <<
"Distance to APD: " << dapd <<
" - y at APD: " <<
y;
529 double waveLength =
p.mag() * 1.239e8;