26 #include "CLHEP/Random/RandExponential.h"
27 #include "CLHEP/Random/RandFlat.h"
59 :
me(
"CSCGasCollisions"),
60 gasDensity(2.1416
e-03),
65 theGammaBins(N_GAMMA, 0.),
66 theEnergyBins(N_ENERGY, 0.),
67 theCollisionTable(N_ENTRIES, 0.),
69 theParticleDataTable(nullptr),
70 saveGasCollisions_(
false),
71 dumpGasCollisions_(
false) {
77 <<
" keV (for higher elosses, hits should have been simulated.)";
107 string colliFile =
"SimMuon/CSCDigitizer/data/collisions.dat";
111 ifstream
fin{
f1.fullPath()};
114 string errorMessage =
"Cannot open input file " +
f1.fullPath();
120 fin.seekg(0, ios::beg);
139 LogTrace(
me) <<
"Reading collisions table \n";
152 std::vector<LocalPoint> &positions,
154 CLHEP::HepRandomEngine *engine) {
155 const float epsilonL = 0.01;
163 double mom = simhit.
pabs();
168 double mass = 0.105658;
169 if (particle ==
nullptr) {
172 mass = particle->mass();
180 if (gapSize <= epsilonL) {
181 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! simhit entry and exit are too close - "
185 <<
" : momentum = " << simhit.
pabs()
186 <<
" GeV/c : energy loss = " << simhit.
energyLoss() * 1.E06 <<
" keV"
187 <<
", gapSize = " << gapSize <<
" cm (< epsilonL = " << epsilonL <<
" cm)";
193 std::vector<float> collisions(
N_ENERGY);
198 double anmax =
exp(collisions[0]);
199 double amu = anmax - anmin;
201 LogTrace(
me) <<
"collisions extremes = " << collisions[
N_ENERGY - 1] <<
", " << collisions[0] <<
"\n"
202 <<
"anmin = " << anmin <<
", anmax = " << anmax <<
"\n"
203 <<
"amu = " << amu <<
"\n";
206 double sum_steps = 0.;
214 while (sum_steps < gapSize) {
218 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! n_try = " << n_try
219 <<
" is > MAX_STEPS = " << maxst <<
" - skipping simhit:"
222 <<
" : momentum = " << simhit.
pabs()
223 <<
" GeV/c : energy loss = " << simhit.
energyLoss() * 1.E06 <<
" keV"
224 <<
"\n gapSize = " << gapSize <<
" cm, last step = " <<
step
225 <<
" cm, sum_steps = " << sum_steps <<
" cm, n_steps = " << n_steps;
229 if (sum_steps +
step > gapSize)
236 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! eloss = " << eloss <<
" eV is too large (> "
237 <<
deCut <<
" eV) - trying another collision";
246 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! " << n_steps
247 <<
" is too many steps - skipping simhit:"
250 <<
" : momentum = " << simhit.
pabs()
251 <<
" GeV/c : energy loss = " << simhit.
energyLoss() * 1.E06 <<
" keV"
252 <<
"\ngapSize=" << gapSize <<
" cm, last step=" <<
step
253 <<
" cm, sum_steps=" << sum_steps <<
" cm";
256 LogTrace(
me) <<
"sum_steps = " << sum_steps <<
" cm , dedx = " << dedx <<
" eV";
262 ionize(eloss, layerLocalPoint);
264 LogTrace(
me) <<
"Energy available = " << eloss <<
" eV is too low for ionization (< eion = " <<
eion <<
" eV)";
280 double step = (CLHEP::RandExponential::shoot(engine)) / avCollisions;
297 const std::vector<float> &collisions,
298 CLHEP::HepRandomEngine *engine)
const {
300 float lnColl =
log(CLHEP::RandFlat::shoot(engine, anmin, anmax));
309 float eloss =
exp(lnE);
321 while (energyAvailable >
eion) {
345 int nelec = static_cast<int>(energyAvailable /
ework);
346 LogTrace(
me) <<
"short-range delta energy in = " << energyAvailable <<
" eV";
348 energyAvailable -= nelec *
ework;
350 if (energyAvailable >
eion) {
352 energyAvailable -=
eion;
354 LogTrace(
me) <<
"short-range delta energy out = " << energyAvailable <<
" eV, nelec = " << nelec;
364 bool new_range =
false;
365 while (!new_range && (energyAvailable >
ework)) {
366 energyAvailable -=
ework;
367 while (energyAvailable >
eion) {
368 double range2 = 0.5 * 0.71 /
gasDensity *
pow(1.E-6 * energyAvailable, 1.72);
369 double drange =
range - range2;
370 LogTrace(
me) <<
" energy left = " << energyAvailable <<
" eV, range2 = " << range2
371 <<
" cm, drange = " << drange <<
" cm";
378 LogTrace(
me) <<
"reset range to range2 = " <<
range <<
" from startHere = " << startHere <<
" and iterate";
388 if (energyAvailable >
eion) {
389 energyAvailable -=
ework;
407 <<
"\nAFTER CROSSING GAP";
426 size_t nsteps = n_steps;
427 size_t mstep =
steps.size() - 1;
429 if ((nsteps !=
MAX_STEPS) && (nsteps != mstep)) {
430 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! no. of steps = " << nsteps
431 <<
" .ne. steps.size()-1 = " << mstep;
433 size_t meloss = elosses.size();
435 if (nsteps != meloss) {
436 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! no. of steps = " << nsteps
437 <<
" .ne. no. of elosses = " << meloss;
439 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] # / length of step / energy loss per collision:";
440 for (
size_t i = 0;
i != nsteps; ++
i) {
445 size_t mclus = ion_clusters.size();
448 if (mclus != melec) {
449 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] WARNING! size of cluster vector = " << mclus
450 <<
" .ne. size of electrons vector = " << melec;
453 "cluster / electrons per cluster: ";
454 for (
size_t i = 0;
i != mclus; ++
i) {
459 int n_ic = count_if(elosses.begin(), elosses.end(), [&](
auto c) {
return c > this->
eion; });
461 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] total no. of collision steps = " << n_steps;
462 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] total sum of steps = " << sum_steps <<
" cm";
464 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] average step length = " << sum_steps /
float(nsteps)
466 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] total energy loss across gap = " << dedx
467 <<
" eV = " << dedx / 1000. <<
" keV";
468 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] no. of primary ionizing collisions across gap = "
469 "no. with eloss > eion = "
470 <<
eion <<
" eV = " << n_ic;
472 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] average energy loss/collision = " << dedx /
float(nsteps)
477 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] TROUBLE! There is a cluster with 0 electrons.";
485 <<
" : momentum = " << simhit.
pabs()
486 <<
" GeV/c : energy loss = " << simhit.
energyLoss() * 1.E06 <<
" keV";
489 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisions] SUMMARY: ionization"
490 <<
" : steps= " << nsteps <<
" : sum(steps)= " << sum_steps
491 <<
" cm : <step>= " << sum_steps /
float(nsteps) <<
" cm"
492 <<
" : ionizing= " << n_ic <<
" : ionclus= " << mclus <<
" : total e= " << n_e
493 <<
" : <dedx/step>= " << dedx /
float(nsteps)
494 <<
" eV : <e/ionclus>= " <<
float(n_e) /
float(mclus)
495 <<
" : dedx= " << dedx / 1000. <<
" keV";
497 edm::LogVerbatim(
"CSCDigitizer") <<
"[CSCGasCollisons] ERROR? no collision steps!";
524 std::vector<float>::const_iterator it =
find(collisions.begin(), collisions.end(), lnCollisions);
526 if (it != collisions.end()) {
528 std::vector<float>::difference_type ihi = it - collisions.begin();
530 <<
" for lnCollisions = " << lnCollisions;
534 std::vector<float>::const_iterator loside =
535 find_if(collisions.begin(), collisions.end(), [&lnCollisions](
auto c) {
return c < lnCollisions; });
536 std::vector<float>::difference_type ilo = loside - collisions.begin();
538 LogTrace(
me) <<
": using energy bin " << ilo - 1 <<
" and " << ilo;
539 lnE =
theEnergyBins[ilo - 1] + (lnCollisions - collisions[ilo - 1]) *
541 (collisions[ilo] - collisions[ilo - 1]);
552 std::vector<float>::const_iterator bigger =
558 <<
" for logGamma = " << logGamma;
563 std::vector<float>::difference_type ihi = bigger -
theGammaBins.begin();
565 double dlg2 = *bigger--;
568 double dlg1 = *bigger;
569 double dlg = (logGamma - dlg1) / (dlg2 - dlg1);
570 double omdlg = 1. - dlg;
576 <<
" for logGamma = " << logGamma;