15 #include "CLHEP/Geometry/Point3D.h"
16 #include "CLHEP/Random/RandFlat.h"
17 #include "CLHEP/Random/RandGaussZiggurat.h"
18 #include "CLHEP/Units/SystemOfUnits.h"
23 #include "TProfile2D.h"
44 ATH_MSG_DEBUG(
"SCT_DetailedSurfaceChargesGenerator::initialize()");
58 return StatusCode::FAILURE;
65 return StatusCode::FAILURE;
71 return StatusCode::FAILURE;
77 return StatusCode::FAILURE;
83 return StatusCode::FAILURE;
89 return StatusCode::FAILURE;
112 ATH_MSG_INFO(
"\tsurface drift still not on, wrong params");
117 ATH_MSG_FATAL(
"\tCannot set both FixedTime and SubtractTime options!");
118 ATH_MSG_INFO(
"\tMake sure the two flags are not set simultaneously in jo");
119 return StatusCode::FAILURE;
132 ATH_MSG_INFO(
"\tDetailedSurfaceChargesGenerator copied");
139 return StatusCode::SUCCESS;
146 ATH_MSG_DEBUG(
"SCT_DetailedSurfaceChargesGenerator::finalize()");
147 return StatusCode::SUCCESS;
154 const double sensorThickness{element->
thickness()};
155 if ((zhit<0.0) or (zhit>sensorThickness)) {
163 const double denominator{vdepl+vbias-(2.0*zhit*vdepl/sensorThickness)};
167 ATH_MSG_ERROR(
"DriftTime: negative argument X for log(X) " << zhit);
187 const float t{this->
DriftTime(zhit, element, ctx)};
189 const float diffusionSigma{
static_cast<float>(sqrt(2.*
m_siPropertiesTool->getSiProperties(hashId, ctx).holeDiffusionConstant()*
t))};
190 return diffusionSigma;
200 const double sensorThickness{element->
thickness()};
201 return this->
DriftTime(sensorThickness, element, ctx);
213 const double sensorThickness{element->
thickness()};
228 float surfaceDriftTime{0.};
236 return surfaceDriftTime;
250 ATH_MSG_VERBOSE(
"SCT_DetailedSurfaceChargesGenerator::process starts");
251 const float p_eventTime{phit.
eventTime()};
252 const unsigned short p_eventId{phit.
eventId()};
253 processSiHit(element, *phit, inserter, p_eventTime, p_eventId, rndmEngine, ctx);
261 if (p_design==
nullptr) {
262 ATH_MSG_ERROR(
"SCT_DetailedSurfaceChargesGenerator::process can not get " << p_design);
270 float timeOfFlight{p_eventTime +
hitTime(phit)};
283 const double sensorThickness{p_design->thickness()};
296 double LargeStep{sqrt(cEta*cEta+cPhi*cPhi+cDep*cDep)};
307 double StepX{cEta/numberOfSteps};
308 double StepY{cPhi/numberOfSteps};
309 double StepZ{cDep/numberOfSteps};
327 for (
int istep{0}; istep<numberOfSteps; ++istep) {
329 double z1{zhit+StepZ*dstep};
332 double zReadout{0.5*sensorThickness - p_design->readoutSide() * z1};
334 float tdrift{
DriftTime(zReadout, element, ctx)};
335 if (tdrift>-2.0000002 and tdrift<-1.9999998) {
336 ATH_MSG_DEBUG(
"Checking for rounding errors in compression");
337 if ((std::abs(z1)-0.5*sensorThickness)<0.000010) {
338 ATH_MSG_DEBUG(
"Rounding error found attempting to correct it. z1 = " << std::fixed << std::setprecision(8) << z1);
340 z1= 0.0000005-0.5*sensorThickness;
342 z1 = 0.5*sensorThickness-0.0000005;
344 zReadout = 0.5*sensorThickness - p_design->readoutSide() * z1;
345 tdrift=
DriftTime(zReadout, element, ctx);
346 if (tdrift>-2.0000002 and tdrift<-1.9999998) {
349 ATH_MSG_DEBUG(
"Correction Successful! z1 = " << std::fixed << std::setprecision(8) << z1 <<
", zReadout = " << zReadout <<
", tdrift = " << tdrift);
352 ATH_MSG_DEBUG(
"No rounding error found. Making no correction.");
356 double x1{xhit+StepX*dstep};
357 double y1{yhit+StepY*dstep};
361 y1 += tanLorentz*zReadout;
364 float rx{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
365 double xd{
x1+diffusionSigma*rx};
366 float ry{CLHEP::RandGaussZiggurat::shoot(rndmEngine)};
367 double yd{
y1+diffusionSigma*ry};
370 if (p_design->inActiveArea(position)) {
371 float sdist{
static_cast<float>(p_design->scaledDistanceToNearestDiode(position))};
373 float totaltime{(
m_tfix>-998.) ?
m_tfix.value() : tdrift + timeOfFlight + tsurf};
377 ATH_MSG_INFO(
"Total Time: " << totaltime <<
" tdrift " << tdrift <<
" tsurf " << tsurf <<
" sdist " << sdist <<
" charge: " << q1);
382 ATH_MSG_INFO(std::fixed << std::setprecision(8) <<
"Local position: " << position <<
" of the element is out of active area, charge = " << q1);
391 if (b_design==
nullptr) {
392 ATH_MSG_ERROR(
"SCT_DetailedSurfaceChargesGenerator::process can not get " << b_design);
396 double stripPitch{p_design->stripPitch()};
397 double stripPatternCentre{b_design->phiStripPatternCentre()};
398 double dstrip{(
y1-stripPatternCentre)/stripPitch};
403 dstrip -=
static_cast<double>(
static_cast<int>(dstrip));
405 dstrip -=
static_cast<double>(
static_cast<int>(dstrip)-1);
407 double xtakadist{dstrip*stripPitch};
408 double x0{xtakadist/10.};
409 double y0{(sensorThickness - zReadout)/10.};
412 ATH_MSG_INFO(
"element->isBarrel(): " << element->
isBarrel() <<
" stripPitch: " << stripPitch <<
" stripPatternCentre: " << stripPatternCentre);
413 ATH_MSG_INFO(
"tanLorentz, y1, xtakadist = " << tanLorentz <<
", " <<
y1 <<
", " << xtakadist);
415 double Q_all[5][50]={};
418 holeTransport (x0, y0, Q_all[0], Q_all[1], Q_all[2], Q_all[3], Q_all[4], rndmEngine);
419 electronTransport(x0, y0, Q_all[0], Q_all[1], Q_all[2], Q_all[3], Q_all[4], rndmEngine);
422 double ystrip{
y1 +
strip*stripPitch};
424 if (p_design->inActiveArea(position)) {
425 for (
int itq{0}; itq<50; itq++) {
427 double time{(itq+1)*0.5 + timeOfFlight};
435 ATH_MSG_INFO(std::fixed << std::setprecision(8) <<
"Local position: " << position <<
" of the element is out of active area, charge = " << q1);
440 ATH_MSG_ERROR(
"Fixed charge map model, implementation not finished yet...");
443 if (b_design==
nullptr) {
444 ATH_MSG_ERROR(
"SCT_DetailedSurfaceChargesGenerator::process can not get " << b_design);
449 double stripPitch{p_design->stripPitch()};
450 double stripPatternCentre{b_design->phiStripPatternCentre()};
451 double dstrip{(
y1-stripPatternCentre)/stripPitch};
456 dstrip -=
static_cast<double>(
static_cast<int>(dstrip));
458 dstrip -=
static_cast<double>(
static_cast<int>(dstrip)-1);
460 double xtakadist{dstrip*stripPitch};
461 double x0{xtakadist*1000.};
462 double y0{(sensorThickness - zReadout)*1000.};
466 double ystrip{
y1 +
strip*stripPitch};
468 if (p_design->inActiveArea(position)) {
472 for (
int it{0};
it<50;
it++) {
481 ATH_MSG_INFO(std::fixed << std::setprecision(8) <<
"Local position: " << position <<
" of the element is out of active area, charge = " << q1);
511 double Ex{0.}, Ey{0.};
514 if (Ey > 0.1)
continue;
520 ATH_MSG_INFO(
"------ initialization of e-h transport ------");
530 ATH_MSG_INFO(
"----parameters for old SCT digitization model ----");
531 ATH_MSG_INFO(
"\tmean E field = " << Emean <<
" [KV/cm] ");
535 ATH_MSG_INFO(
"\tdiffusion D = " << diffusion <<
" [ ]");
541 ATH_MSG_INFO(
"-----------------------------------------------");
552 ATH_MSG_INFO(
"----------------------------------------------");
579 for (
int ix{0}; ix<17; ix++) {
580 for (
int iy{0}; iy<115; iy++) {
599 for (
int ix{0}; ix<81; ix++) {
600 for (
int iy{0}; iy<115; iy++) {
617 const double REx{-Ex};
618 const double REy{-Ey};
619 const double E{sqrt(Ex*Ex+Ey*Ey)};
620 const double mu_e{
mud_e(
E)};
621 const double v_e{mu_e *
E};
624 const double secLA{sqrt(1.+tanLA_e*tanLA_e)};
625 const double cosLA{1./secLA};
626 const double sinLA{tanLA_e / secLA};
627 vy_e = v_e * (REy*cosLA - REx*sinLA)/
E;
628 vx_e = v_e * (REx*cosLA + REy*sinLA)/
E;
648 const double E{sqrt(Ex*Ex+Ey*Ey)};
649 const double mu_h{
mud_h(
E)};
650 const double v_h{mu_h *
E};
653 const double secLA{sqrt(1.+tanLA_h*tanLA_h)};
654 const double cosLA{1./secLA};
655 const double sinLA{tanLA_h / secLA};
657 vy_h = v_h * (Ey*cosLA - Ex*sinLA)/
E;
658 vx_h = v_h * (Ex*cosLA + Ey*sinLA)/
E;
673 static const double deltax{0.0005};
674 static const double deltay{0.00025};
678 const double dx{std::abs(
x-xc)};
679 const int ix{
static_cast<int>(
dx / deltax)};
680 if (ix > 79)
return 0.;
681 const int iy{
static_cast<int>(
y / deltay)};
682 const double fx{(
dx - ix*deltax) / deltax};
683 const double fy{(
y - iy*deltay) / deltay};
689 ATH_MSG_DEBUG(
"induced: x,y,iy=" <<
x <<
" " <<
y <<
" " << iy <<
" istrip,xc,dx,ix="
690 << istrip <<
" " << xc <<
" " <<
dx <<
" " <<ix <<
" fx,fy=" << fx <<
" " << fy <<
", P=" <<
P);
706 static const double deltay{0.00025}, deltax{0.00025};
731 int iy{
static_cast<int>(
y/deltay)};
732 double fy{(
y-iy*deltay) / deltay};
738 int ix{
static_cast<int>(xxx/deltax)};
739 double fx{(xxx - ix*deltax) / deltax};
741 ATH_MSG_DEBUG(
"x,y,ix,iy,fx,fy,xx,xxx= " <<
x <<
" " <<
y <<
" " << ix <<
" " << iy <<
" " << fx <<
" " << fy <<
" " << xx <<
" " << xxx);
745 double Ex00{0.}, Ex10{0.}, Ex01{0.}, Ex11{0.};
746 double Ey00{0.}, Ey10{0.}, Ey01{0.}, Ey11{0.};
757 ATH_MSG_WARNING(
"Only +150 V bias voltage case is available. However, " << iVB <<
" V bias voltage is used. Electoric field is not extracted!!!");
761 Ex = Ex00*(1.-fx)*(1.-fy) + Ex10*fx*(1.-fy) + Ex01*(1.-fx)*fy + Ex11*fx*fy;
763 ATH_MSG_DEBUG(
"xx, xhalfpitch = " << xx <<
" " << xhalfpitch);
765 if (xx > xhalfpitch) Ex = -Ex;
766 Ey = Ey00*(1.-fx)*(1.-fy) + Ey10*fx*(1.-fy) + Ey01*(1.-fx)*fy + Ey11*fx*fy;
801 double t_current{0.};
806 static const double betaHoles{5.1E-16};
807 double trappingHoles{1./(
m_Fluence*betaHoles)};
808 double u{CLHEP::RandFlat::shoot(0., 1.)};
809 double drift_time{-TMath::Log(
u)*trappingHoles};
811 for (
int istrip{-2}; istrip<=2; istrip++) {
812 qstrip[istrip+2] =
induced(istrip,
x,
y);
815 ATH_MSG_DEBUG(
"h:qstrip=" << qstrip[0] <<
" " << qstrip[1] <<
" " << qstrip[2] <<
" " << qstrip[3] <<
" " << qstrip[4]);
818 if (not isInBulk)
break;
819 if (not
hole(
x,
y, vx, vy, D))
break;
832 if (drift_time < t_current)
break;
836 double diffusion{sqrt(2.*D*
dt*1.
E-9)};
837 y += diffusion * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
838 x += diffusion * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
848 for (
int istrip{-2}; istrip<=2; istrip++) {
851 double dq{qnew - qstrip[jj]};
856 int jt{
static_cast<int>((t_current+0.001) / 0.50)};
859 case -2: Q_m2[jt] +=
dq;
break;
860 case -1: Q_m1[jt] +=
dq;
break;
861 case 0: Q_00[jt] +=
dq;
break;
862 case +1: Q_p1[jt] +=
dq;
break;
863 case +2: Q_p2[jt] +=
dq;
break;
869 ATH_MSG_DEBUG(
"h:qstrip=" << qstrip[0] <<
" " << qstrip[1] <<
" " << qstrip[2] <<
" " << qstrip[3] <<
" " << qstrip[4]);
873 ATH_MSG_DEBUG(
"holeTransport : x,y=(" << x0*1.
e4<<
"," <<y0*1.
e4<<
")->(" <<
x*1.
e4<<
"," <<
y*1.
e4 <<
") t=" << t_current);
897 double t_current{0.};
902 static const double betaElectrons{3.1E-16};
903 const double trappingElectrons{1./(
m_Fluence*betaElectrons)};
904 const double u{CLHEP::RandFlat::shoot(0., 1.)};
905 const double drift_time{-TMath::Log(
u)*trappingElectrons};
907 for (
int istrip{-2}; istrip<=2; istrip++) {
908 qstrip[istrip+2] = -
induced(istrip,
x,
y);
913 if (not isInBulk)
break;
927 if (drift_time < t_current)
break;
931 double diffusion{sqrt(2.* D *
dt*1.
E-9)};
932 y += diffusion * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
933 x += diffusion * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
939 for (
int istrip{-2}; istrip<=2; istrip++) {
942 double dq{qnew - qstrip[jj]};
945 if (istrip==0)
ATH_MSG_DEBUG(
"e:t,x,y=" << t_current <<
" " <<
x*1
e4 <<
" " <<
y*1
e4 <<
" dq[0]=" <<
dq);
947 int jt{
static_cast<int>((t_current + 0.001) / 0.50)};
950 case -2: Q_m2[jt] +=
dq;
break;
951 case -1: Q_m1[jt] +=
dq;
break;
952 case 0: Q_00[jt] +=
dq;
break;
953 case +1: Q_p1[jt] +=
dq;
break;
954 case +2: Q_p2[jt] +=
dq;
break;
961 ATH_MSG_DEBUG(
"elecTransport : x,y=(" << x0*1.
e4 <<
"," << y0*1.
e4 <<
")->(" <<
x*1.
e4 <<
"," <<
y*1.
e4 <<
") t=" << t_current);
973 static const double dt{0.5};
977 if (strip<-2 or strip>2)
return charge;
983 ix =
static_cast<int>(fx);
987 iy =
static_cast<int>(fy);
1002 it =
static_cast<int>(
ft);
1025 const double charge0{p000*(1.-fx)*(1.-fy) + p010*(1.-fx)*fy + p100*fx*(1.-fy) + p110*fx*fy};
1026 const double charge1{p001*(1.-fx)*(1.-fy) + p011*(1.-fx)*fy + p101*fx*(1.-fy) + p111*fx*fy};