273 return StatusCode::SUCCESS;
278 if (!Module.
isDBM()) {
279 return StatusCode::SUCCESS;
288 double eta_0 = initialConditions[0];
289 double phi_0 = initialConditions[1];
290 double depth_0 = initialConditions[2];
291 double dEta = initialConditions[3];
292 double dPhi = initialConditions[4];
293 double dDepth = initialConditions[5];
294 double ncharges = initialConditions[6];
295 double iTotalLength = initialConditions[7];
297 const double oneOverNchargesTimes1e6 = 1./(1.E+6 * ncharges);
304 int etaCells = p_design.
columns();
305 int phiCells = p_design.
rows();
307 double eleholePairEnergy = 0;
308 double smearRand = 0;
310 if (Module.
isDBM()) {
311 eleholePairEnergy = 1. / (13. *
CLHEP::eV);
313 smearRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
320 double smearScale = 1. + 0.35 * smearRand;
321 double tanLorentz(0);
325 coLorentz = std::sqrt(1.0 + (tanLorentz*tanLorentz));
333 const double pHitTime =
hitTime(phit);
335 const double halfEtaPitch = 0.5*Module.
etaPitch();
336 const double halfPhiPitch = 0.5*Module.
phiPitch();
342 std::pair<double, double> trappingTimes;
356 std::map<unsigned, std::pair<SiLocalPosition, double>> cachedChargeMap;
357 std::map<unsigned, SiCellId> diodeCellMap;
358 for (
const auto& iHitRecord : trfHitRecord) {
360 double eta_i = eta_0;
361 double phi_i = phi_0;
362 double depth_i = depth_0;
364 eta_i += 1.0 * iHitRecord.first / iTotalLength *
dEta;
365 phi_i += 1.0 * iHitRecord.first / iTotalLength *
dPhi;
366 depth_i += 1.0 * iHitRecord.first / iTotalLength * dDepth;
372 if (!pixel_i.
isValid())
continue;
376 double dist_electrode = 0.5 * sensorThickness - Module.
design().
readoutSide() * depth_i;
377 if (dist_electrode < 0) {
385 const int nnLoop_pixelEtaMin =
std::max(-1, pixel_i.
etaIndex() + 1 - etaCells);
387 const int nnLoop_pixelPhiMin =
std::max(-1, pixel_i.
phiIndex() + 1 - phiCells);
389 std::array<double, 3> sensorScales{};
391 const std::size_t distance_f_e_bin_x = distanceMap_e.
getBinX(dist_electrode);
392 const std::size_t distance_f_h_bin_x = distanceMap_h.
getBinX(dist_electrode);
393 const std::size_t tanLorentz_e_bin_x = lorentzMap_e.
getBinX(dist_electrode);
394 const std::size_t tanLorentz_h_bin_x = lorentzMap_h.
getBinX(dist_electrode);
396 const std::size_t sizePhi = std::abs(nnLoop_pixelPhiMax - nnLoop_pixelPhiMin) + 1;
398 const auto pixel_eta = pixel_i.
etaIndex();
399 const auto pixel_phi = pixel_i.
phiIndex();
401 for (
int p = nnLoop_pixelEtaMin;
p <= nnLoop_pixelEtaMax;
p++) {
402 const std::size_t ieta =
p - nnLoop_pixelEtaMin;
406 if (std::abs(columnWidth - 0.6) < 1
e-9) {
408 }
else if (std::abs(columnWidth - 0.45) < 1
e-9) {
410 }
else if (std::abs(columnWidth - 0.5) < 1
e-9) {
413 sensorScales[ieta] = scale_f;
415 for (
int q = nnLoop_pixelPhiMin;
q <= nnLoop_pixelPhiMax;
q++) {
418 const std::size_t iphi =
q - nnLoop_pixelPhiMin;
419 const std::size_t
index = iphi + ieta*sizePhi;
426 for (
int j = 0; j < ncharges; j++) {
428 double energy_per_step = oneOverNchargesTimes1e6 * iHitRecord.second;
429 double u = CLHEP::RandFlat::shoot(rndmEngine, 0.0, 1.0);
431 const double drifttime_e = (-1.) * (trappingTimes.first) * logf(
u);
432 u = CLHEP::RandFlat::shoot(rndmEngine, 0.0, 1.0);
433 const double drifttime_h = (-1.) * (trappingTimes.second) * logf(
u);
441 const double depth_f_e = distanceMap_e.
getContent(distance_f_e_bin_x, distanceMap_e.
getBinY(drifttime_e));
442 const double depth_f_h = distanceMap_h.
getContent(distance_f_h_bin_x, distanceMap_h.
getBinY(drifttime_h));
443 const double tanLorentz_e = lorentzMap_e.
getContent(tanLorentz_e_bin_x, lorentzMap_e.
getBinY(depth_f_e));
444 const double tanLorentz_h = lorentzMap_h.
getContent(tanLorentz_h_bin_x, lorentzMap_h.
getBinY(depth_f_h));
445 const double dz_e = std::abs(dist_electrode - depth_f_e);
446 const double dz_h = std::abs(depth_f_h - dist_electrode);
447 const double coLorentz_e = std::sqrt(1.0 + (tanLorentz_e*tanLorentz_e));
450 double phiRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
454 const double phi_f_e = phi_i + dz_e * tanLorentz_e + rdif_e * phiRand;
455 double etaRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
456 double eta_f_e = eta_i + rdif_e * etaRand;
458 phiRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
459 const double coLorentz_h = std::sqrt(1.0 + (tanLorentz_h*tanLorentz_h));
461 const double phi_f_h = phi_i + dz_h * tanLorentz_h + rdif_h * phiRand;
462 etaRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
463 double eta_f_h = eta_i + rdif_h * etaRand;
472 const std::size_t ramo_f_e_bin_z = ramoPotentialMap.
getBinZ(1
e3*depth_f_e);
473 const std::size_t ramo_f_h_bin_z = ramoPotentialMap.
getBinZ(1
e3*depth_f_h);
475 const bool isFirstZ_e = ramoPotentialMap.
isFirstZ(1
e3*depth_f_e);
476 const bool isOverflowZ_h = ramoPotentialMap.
isOverflowZ(1
e3*depth_f_h);
478 const double pixelEta_f_e = eta_f_e - centreOfPixel_i.
xEta();
479 const double pixelPhi_f_e = phi_f_e - centreOfPixel_i.
xPhi();
481 const double pixelEta_f_h = eta_f_h - centreOfPixel_i.
xEta();
482 const double pixelPhi_f_h = phi_f_h - centreOfPixel_i.
xPhi();
486 for (
int p = nnLoop_pixelEtaMin;
p <= nnLoop_pixelEtaMax;
p++) {
487 const std::size_t ieta =
p - nnLoop_pixelEtaMin;
489 for (
int q = nnLoop_pixelPhiMin;
q <= nnLoop_pixelPhiMax;
q++) {
493 const std::size_t iphi =
q - nnLoop_pixelPhiMin;
494 const std::size_t
index = iphi + ieta*sizePhi;
498 const double dPhi_nn_centre = centrePixelNN.second - centreOfPixel_i.
xPhi();
499 const double dEta_nn_centre = centrePixelNN.first - centreOfPixel_i.
xEta();
507 const double dEta_f_e = std::abs(pixelEta_f_e - dEta_nn_centre)*sensorScales[ieta];
508 const double dPhi_f_e = std::abs(pixelPhi_f_e - dPhi_nn_centre);
509 const double dEta_f_h = 1
e3*std::abs(pixelEta_f_h - dEta_nn_centre)*sensorScales[ieta];
510 const double dPhi_f_h = 1
e3*std::abs(pixelPhi_f_h - dPhi_nn_centre);
513 double ramo_f_e = 0.0;
514 double ramo_f_h = 0.0;
517 if (dEta_f_e >= halfEtaPitch || dPhi_f_e >= halfPhiPitch) {
530 ramo_f_h = ramoPotentialMap.
getContent(ramoPotentialMap.
getBinX(dPhi_f_h), ramoPotentialMap.
getBinY(dEta_f_h), ramo_f_h_bin_z);
536 const double potentialDiff = ramo_f_e - ramo_f_h;
538 const double induced_charge = potentialDiff * energy_per_step * eleholePairEnergy;
540 unsigned key = (
static_cast<unsigned>(pixel_eta-
p) << 16) |
static_cast<unsigned>(pixel_phi-
q);
541 auto cacheIterator = cachedChargeMap.find(
key);
542 if(cacheIterator == cachedChargeMap.end()) {
543 cachedChargeMap.insert(std::make_pair(
key, std::make_pair(Module.
hitLocalToLocal(centrePixelNN.first, centrePixelNN.second), induced_charge)));
545 cacheIterator->second.second += induced_charge;
552 std::for_each(cachedChargeMap.begin(), cachedChargeMap.end(), [&diodeCellMap, &Module, &chargedDiodes, &pHitTime, &particleLink](
auto& pos_charge_pair){
553 auto& key = pos_charge_pair.first;
554 auto& chargePos = pos_charge_pair.second.first;
555 auto& charge_value = pos_charge_pair.second.second;
557 const SiSurfaceCharge scharge(chargePos, SiCharge(charge_value, pHitTime, SiCharge::track, particleLink));
558 auto diodeIterator = diodeCellMap.find(key);
559 if(diodeIterator == diodeCellMap.end()) diodeIterator = diodeCellMap.insert(std::make_pair(key, Module.cellIdOfPosition(scharge.position()))).first;
560 const SiCellId& thisDiode = diodeIterator->second;
561 if (thisDiode.isValid()) {
562 const SiCharge& charge = scharge.charge();
563 chargedDiodes.add(thisDiode, charge);
577 if (layerToRead > 3) {
585 for (
const auto & iHitRecord : trfHitRecord) {
586 double eta_i = eta_0;
587 double phi_i = phi_0;
588 double depth_i = depth_0;
590 eta_i += 1.0 * iHitRecord.first / iTotalLength *
dEta;
591 phi_i += 1.0 * iHitRecord.first / iTotalLength *
dPhi;
592 depth_i += 1.0 * iHitRecord.first / iTotalLength * dDepth;
600 tanLorentz = lorentzCorrectionHist.
getContent(depthZ);
601 coLorentz = std::sqrt(1.0 + (tanLorentz*tanLorentz));
604 const double chargeCorrection = chargeCorrectionHist.
getContent(depthZ);
607 double nontrappingProbability = 1.0;
608 if (Module.
isDBM()) {
609 nontrappingProbability =
exp(-dist_electrode / collectionDist);
612 for (
int j = 0; j < ncharges; j++) {
614 double energy_per_step = oneOverNchargesTimes1e6 * iHitRecord.second;
619 double phiRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
620 double phi_drifted = phi_i + dist_electrode * tanLorentz + rdif * phiRand;
621 double etaRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
622 double eta_drifted = eta_i + rdif * etaRand;
634 if (Module.
isDBM()) {
635 ed = energy_per_step * eleholePairEnergy * nontrappingProbability * smearScale;
637 ed = energy_per_step * eleholePairEnergy;
640 ed *= chargeCorrection;
654 for (
const auto & iHitRecord : trfHitRecord) {
655 double eta_i = eta_0;
656 double phi_i = phi_0;
657 double depth_i = depth_0;
659 eta_i += 1.0 * iHitRecord.first / iTotalLength *
dEta;
660 phi_i += 1.0 * iHitRecord.first / iTotalLength *
dPhi;
661 depth_i += 1.0 * iHitRecord.first / iTotalLength * dDepth;
666 double dist_electrode = 0.5 * sensorThickness - Module.
design().
readoutSide() * depth_i;
667 if (dist_electrode < 0) {
672 double nontrappingProbability = 1.0;
673 if (Module.
isDBM()) {
674 nontrappingProbability =
exp(-dist_electrode / collectionDist);
677 for (
int j = 0; j < ncharges; j++) {
679 double energy_per_step = oneOverNchargesTimes1e6 * iHitRecord.second;
684 double phiRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
685 double phi_drifted = phi_i + dist_electrode * tanLorentz + rdif * phiRand;
686 double etaRand = CLHEP::RandGaussZiggurat::shoot(rndmEngine);
687 double eta_drifted = eta_i + rdif * etaRand;
699 if (Module.
isDBM()) {
700 ed = energy_per_step * eleholePairEnergy * nontrappingProbability * smearScale;
702 ed = energy_per_step * eleholePairEnergy;
718 return StatusCode::SUCCESS;