ATLAS Offline Software
SCT_DetailedSurfaceChargesGenerator.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 // Athena
9 #include "InDetSimEvent/SiHit.h" // for SiHit, SiHit::xDep, etc
14 // CLHEP
15 #include "CLHEP/Geometry/Point3D.h"
16 #include "CLHEP/Random/RandFlat.h"
17 #include "CLHEP/Random/RandGaussZiggurat.h" // for RandGaussZiggurat
18 #include "CLHEP/Units/SystemOfUnits.h"
19 
20 // ROOT
21 #include "TMath.h" // for Log
22 #include "TProfile.h" // for TProfile
23 #include "TProfile2D.h" // for TProfile2D
24 
25 // C++ Standard Library
26 #include <cmath>
27 
31 
32 //#define SCT_DIG_DEBUG
33 
34 // constructor
35 SCT_DetailedSurfaceChargesGenerator::SCT_DetailedSurfaceChargesGenerator(const std::string& type, const std::string& name, const IInterface* parent)
36  : base_class(type, name, parent)
37  {
38 }
39 
40 //----------------------------------------------------------------------
41 // Initialize
42 //----------------------------------------------------------------------
44  ATH_MSG_DEBUG("SCT_DetailedSurfaceChargesGenerator::initialize()");
45 
46  //Get ISiPropertiesTool
47  ATH_CHECK(m_siPropertiesTool.retrieve());
48 
49  //Get ISiliconConditionsTool
50  ATH_CHECK(m_siConditionsTool.retrieve());
51 
53  if (m_doHistoTrap) {
54  //-- Get Histogram Service
55  StatusCode rc{m_thistSvc.retrieve()};
56  if (rc.isFailure()) {
57  ATH_MSG_FATAL("Unable to retrieve pointer to THistSvc");
58  return StatusCode::FAILURE;
59  }
60  if (m_doHistoTrap) {
61  m_h_efieldz = new TProfile("efieldz", "", 50, 0., 0.03);
62  rc = m_thistSvc->regHist("/file1/efieldz", m_h_efieldz);
63  if (rc.isFailure()) {
64  ATH_MSG_FATAL("Unable to retrieve pointer to THistSvc");
65  return StatusCode::FAILURE;
66  }
67  m_h_yzRamo = new TProfile2D("yzRamo", "", 60, -0.44, 0.44, 60, 0., m_bulk_depth*10.);
68  rc = m_thistSvc->regHist("/file1/yzRamo", m_h_yzRamo);
69  if (rc.isFailure()) {
70  ATH_MSG_FATAL("Unable to retrieve pointer to THistSvc");
71  return StatusCode::FAILURE;
72  }
73  m_h_yzEfield = new TProfile2D("yzEfield", "", 40, -0.004, 0.004, 60, 0., m_bulk_depth);
74  rc = m_thistSvc->regHist("/file1/yzEfield", m_h_yzEfield);
75  if (rc.isFailure()) {
76  ATH_MSG_FATAL("Unable to retrieve pointer to THistSvc");
77  return StatusCode::FAILURE;
78  }
79  m_h_yEfield = new TProfile2D("yEfield", "", 40, -0.004, 0.004, 60, 0., m_bulk_depth);
80  rc = m_thistSvc->regHist("/file1/yEfield", m_h_yEfield);
81  if (rc.isFailure()) {
82  ATH_MSG_FATAL("Unable to retrieve pointer to THistSvc");
83  return StatusCode::FAILURE;
84  }
85  m_h_zEfield = new TProfile2D("zEfield", "", 40, -0.004, 0.004, 60, 0., m_bulk_depth);
86  rc = m_thistSvc->regHist("/file1/zEfield", m_h_zEfield);
87  if (rc.isFailure()) {
88  ATH_MSG_FATAL("Unable to retrieve pointer to THistSvc");
89  return StatusCode::FAILURE;
90  }
91  }
92  }
94 
96  m_tSurfaceDrift.setValue(m_tSurfaceDrift.value() * CLHEP::ns);
97 
98  // Surface drift time calculation Stuff
101  if ((m_tSurfaceDrift > m_tHalfwayDrift) and
102  (m_tHalfwayDrift>=0.0) and
103  (m_distHalfInterStrip>0.0) and
105  m_SurfaceDriftFlag = true;
106 #ifdef SCT_DIG_DEBUG
107  ATH_MSG_INFO("\tsurface drift ON: surface drift time at d=" << m_distInterStrip << " (mid strip) =" << this->SurfaceDriftTime(m_distInterStrip));
108  ATH_MSG_INFO("\tsurface drift ON: surface drift time at d=" << m_distHalfInterStrip << " (half way) =" << this->SurfaceDriftTime(m_distHalfInterStrip));
109  ATH_MSG_INFO("\tsurface drift ON: surface drift time at d=0.0" << " (strip center) =" << this->SurfaceDriftTime(0.));
110 #endif
111  } else {
112  ATH_MSG_INFO("\tsurface drift still not on, wrong params");
113  }
114 
115  // Make sure these two flags are not set simultaneously
116  if (m_tfix>-998. and m_tsubtract>-998.) {
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;
120  }
121 
123  ATH_MSG_INFO("\tUsing Taka Kondo eh-transport code");
125  }
127  ATH_MSG_INFO("\tUsing Taka Kondo fixed charge map");
128  //init_ChargeMapModel("..."); //PJ to be changed
129  }
130 
131 #ifdef SCT_DIG_DEBUG
132  ATH_MSG_INFO("\tDetailedSurfaceChargesGenerator copied");
133  ATH_MSG_INFO("\tn.charg " << m_numberOfCharges);
134  ATH_MSG_INFO("\tdigi steps " << m_smallStepLength << " mm");
135 #endif
136 
137  ATH_CHECK(m_lorentzAngleTool.retrieve());
138 
139  return StatusCode::SUCCESS;
140 }
141 
142 //----------------------------------------------------------------------
143 // finalize
144 //----------------------------------------------------------------------
146  ATH_MSG_DEBUG("SCT_DetailedSurfaceChargesGenerator::finalize()");
147  return StatusCode::SUCCESS;
148 }
149 
150 //----------------------------------------------------------------------
151 // perpandicular Drift time calculation
152 //----------------------------------------------------------------------
153 float SCT_DetailedSurfaceChargesGenerator::DriftTime(float zhit, const SiDetectorElement* element, const EventContext& ctx) const {
154  const double sensorThickness{element->thickness()};
155  if ((zhit<0.0) or (zhit>sensorThickness)) {
156  ATH_MSG_DEBUG("DriftTime: hit coordinate zhit=" << zhit/CLHEP::micrometer << " out of range");
157  return -2.0;
158  }
159  const IdentifierHash hashId{element->identifyHash()};
160 
161  const double vdepl{m_siConditionsTool->depletionVoltage(hashId, ctx) * CLHEP::volt};
162  const double vbias{m_siConditionsTool->biasVoltage(hashId, ctx) * CLHEP::volt};
163  const double denominator{vdepl+vbias-(2.0*zhit*vdepl/sensorThickness)};
164  if (denominator<=0.0) {
165  if (vbias>=vdepl) { //Should not happen
166  if (not m_isOverlay) {
167  ATH_MSG_ERROR("DriftTime: negative argument X for log(X) " << zhit);
168  }
169  return -1.0;
170  } else {
171  // (vbias<vdepl) can happen with underdepleted sensors, lose charges in that volume
172  // ATH_MSG_DEBUG("DriftTime: ->infinity since vdepl>vbias, zhit: " << zhit );
173  return -10.0;
174  }
175  }
176 
177  float driftTime{static_cast<float>(log((vdepl+vbias)/denominator))};
178  driftTime *= sensorThickness*sensorThickness/(2.0*m_siPropertiesTool->getSiProperties(hashId, ctx).holeDriftMobility()*vdepl);
179  return driftTime;
180 }
181 
182 //----------------------------------------------------------------------
183 // Sigma Diffusion calculation
184 //----------------------------------------------------------------------
185 float SCT_DetailedSurfaceChargesGenerator::DiffusionSigma(float zhit, const SiDetectorElement* element, const EventContext& ctx) const {
186  const IdentifierHash hashId{element->identifyHash()};
187  const float t{this->DriftTime(zhit, element, ctx)}; // in ns
188  if (t>0.0) {
189  const float diffusionSigma{static_cast<float>(sqrt(2.*m_siPropertiesTool->getSiProperties(hashId, ctx).holeDiffusionConstant()*t))}; // in mm
190  return diffusionSigma;
191  }
192  return 0.0;
193 }
194 
195 //----------------------------------------------------------------------
196 // Maximum drift time
197 //----------------------------------------------------------------------
198 float SCT_DetailedSurfaceChargesGenerator::MaxDriftTime(const SiDetectorElement* element, const EventContext& ctx) const {
199  if (element) {
200  const double sensorThickness{element->thickness()};
201  return this->DriftTime(sensorThickness, element, ctx);
202  } else {
203  ATH_MSG_INFO("Error: SiDetectorElement not set!");
204  return 0.;
205  }
206 }
207 
208 //----------------------------------------------------------------------
209 // Maximum Sigma difusion
210 //----------------------------------------------------------------------
211 float SCT_DetailedSurfaceChargesGenerator::MaxDiffusionSigma(const SiDetectorElement* element, const EventContext& ctx) const {
212  if (element) {
213  const double sensorThickness{element->thickness()};
214  return this->DiffusionSigma(sensorThickness, element, ctx);
215  } else {
216  ATH_MSG_INFO("Error: SiDetectorElement not set!");
217  return 0.;
218  }
219 }
220 
221 //----------------------------------------------------------------------
222 // Calculating the surface drift time but I should confess that
223 // I haven't found out yet where the calculation come from
224 //----------------------------------------------------------------------
226  if (m_SurfaceDriftFlag) {
227  if ((ysurf>=0.0) and (ysurf<=m_distInterStrip)) {
228  float surfaceDriftTime{0.};
229  if (ysurf<m_distHalfInterStrip) {
230  const float y{ysurf/m_distHalfInterStrip};
231  surfaceDriftTime = m_tHalfwayDrift*y*y;
232  } else {
234  surfaceDriftTime = m_tSurfaceDrift+(m_tHalfwayDrift-m_tSurfaceDrift)*y*y;
235  }
236  return surfaceDriftTime;
237  } else {
238  ATH_MSG_INFO(" ysurf out of range " << ysurf);
239  return -1.0;
240  }
241  } else {
242  return 0.0;
243  }
244 }
245 
246 //-------------------------------------------------------------------------------------------
247 // create a list of surface charges from a hit - called from SCT_Digitization AthAlgorithm
248 //-------------------------------------------------------------------------------------------
249 void SCT_DetailedSurfaceChargesGenerator::process(const SiDetectorElement* element, const TimedHitPtr<SiHit>& phit, ISiSurfaceChargesInserter& inserter, CLHEP::HepRandomEngine * rndmEngine, const EventContext& ctx) {
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);
254 }
255 
256 //-------------------------------------------------------------------------------------------
257 // create a list of surface charges from a hit - called from both AthAlgorithm and PileUpTool
258 //-------------------------------------------------------------------------------------------
259 void SCT_DetailedSurfaceChargesGenerator::processSiHit(const SiDetectorElement* element, const SiHit& phit, ISiSurfaceChargesInserter& inserter, float p_eventTime, unsigned short p_eventId, CLHEP::HepRandomEngine * rndmEngine, const EventContext& ctx) {
260  const SCT_ModuleSideDesign* p_design{dynamic_cast<const SCT_ModuleSideDesign*>(&(element->design()))};
261  if (p_design==nullptr) {
262  ATH_MSG_ERROR("SCT_DetailedSurfaceChargesGenerator::process can not get " << p_design);
263  return;
264  }
265 
266  //---**************************************
267  // Time of Flight Calculation - separate method?
268  //---**************************************
269  //--- Original calculation of Time of Flight of the particle Time needed by the particle to reach the sensor
270  float timeOfFlight{p_eventTime + hitTime(phit)}; // hitTime(phit): Open functions of InDetSimEvent/SiHit.h hitTime(phit) = phit->meanTime();
271 
272  // Kondo 19/09/2007: Use the coordinate of the center of the module to calculate the time of flight
273  timeOfFlight -= (element->center().mag())/CLHEP::c_light;
274 
276  if (m_tsubtract>-998.) timeOfFlight -= m_tsubtract;
277  //---**************************************
278 
279  //Get HashId
280  const IdentifierHash hashId{element->identifyHash()};
281 
282  //get sensor thickness and tg lorentz from SiDetectorDesign
283  const double sensorThickness{p_design->thickness()};
284  const double tanLorentz{m_lorentzAngleTool->getTanLorentzAngle(hashId)};
285 
286  const CLHEP::Hep3Vector pos{phit.localStartPosition()};
287  const double xEta{pos[SiHit::xEta]};
288  const double xPhi{pos[SiHit::xPhi]};
289  const double xDep{pos[SiHit::xDep]};
290 
291  const CLHEP::Hep3Vector endPos{phit.localEndPosition()};
292  const double cEta{endPos[SiHit::xEta]-xEta};
293  const double cPhi{endPos[SiHit::xPhi]-xPhi};
294  const double cDep{endPos[SiHit::xDep]-xDep};
295 
296  double LargeStep{sqrt(cEta*cEta+cPhi*cPhi+cDep*cDep)};
297  int numberOfSteps{static_cast<int>(LargeStep/m_smallStepLength) + 1};
298  double steps{static_cast<double>(m_numberOfCharges*numberOfSteps)};
299  double e1{phit.energyLoss()/steps};
300  double q1{e1*m_siPropertiesTool->getSiProperties(hashId, ctx).electronHolePairsPerEnergy()};
301 
302  //in the following, to test the code, we will use the original coordinate system of the SCTtest3SurfaceChargesGenerator x is eta y is phi z is depth
303  double xhit{xEta};
304  double yhit{xPhi};
305  double zhit{xDep};
306 
307  double StepX{cEta/numberOfSteps};
308  double StepY{cPhi/numberOfSteps};
309  double StepZ{cDep/numberOfSteps};
310 
311  //check the status of truth information for this SiHit
312  //some Truth information is cut for pile up events
313  const HepMcParticleLink trklink = HepMcParticleLink::getRedirectedLink(phit.particleLink(), p_eventId, ctx); // This link should now correctly resolve to the TruthEvent McEventCollection in the main StoreGateSvc.
314 
316  if (phit.truthID() != 0 || phit.truthBarcode() != 0) { // if the hit was not caused by a delta-ray then one of these must be true
317  if (not trklink.isValid()) {
318  // TODO consider extending this check to reject links to
319  // GenEvents other than the first one in the McEventCollection,
320  // so that the digitization output doesn't change if pile-up
321  // truth is saved.
322  hitproc = SiCharge::cut_track;
323  }
324  }
325 
326  double dstep{-0.5};
327  for (int istep{0}; istep<numberOfSteps; ++istep) {
328  dstep += 1.0;
329  double z1{zhit+StepZ*dstep};//(static_cast<float>(istep)+0.5);
330 
331  //Distance between charge and readout side. p_design->readoutSide() is +1 if readout side is in +ve depth axis direction and visa-versa.
332  double zReadout{0.5*sensorThickness - p_design->readoutSide() * z1};
333 
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);
339  if (z1<0.0) {
340  z1= 0.0000005-0.5*sensorThickness; //set new coordinate to be 0.5nm inside wafer volume.
341  } else {
342  z1 = 0.5*sensorThickness-0.0000005; //set new coordinate to be 0.5nm inside wafer volume.
343  }
344  zReadout = 0.5*sensorThickness - p_design->readoutSide() * z1;
345  tdrift=DriftTime(zReadout, element, ctx);
346  if (tdrift>-2.0000002 and tdrift<-1.9999998) {
347  ATH_MSG_WARNING("Attempt failed. Making no correction.");
348  } else {
349  ATH_MSG_DEBUG("Correction Successful! z1 = " << std::fixed << std::setprecision(8) << z1 << ", zReadout = " << zReadout << ", tdrift = " << tdrift);
350  }
351  } else {
352  ATH_MSG_DEBUG("No rounding error found. Making no correction.");
353  }
354  }
355  if (tdrift > 0.0) {
356  double x1{xhit+StepX*dstep};//(static_cast<float>(istep)+0.5);
357  double y1{yhit+StepY*dstep};//(static_cast<float>(istep)+0.5);
358 
359  //PJ select driftmodel here
360  if (m_chargeDriftModel == defaultSCTModel or element->isEndcap()) { //Standard SCT driftmodel
361  y1 += tanLorentz*zReadout;
362  float diffusionSigma{DiffusionSigma(zReadout, element, ctx)};
363  for (int i{0}; i<m_numberOfCharges; ++i) {
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};
368 
369  SiLocalPosition position{element->hitLocalToLocal(xd, yd)};
370  if (p_design->inActiveArea(position)) {
371  float sdist{static_cast<float>(p_design->scaledDistanceToNearestDiode(position))};
372  float tsurf{this->SurfaceDriftTime(2.0*sdist)};
373  float totaltime{(m_tfix>-998.) ? m_tfix.value() : tdrift + timeOfFlight + tsurf};
374  inserter(SiSurfaceCharge(position, SiCharge(q1, totaltime, hitproc, trklink)));
375 
376 #ifdef SCT_DIG_DEBUG
377  ATH_MSG_INFO("Total Time: " << totaltime << " tdrift " << tdrift << " tsurf " << tsurf << " sdist " << sdist << " charge: " << q1);
378 #endif
379 
380  } else {
381 #ifdef SCT_DIG_DEBUG
382  ATH_MSG_INFO(std::fixed << std::setprecision(8) << "Local position: " << position << " of the element is out of active area, charge = " << q1);
383 #endif
384  }
385  } // end of loop on charges
386  } else if (m_chargeDriftModel == ehTransport and element->isBarrel()) { //TKs eh-transport model
387  //PJ calculates induced charge from e's and h's for 5 strips with 0.5 ns steps
388  // Set up local taka parameters, TK using cm...
389 
390  const InDetDD::SCT_BarrelModuleSideDesign* b_design{dynamic_cast<const InDetDD::SCT_BarrelModuleSideDesign*>(&(element->design()))};
391  if (b_design==nullptr) {
392  ATH_MSG_ERROR("SCT_DetailedSurfaceChargesGenerator::process can not get " << b_design);
393  return;
394  }
395 
396  double stripPitch{p_design->stripPitch()};
397  double stripPatternCentre{b_design->phiStripPatternCentre()};
398  double dstrip{(y1-stripPatternCentre)/stripPitch};
399 
400  // need the distance from the nearest strips edge not centre, xtaka = 1/2*stripPitch
401  // centre of detector, y1=0, is in the middle of an interstrip gap
402  if (dstrip>0.) {
403  dstrip -= static_cast<double>(static_cast<int>(dstrip));
404  } else {
405  dstrip -= static_cast<double>(static_cast<int>(dstrip)-1);
406  }
407  double xtakadist{dstrip*stripPitch};
408  double x0{xtakadist/10.}; // [mm] to [cm]
409  double y0{(sensorThickness - zReadout)/10.}; // [mm] to [cm]
410 
411 #ifdef SCT_DIG_DEBUG
412  ATH_MSG_INFO("element->isBarrel(): " << element->isBarrel() << " stripPitch: " << stripPitch << " stripPatternCentre: " << stripPatternCentre);
413  ATH_MSG_INFO("tanLorentz, y1, xtakadist = " << tanLorentz << ", " << y1 << ", " << xtakadist);
414 #endif
415  double Q_all[5][50]={};
416 
417  // Electron and hole transportation starting at x0 and y0
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);
420  //Loop over the strips and add the surface charges from each step and strip
421  for (int strip{-2}; strip<=2; strip++) {
422  double ystrip{y1 + strip*stripPitch};
423  SiLocalPosition position{element->hitLocalToLocal(x1, ystrip)};
424  if (p_design->inActiveArea(position)) {
425  for (int itq{0}; itq<50; itq++) {
426  const double charge =Q_all[strip+2][itq];
427  double time{(itq+1)*0.5 + timeOfFlight};
428  if (charge != 0.) inserter(SiSurfaceCharge(position, SiCharge(q1*charge,time,hitproc,trklink)));
429 #ifdef SCT_DIG_DEBUG
430  ATH_MSG_DEBUG("strip: " << strip << " position, x,y:" << x1 << ", " << ystrip << " charge: " << q1*charge);
431 #endif
432  }
433  } else {
434 #ifdef SCT_DIG_DEBUG
435  ATH_MSG_INFO(std::fixed << std::setprecision(8) << "Local position: " << position << " of the element is out of active area, charge = " << q1);
436 #endif
437  }
438  }
439  } else if (m_chargeDriftModel == fixedChargeMap and element->isBarrel()) { //TKs fixed charge map model
440  ATH_MSG_ERROR("Fixed charge map model, implementation not finished yet...");
441 
442  const InDetDD::SCT_BarrelModuleSideDesign* b_design{dynamic_cast<const InDetDD::SCT_BarrelModuleSideDesign*>(&(element->design()))};
443  if (b_design==nullptr) {
444  ATH_MSG_ERROR("SCT_DetailedSurfaceChargesGenerator::process can not get " << b_design);
445  return;
446  }
447 
448  // Set up local taka parameters, TK using um...I think
449  double stripPitch{p_design->stripPitch()};
450  double stripPatternCentre{b_design->phiStripPatternCentre()};
451  double dstrip{(y1-stripPatternCentre)/stripPitch};
452 
453  // need the distance from the nearest strips edge not centre, xtaka = 1/2*stripPitch
454  // centre of detector, y1=0, is in the middle of an interstrip gap
455  if (dstrip>0.) {
456  dstrip -= static_cast<double>(static_cast<int>(dstrip));
457  } else {
458  dstrip -= static_cast<double>(static_cast<int>(dstrip)-1);
459  }
460  double xtakadist{dstrip*stripPitch};
461  double x0{xtakadist*1000.}; // [mm] to [um]
462  double y0{(sensorThickness - zReadout)*1000.}; // [mm] to [um]
463 
464  //Loop over the strips and add the surface charges from each step and strip
465  for (int strip{-2}; strip<=2; strip++) {
466  double ystrip{y1 + strip*stripPitch};
467  SiLocalPosition position{element->hitLocalToLocal(x1, ystrip)};
468  if (p_design->inActiveArea(position)) {
469  //PJ best way of doing this...
470  double time{0.};
471  double charge{0.};
472  for (int it{0}; it<50; it++) {
473  time = 0.25 + 0.5*it;
474  charge = q1 * inducedCharge(strip, x0, y0, time);
475  if (charge != 0.) {
476  inserter(SiSurfaceCharge(position, SiCharge(charge, time+timeOfFlight, hitproc, trklink)));
477  }
478  }
479  } else {
480 #ifdef SCT_DIG_DEBUG
481  ATH_MSG_INFO(std::fixed << std::setprecision(8) << "Local position: " << position << " of the element is out of active area, charge = " << q1);
482 #endif
483  }
484  }
485  } else {
486  ATH_MSG_ERROR("Wrong chargeDriftModel " << m_chargeDriftModel << " 0, standard, 1 eh transport, 2 fixed charge map");
487  }
488  }
489  }
490  }
491 
492 //------------------------------------------------------------
493 // initialization of e/h transport programme
494 //-----------------------------------------------------------
496  //------------------------ initialize subfunctions ------------
499  initExEyArray();
501 
502  //------------ find delepletion deph for model=uniformEFieldModel and flatDiodeModel -------------
503  ATH_MSG_INFO("\tmodel= " << m_eFieldModel << " VB= " << m_biasVoltage << " B= " << m_magneticField);
507  }
508 
509  // ----------- find for the case of model = FEMsolution ---------------
510  if (m_eFieldModel == FEMsolution) {
511  double Ex{0.}, Ey{0.};
512  for (double y{0.}; y < m_bulk_depth; y += 0.00025) {
513  EField(0., y, Ex, Ey);
514  if (Ey > 0.1) continue;
516  }
517  }
519 
520  ATH_MSG_INFO("------ initialization of e-h transport ------");
521  ATH_MSG_INFO("\tm_bulk_depth = " << m_bulk_depth << " [cm]");
522  ATH_MSG_INFO("\tm_depletion_depth = " << m_depletion_depth << " [cm]");
523  ATH_MSG_INFO("\tm_y_origin _min = " << m_y_origin_min << " [cm]");
524 
525  //----for the case of uniform field model (SCT digitization model)------
526  double Emean{m_biasVoltage / m_depletion_depth};
527  m_driftMobility = mud_h(Emean);
528 
529 #ifdef SCT_DIG_DEBUG
530  ATH_MSG_INFO("----parameters for old SCT digitization model ----");
531  ATH_MSG_INFO("\tmean E field = " << Emean << " [KV/cm] ");
532  ATH_MSG_INFO("\tdriftMobility = " << m_driftMobility<< " [ ]");
533 
534  double diffusion{m_kB * m_sensorTemperature * m_driftMobility / m_e};
535  ATH_MSG_INFO("\tdiffusion D = " << diffusion << " [ ]");
536 
537  double r_h{0.72 - 0.0005*(m_sensorTemperature-CLHEP::STP_Temperature)};
538  double tanLA{r_h * m_driftMobility * m_magneticField * 1.E-4};
539  ATH_MSG_INFO("\ttan(LA) = " << tanLA);
540  ATH_MSG_INFO("\tLA = " << atan(tanLA)*180./M_PI << " [degree]");
541  ATH_MSG_INFO("-----------------------------------------------");
542 
543  ATH_MSG_INFO("EfieldModel\t" << m_eFieldModel << "\t(default = FEMsolution)");
544  ATH_MSG_INFO("DepletionVoltage_VD\t" << m_depletionVoltage << "\t(default = 70.)");
545  ATH_MSG_INFO("BiasVoltage_VB\t" << m_biasVoltage << "\t(150.)");
546  ATH_MSG_INFO("MagneticField_B\t" << m_magneticField << "\t(-2.0)");
547  ATH_MSG_INFO("Temperature_T\t" << m_sensorTemperature << "\t(273.15)");
548  ATH_MSG_INFO("TransportTimeStep \t" << m_transportTimeStep << "\t(0.25)");
549  ATH_MSG_INFO("TransportTimeMax\t" << m_transportTimeMax << "\t(25.0)");
550  ATH_MSG_INFO("BulkDepth\t" << m_bulk_depth << "\t(0.0285)");
551  ATH_MSG_INFO("StripPitch\t" << m_strip_pitch << "\t(0.0080)");
552  ATH_MSG_INFO("----------------------------------------------");
553 #endif
554 
555 }
556 
557 //--------------------------------------------------------------
558 // initialize drift mobility for electrons
559 //--------------------------------------------------------------
561  m_vs_e = 1.53E9 * pow(T, -0.87);
562  m_Ec_e = 1.01 * pow(T, 1.55);
563  m_beta_e = 2.57E-2 * pow(T, 0.66);
564 }
565 
566 //--------------------------------------------------------------
567 // initialize drift mobility for holes
568 //--------------------------------------------------------------
570  m_vs_h = 1.62E8 * pow(T, -0.52);
571  m_Ec_h = 1.24 * pow(T, 1.68);
572  m_beta_h = 0.46 * pow(T, 0.17);
573 }
574 
575 //--------------------------------------------------------------
576 // initialize ExEyArray
577 //--------------------------------------------------------------
579  for (int ix{0}; ix<17; ix++) {
580  for (int iy{0}; iy<115; iy++) {
581  m_ExValue150[ix][iy] = ExValue150(ix, iy);
582  m_EyValue150[ix][iy] = EyValue150(ix, iy);
583  if (m_doHistoTrap) {
584  m_h_yzEfield->Fill( ix*0.00025, iy*0.00025, sqrt(ExValue150(ix, iy)*ExValue150(ix, iy)+EyValue150(ix, iy)*EyValue150(ix, iy)));
585  m_h_yzEfield->Fill(-ix*0.00025, iy*0.00025, sqrt(ExValue150(ix, iy)*ExValue150(ix, iy)+EyValue150(ix, iy)*EyValue150(ix, iy)));
586  m_h_yEfield->Fill( ix*0.0005, iy*0.00025, ExValue150(ix, iy));
587  m_h_yEfield->Fill( -ix*0.0005, iy*0.00025, ExValue150(ix, iy));
588  m_h_zEfield->Fill( ix*0.0005, iy*0.00025, EyValue150(ix, iy));
589  m_h_zEfield->Fill( -ix*0.0005, iy*0.00025, EyValue150(ix, iy));
590  }
591  }
592  }
593 }
594 
595 //--------------------------------------------------------------
596 // initialize PotentialValue
597 //--------------------------------------------------------------
599  for (int ix{0}; ix<81; ix++) {
600  for (int iy{0}; iy<115; iy++) {
601  m_PotentialValue[ix][iy] = GetPotentialValue(ix, iy);
602  if (m_doHistoTrap) {
603  m_h_yzRamo->Fill( ix*0.005, iy*0.0025, GetPotentialValue(ix, iy));
604  m_h_yzRamo->Fill(-ix*0.005, iy*0.0025, GetPotentialValue(ix, iy));
605  }
606  }
607  }
608 }
609 
610 //---------------------------------------------------------------
611 // parameters for electron transport
612 //---------------------------------------------------------------
613 bool SCT_DetailedSurfaceChargesGenerator::electron(double x_e, double y_e, double& vx_e, double& vy_e, double& D_e) const {
614  double Ex, Ey;
615  EField(x_e, y_e, Ex, Ey); // [V/cm]
616  if (Ey > 0.) {
617  const double REx{-Ex}; // because electron has negative charge
618  const double REy{-Ey}; // because electron has negative charge
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};
622  const double r_e{1.13+0.0008*(m_sensorTemperature-CLHEP::STP_Temperature)};
623  const double tanLA_e{r_e * mu_e * (-m_magneticField) * 1.E-4}; // because e has negative charge
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;
629  D_e = m_kB * m_sensorTemperature * mu_e / m_e;
630  return true;
631  } else {
632  return false;
633  }
634 }
635 
636 //---------------------------------------------------------------
637 // parameters for hole transport
638 //---------------------------------------------------------------
639 bool SCT_DetailedSurfaceChargesGenerator::hole(double x_h, double y_h, double& vx_h, double& vy_h, double& D_h) {
640  double Ex, Ey;
641  EField(x_h, y_h, Ex, Ey); // [V/cm]
642 
643  if (m_doHistoTrap) {
644  m_h_efieldz->Fill(y_h, Ey);
645  }
646 
647  if (Ey > 0.) {
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};
651  const double r_h{0.72 - 0.0005*(m_sensorTemperature-CLHEP::STP_Temperature)};
652  const double tanLA_h{r_h * mu_h * m_magneticField * 1.E-4};
653  const double secLA{sqrt(1.+tanLA_h*tanLA_h)};
654  const double cosLA{1./secLA};
655  const double sinLA{tanLA_h / secLA};
656 
657  vy_h = v_h * (Ey*cosLA - Ex*sinLA)/E;
658  vx_h = v_h * (Ex*cosLA + Ey*sinLA)/E;
659  D_h = m_kB * m_sensorTemperature * mu_h / m_e;
660  return true;
661  } else {
662  return false;
663  }
664 }
665 
666 //-------------------------------------------------------------------
667 // calculation of induced charge using Weighting (Ramo) function
668 //-------------------------------------------------------------------
669 double SCT_DetailedSurfaceChargesGenerator::induced(int istrip, double x, double y) const {
670  // x and y are the coorlocation of charge (e or hole)
671  // induced chardege on the strip "istrip" situated at the height y = d
672  // the center of the strip (istrip=0) is x = 0.004 [cm]
673  static const double deltax{0.0005};
674  static const double deltay{0.00025};
675 
676  if (y < 0. or y > m_bulk_depth) return 0.;
677  const double xc{m_strip_pitch * (istrip + 0.5)};
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};
684  double P{ m_PotentialValue[ix ][iy ] *(1.-fx)*(1.-fy)
685  + m_PotentialValue[ix+1][iy ] * fx *(1.-fy)
686  + m_PotentialValue[ix ][iy+1] *(1.-fx)* fy
687  + m_PotentialValue[ix+1][iy+1] * fx * fy};
688 #ifdef SCT_DIG_DEBUG
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);
691 #endif
692 
693  return P;
694 }
695 
696 //--------------------------------------------------------------
697 // Electric Field Ex and Ey
698 //--------------------------------------------------------------
699 void SCT_DetailedSurfaceChargesGenerator::EField(double x, double y, double& Ex, double& Ey) const {
700  // m_eFieldModel == uniformEFieldModel; uniform E-field model
701  // m_eFieldModel == flatDiodeModel; flat diode model
702  // m_eFieldModel == FEMsolution; FEM solutions
703  // x == 0.0040 [cm] : at the center of strip
704  // x must be within 0 and 0.008 [cm]
705 
706  static const double deltay{0.00025}, deltax{0.00025}; // [cm]
707 
708  Ex = 0.;
709  Ey = 0.;
710  if (y < 0. or y > m_bulk_depth) return;
711 
712  //---------- case for uniform electric field ------------------------
715  return;
716  }
717 
718  //---------- case for flat diode model ------------------------------
722  } else {
725  }
726  return;
727  }
728 
729  //---------- case for FEM analysis solution -------------------------
730  if (m_eFieldModel==FEMsolution) {
731  int iy{static_cast<int>(y/deltay)};
732  double fy{(y-iy*deltay) / deltay};
733  double xhalfpitch{m_strip_pitch/2.};
734  double x999{999.*m_strip_pitch};
735  double xx{fmod (x+x999, m_strip_pitch)};
736  double xxx{xx};
737  if (xx > xhalfpitch) xxx = m_strip_pitch - xx;
738  int ix{static_cast<int>(xxx/deltax)};
739  double fx{(xxx - ix*deltax) / deltax};
740 #ifdef SCT_DIG_DEBUG
741  ATH_MSG_DEBUG("x,y,ix,iy,fx,fy,xx,xxx= " << x << " " << y << " " << ix << " " << iy << " " << fx << " " << fy << " " << xx << " " << xxx);
742 #endif
743  int ix1{ix+1};
744  int iy1{iy+1};
745  double Ex00{0.}, Ex10{0.}, Ex01{0.}, Ex11{0.};
746  double Ey00{0.}, Ey10{0.}, Ey01{0.}, Ey11{0.};
747  //-------- pick up appropriate data file for m_biasVoltage-----------------------
748  int iVB{static_cast<int>(m_biasVoltage)};
749  switch (iVB) {
750  case 150:
751  Ex00 = m_ExValue150[ix][iy]; Ex10 = m_ExValue150[ix1][iy];
752  Ex01 = m_ExValue150[ix][iy1]; Ex11 = m_ExValue150[ix1][iy1];
753  Ey00 = m_EyValue150[ix][iy]; Ey10 = m_EyValue150[ix1][iy];
754  Ey01 = m_EyValue150[ix][iy1]; Ey11 = m_EyValue150[ix1][iy1];
755  break;
756  default:
757  ATH_MSG_WARNING("Only +150 V bias voltage case is available. However, " << iVB << " V bias voltage is used. Electoric field is not extracted!!!");
758  break;
759  }
760  //---------------- end of data bank search---
761  Ex = Ex00*(1.-fx)*(1.-fy) + Ex10*fx*(1.-fy) + Ex01*(1.-fx)*fy + Ex11*fx*fy;
762 #ifdef SCT_DIG_DEBUG
763  ATH_MSG_DEBUG("xx, xhalfpitch = " << xx << " " << xhalfpitch);
764 #endif
765  if (xx > xhalfpitch) Ex = -Ex;
766  Ey = Ey00*(1.-fx)*(1.-fy) + Ey10*fx*(1.-fy) + Ey01*(1.-fx)*fy + Ey11*fx*fy;
767  return;
768  }
769  }
770 
771 //--------------------------------------------------------------
772 // drift mobility for electrons
773 //--------------------------------------------------------------
775  return m_vs_e/m_Ec_e/pow(1.+pow(E/m_Ec_e, m_beta_e), 1./m_beta_e);
776 }
777 
778 //--------------------------------------------------------------
779 // drift mobility for holes
780 //--------------------------------------------------------------
782  return m_vs_h/m_Ec_h/pow(1.+pow(E/m_Ec_h, m_beta_h), 1./m_beta_h);
783 }
784 
785 //---------------------------------------------------------------------
786 // holeTransport
787 //---------------------------------------------------------------------
788 void SCT_DetailedSurfaceChargesGenerator::holeTransport(double& x0, double& y0, double* Q_m2, double* Q_m1, double* Q_00, double* Q_p1, double* Q_p2, CLHEP::HepRandomEngine * rndmEngine) {
789  // transport holes in the bulk
790  // T. Kondo, 2010.9.9
791  // External parameters to be specified
792  // m_transportTimeMax [nsec]
793  // m_transportTimeStep [nsec]
794  // m_bulk_depth [cm]
795  // Induced currents are added to
796  // Q_m2[50],Q_m1[50],Q_00[50],Q_p1[50],Q_p2[50]
797 
798  double x{x0}; // original hole position [cm]
799  double y{y0}; // original hole position [cm]
800  bool isInBulk{true}; //PJ ?!
801  double t_current{0.};
802  double qstrip[5];
803  double vx, vy, D;
804 
805  // -- Charge Trapping -- //
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};
810 
811  for (int istrip{-2}; istrip<=2; istrip++) {
812  qstrip[istrip+2] = induced(istrip, x, y);
813  }
814 #ifdef SCT_DIG_DEBUG
815  ATH_MSG_DEBUG("h:qstrip=" << qstrip[0] << " " << qstrip[1] << " " << qstrip[2] << " " << qstrip[3] << " " << qstrip[4]);
816 #endif
817  while (t_current < m_transportTimeMax) {
818  if (not isInBulk) break;
819  if (not hole(x, y, vx, vy, D)) break;
820  double delta_y{vy * m_transportTimeStep *1.E-9};
821  y += delta_y;
822  double dt{m_transportTimeStep};
823  if (y > m_bulk_depth) {
824  isInBulk = false;
825  dt = (m_bulk_depth - (y-delta_y))/delta_y * m_transportTimeStep;
826  y = m_bulk_depth;
827  }
828  t_current += dt;
829 
830  // -- Charge Trapping -- //
831  if (m_doTrapping) {
832  if (drift_time < t_current) break;
833  }
834 
835  x += vx*dt*1.E-9;
836  double diffusion{sqrt(2.*D*dt*1.E-9)};
837  y += diffusion * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
838  x += diffusion * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
839  if (y > m_bulk_depth) {
840  y = m_bulk_depth;
841  isInBulk = false;
842  }
843 
844  // Get induced current by subtracting induced charges
845 #ifdef SCT_DIG_DEBUG
846  ATH_MSG_DEBUG("h:t,x,y=" << t_current << ", " << x*1e4 << ", " << y*1e4);
847 #endif
848  for (int istrip{-2}; istrip<=2; istrip++) {
849  double qnew{induced(istrip, x, y)};
850  int jj{istrip + 2};
851  double dq{qnew - qstrip[jj]};
852  qstrip[jj] = qnew;
853 #ifdef SCT_DIG_DEBUG
854  ATH_MSG_DEBUG("dq= " << dq);
855 #endif
856  int jt{static_cast<int>((t_current+0.001) / 0.50)};
857  if (jt<50) {
858  switch (istrip) {
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;
864  // default: break; // logically dead code
865  }
866  }
867  }
868 #ifdef SCT_DIG_DEBUG
869  ATH_MSG_DEBUG("h:qstrip=" << qstrip[0] << " " << qstrip[1] << " " << qstrip[2] << " " << qstrip[3] << " " << qstrip[4]);
870 #endif
871  } // end of hole tracing
872 #ifdef SCT_DIG_DEBUG
873  ATH_MSG_DEBUG("holeTransport : x,y=(" << x0*1.e4<< "," <<y0*1.e4<< ")->(" << x*1.e4<< "," <<y*1.e4 << ") t=" << t_current);
874 #endif
875  }
876 
878  return getPotentialValue(ix, iy);
879 }
880 
881 //---------------------------------------------------------------------
882 // electronTransport
883 //---------------------------------------------------------------------
884 void SCT_DetailedSurfaceChargesGenerator::electronTransport(double& x0, double& y0, double* Q_m2, double* Q_m1, double* Q_00, double* Q_p1, double* Q_p2, CLHEP::HepRandomEngine * rndmEngine) const {
885  // transport electrons in the bulk
886  // T. Kondo, 2010.9.10
887  // External parameters to be specified
888  // m_transportTimeMax [nsec]
889  // m_transportTimeStep [nsec]
890  // m_y_origin_min [cm] 0 except under-depleted cases
891  // Induced currents are added to
892  // Q_m2[50],Q_m1[50],Q_00[50],Q_p1[50],Q_p2[50]
893 
894  double x{x0}; // original electron position [cm]
895  double y{y0}; // original electron position [cm]
896  bool isInBulk{true};
897  double t_current{0.};
898  double qstrip[5];
899  double vx, vy, D;
900 
901  // -- Charge Trapping -- //
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};
906 
907  for (int istrip{-2}; istrip<=2; istrip++) {
908  qstrip[istrip+2] = -induced(istrip, x, y);
909  }
910 
911  // note 0.004[cm] is to shift from Richard's to Taka's coordinates
912  while (t_current < m_transportTimeMax) {
913  if (not isInBulk) break;
914  if (not electron(x, y, vx, vy, D)) break;
915  double delta_y{vy * m_transportTimeStep *1.E-9};
916  y += delta_y;
917  double dt{m_transportTimeStep}; // [nsec]
918  if (y < m_y_origin_min) {
919  isInBulk = false;
920  dt = (m_y_origin_min - (y-delta_y))/delta_y * m_transportTimeStep;
921  y = m_y_origin_min;
922  }
923  t_current += dt;
924 
925  // -- Charge Trapping -- //
926  if (m_doTrapping) {
927  if (drift_time < t_current) break;
928  }
929 
930  x += vx * dt *1.E-9;
931  double diffusion{sqrt(2.* D * dt*1.E-9)};
932  y += diffusion * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
933  x += diffusion * CLHEP::RandGaussZiggurat::shoot(rndmEngine);
934  if (y < m_y_origin_min) {
935  y = m_y_origin_min;
936  isInBulk = false;
937  }
938  // get induced current by subtracting induced charges
939  for (int istrip{-2}; istrip<=2; istrip++) {
940  double qnew{-induced(istrip, x, y)};
941  int jj{istrip + 2};
942  double dq{qnew - qstrip[jj]};
943  qstrip[jj] = qnew;
944 #ifdef SCT_DIG_DEBUG
945  if (istrip==0) ATH_MSG_DEBUG("e:t,x,y=" << t_current << " " << x*1e4 << " " << y*1e4 << " dq[0]=" << dq);
946 #endif
947  int jt{static_cast<int>((t_current + 0.001) / 0.50)};
948  if (jt<50) {
949  switch (istrip) {
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;
955  // default: break; // logically dead code
956  }
957  }
958  }
959  } // end of hole tracing
960 #ifdef SCT_DIG_DEBUG
961  ATH_MSG_DEBUG("elecTransport : x,y=(" << x0*1.e4 << "," << y0*1.e4 << ")->(" << x*1.e4 << "," << y*1.e4 << ") t=" << t_current);
962 #endif
963 
964  }
965 
966 //---------------------------------------------------------------------
967 // Charge map calculations
968 //---------------------------------------------------------------------
969 double SCT_DetailedSurfaceChargesGenerator::inducedCharge (int& strip, double& x, double& y, double& t) const {
970  // x and y are in um, t is in ns.
971  double charge{0.};
972 
973  static const double dt{0.5};
974  double fx, fy, ft;
975  int ix, iy, it;//, iy1, it1;
976 
977  if (strip<-2 or strip>2) return charge;
978  if (x<0. or x>=m_strip_pitch*10000.) return charge;
979  if (y<0. or y>=m_bulk_depth*10000.) return charge;
980  if (t<0. or t>=m_transportTimeMax) return charge;
981 
982  fx = x / m_stripCharge_dx;
983  ix = static_cast<int>(fx);
984  fx -= ix;
985 
986  fy = (y - 0.5*m_stripCharge_dy) / m_stripCharge_dy;
987  iy = static_cast<int>(fy);
988  fy -= iy;
989  //iy1 = iy + 1;
990  if (y <= 0.5*m_stripCharge_dy) {
991  fy = 0.;
992  iy = 0;
993  /*iy1 = 0;*/
994  }
995  if (y >= m_bulk_depth*10000.-0.5*m_stripCharge_dy) {
996  fy = 1.;
997  iy = m_stripCharge_iymax;
998  /*iy1 = iy;*/
999  }
1000 
1001  ft = (t - m_transportTimeStep) / dt;
1002  it = static_cast<int>(ft);
1003  ft -= it;
1004  //it1 = it + 1;
1005  if (t <= m_transportTimeStep) {
1006  ft = 0.;
1007  it = 0;
1008  /*it1= 0;*/
1009  }
1011  ft = 1.;
1012  it = 49;
1013  /*it1=49;*/
1014  }
1015 
1016  double p000{0.};//m_stripCharge[strip+2][ix][iy][it];
1017  double p010{0.};//m_stripCharge[strip+2][ix][iy1][it];
1018  double p100{0.};//m_stripCharge[strip+2][ix+1][iy][it];
1019  double p110{0.};//m_stripCharge[strip+2][ix+1][iy1][it];
1020  double p001{0.};//m_stripCharge[strip+2][ix][iy][it1];
1021  double p011{0.};//m_stripCharge[strip+2][ix][iy1][it1];
1022  double p101{0.};//m_stripCharge[strip+2][ix+1][iy][it1];
1023  double p111{0.};//m_stripCharge[strip+2][ix+1][iy1][it1];
1024 
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};
1027 
1028  charge = charge0*(1.-ft) + charge1*ft;
1029 
1030  return charge;
1031 }
SCT_DetailedSurfaceChargesGenerator::m_kB
double m_kB
Definition: SCT_DetailedSurfaceChargesGenerator.h:169
SiHit::xPhi
@ xPhi
Definition: SiHit.h:162
SCT_DetailedSurfaceChargesGenerator::m_numberOfCharges
IntegerProperty m_numberOfCharges
number of charges
Definition: SCT_DetailedSurfaceChargesGenerator.h:121
plotBeamSpotCompare.x1
x1
Definition: plotBeamSpotCompare.py:216
getPotentialValue
double getPotentialValue(const int ix, const int iy)
A free function to return the SCT electric field potential internal to the silicon on a 81 * 115 arra...
Definition: SCT_GetPotentialValue.cxx:9
SCT_DetailedSurfaceChargesGenerator::m_distInterStrip
float m_distInterStrip
Inter strip distance normalized to 1.
Definition: SCT_DetailedSurfaceChargesGenerator.h:157
InDetDD::SiDetectorElement::isEndcap
bool isEndcap() const
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
SCT_DetailedSurfaceChargesGenerator::initTransportModel
void initTransportModel()
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:495
PlotCalibFromCool.ft
ft
Definition: PlotCalibFromCool.py:329
SiSurfaceCharge
Definition: SiSurfaceCharge.h:23
SiliconTech::strip
@ strip
SiHit::localEndPosition
HepGeom::Point3D< double > localEndPosition() const
Definition: SiHit.cxx:153
SCT_DetailedSurfaceChargesGenerator::m_isOverlay
BooleanProperty m_isOverlay
Definition: SCT_DetailedSurfaceChargesGenerator.h:147
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
SCT_DetailedSurfaceChargesGenerator::mud_h
double mud_h(double E) const
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:781
SCT_DetailedSurfaceChargesGenerator::m_smallStepLength
FloatProperty m_smallStepLength
max internal step along the larger G4 step
Definition: SCT_DetailedSurfaceChargesGenerator.h:122
python.PhysicalConstants.STP_Temperature
float STP_Temperature
Definition: PhysicalConstants.py:119
egammaEnergyPositionAllSamples::e1
double e1(const xAOD::CaloCluster &cluster)
return the uncorrected cluster energy in 1st sampling
SCT_DetailedSurfaceChargesGenerator::init_mud_h
void init_mud_h(double T)
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:569
SiHit.h
SCT_DetailedSurfaceChargesGenerator::m_driftMobility
double m_driftMobility
Definition: SCT_DetailedSurfaceChargesGenerator.h:177
SCT_ModuleSideDesign.h
SCT_DetailedSurfaceChargesGenerator::m_depletionVoltage
DoubleProperty m_depletionVoltage
Definition: SCT_DetailedSurfaceChargesGenerator.h:140
InDetDD::SCT_ModuleSideDesign
Definition: SCT_ModuleSideDesign.h:40
SCT_DetailedSurfaceChargesGenerator::m_doHistoTrap
BooleanProperty m_doHistoTrap
Definition: SCT_DetailedSurfaceChargesGenerator.h:131
SCT_DetailedSurfaceChargesGenerator::hole
bool hole(double x_h, double y_h, double &vx_h, double &vy_h, double &D_h)
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:639
SCT_DetailedSurfaceChargesGenerator::initPotentialValue
void initPotentialValue()
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:598
SCT_DetailedSurfaceChargesGenerator::electron
bool electron(double x_e, double y_e, double &vx_e, double &vy_e, double &D_e) const
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:613
InDetDD::SolidStateDetectorElementBase::center
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
SCT_DetailedSurfaceChargesGenerator::m_h_zEfield
TProfile2D * m_h_zEfield
Definition: SCT_DetailedSurfaceChargesGenerator.h:202
SCT_DetailedSurfaceChargesGenerator::m_SurfaceDriftFlag
bool m_SurfaceDriftFlag
surface drift ON/OFF
Definition: SCT_DetailedSurfaceChargesGenerator.h:160
SCT_DetailedSurfaceChargesGenerator::mud_e
double mud_e(double E) const
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:774
conifer::pow
constexpr int pow(int x)
Definition: conifer.h:20
SCT_DetailedSurfaceChargesGenerator::m_chargeDriftModel
IntegerProperty m_chargeDriftModel
Definition: SCT_DetailedSurfaceChargesGenerator.h:136
SiCharge::track
@ track
Definition: SiCharge.h:28
SCT_DetailedSurfaceChargesGenerator::m_distHalfInterStrip
float m_distHalfInterStrip
Half way distance inter strip.
Definition: SCT_DetailedSurfaceChargesGenerator.h:158
skel.it
it
Definition: skel.GENtoEVGEN.py:423
TProfile2D
Definition: rootspy.cxx:531
SCT_DetailedSurfaceChargesGenerator::m_transportTimeMax
DoubleProperty m_transportTimeMax
Definition: SCT_DetailedSurfaceChargesGenerator.h:145
M_PI
#define M_PI
Definition: ActiveFraction.h:11
SCT_DetailedSurfaceChargesGenerator::m_tsubtract
FloatProperty m_tsubtract
Definition: SCT_DetailedSurfaceChargesGenerator.h:128
SCT_DetailedSurfaceChargesGenerator::m_y_origin_min
double m_y_origin_min
Definition: SCT_DetailedSurfaceChargesGenerator.h:166
SiCharge
Definition: SiCharge.h:25
SCT_DetailedSurfaceChargesGenerator::m_beta_e
double m_beta_e
Definition: SCT_DetailedSurfaceChargesGenerator.h:175
InDetDD::SCT_BarrelModuleSideDesign
Definition: SCT_BarrelModuleSideDesign.h:34
TimedHitPtr< SiHit >
SCT_DetailedSurfaceChargesGenerator::MaxDiffusionSigma
float MaxDiffusionSigma(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max sigma diffusion
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:211
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
x
#define x
SCT_DetailedSurfaceChargesGenerator::processSiHit
void processSiHit(const InDetDD::SiDetectorElement *element, const SiHit &phit, ISiSurfaceChargesInserter &inserter, const float eventTime, const unsigned short eventID, CLHEP::HepRandomEngine *rndmEngine, const EventContext &ctx)
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:259
SCT_DetailedSurfaceChargesGenerator::init_mud_e
void init_mud_e(double T)
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:560
Trk::u
@ u
Enums for curvilinear frames.
Definition: ParamDefs.h:83
InDetDD::SolidStateDetectorElementBase::identifyHash
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
SCT_DetailedSurfaceChargesGenerator::inducedCharge
double inducedCharge(int &istrip, double &x, double &y, double &t) const
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:969
makeTRTBarrelCans.y1
tuple y1
Definition: makeTRTBarrelCans.py:15
SCT_DetailedSurfaceChargesGenerator::GetPotentialValue
static double GetPotentialValue(int ix, int iy)
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:877
SCT_DetailedSurfaceChargesGenerator::SCT_DetailedSurfaceChargesGenerator
SCT_DetailedSurfaceChargesGenerator(const std::string &type, const std::string &name, const IInterface *parent)
constructor
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:35
drawFromPickle.atan
atan
Definition: drawFromPickle.py:36
SiHit
Definition: SiHit.h:19
SCT_DetailedSurfaceChargesGenerator::initExEyArray
void initExEyArray()
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:578
SCT_DetailedSurfaceChargesGenerator::EField
void EField(double x, double y, double &Ex, double &Ey) const
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:699
TimedHitPtr::eventTime
float eventTime() const
t0 offset of the bunch xing containing the hit in ns.
Definition: TimedHitPtr.h:50
InDetDD::SiLocalPosition
Definition: SiLocalPosition.h:31
SCT_DetailedSurfaceChargesGenerator::EyValue150
static double EyValue150(int ix, int iy)
Definition: GetExEy_150V.cxx:7
SCT_GetPotentialValue.h
SCT_DetailedSurfaceChargesGenerator::m_siConditionsTool
ToolHandle< ISiliconConditionsTool > m_siConditionsTool
Definition: SCT_DetailedSurfaceChargesGenerator.h:151
Run3DQTestingDriver.dq
dq
Definition: Run3DQTestingDriver.py:108
SCT_DetailedSurfaceChargesGenerator::m_tHalfwayDrift
float m_tHalfwayDrift
Surface drift time.
Definition: SCT_DetailedSurfaceChargesGenerator.h:156
beamspotman.steps
int steps
Definition: beamspotman.py:505
SCT_DetailedSurfaceChargesGenerator::m_PotentialValue
double m_PotentialValue[81][115]
Definition: SCT_DetailedSurfaceChargesGenerator.h:180
SCT_DetailedSurfaceChargesGenerator::defaultSCTModel
@ defaultSCTModel
Definition: SCT_DetailedSurfaceChargesGenerator.h:76
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
TRT::Hit::driftTime
@ driftTime
Definition: HitInfo.h:43
lumiFormat.i
int i
Definition: lumiFormat.py:92
SCT_DetailedSurfaceChargesGenerator::m_depletion_depth
double m_depletion_depth
Definition: SCT_DetailedSurfaceChargesGenerator.h:165
InDetDD::SolidStateDetectorElementBase::thickness
double thickness() const
PixelAthClusterMonAlgCfg.e4
e4
Definition: PixelAthClusterMonAlgCfg.py:317
python.TrigEgammaMonitorHelper.TProfile
def TProfile(*args, **kwargs)
Definition: TrigEgammaMonitorHelper.py:81
SCT_DetailedSurfaceChargesGenerator::finalize
virtual StatusCode finalize() override
AlgTool finalize.
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:145
SCT_DetailedSurfaceChargesGenerator::m_stripCharge_dy
double m_stripCharge_dy
Definition: SCT_DetailedSurfaceChargesGenerator.h:195
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
CaloNoise_fillDB.dt
dt
Definition: CaloNoise_fillDB.py:58
SCT_DetailedSurfaceChargesGenerator::m_e
double m_e
Definition: SCT_DetailedSurfaceChargesGenerator.h:170
SCT_DetailedSurfaceChargesGenerator::m_Fluence
DoubleProperty m_Fluence
Definition: SCT_DetailedSurfaceChargesGenerator.h:133
SiHit::truthBarcode
int truthBarcode() const
Definition: SiHit.cxx:202
SCT_DetailedSurfaceChargesGenerator::SurfaceDriftTime
float SurfaceDriftTime(float ysurf) const
Calculate of the surface drift time.
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:225
SCT_DetailedSurfaceChargesGenerator::m_ExValue150
double m_ExValue150[17][115]
Definition: SCT_DetailedSurfaceChargesGenerator.h:181
SiHit::particleLink
const HepMcParticleLink & particleLink() const
Definition: SiHit.h:190
test_pyathena.parent
parent
Definition: test_pyathena.py:15
SCT_DetailedSurfaceChargesGenerator::induced
double induced(int istrip, double x, double y) const
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:669
TProfile2D::Fill
int Fill(double, double, double)
Definition: rootspy.cxx:541
SCT_DetailedSurfaceChargesGenerator.h
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SCT_DetailedSurfaceChargesGenerator::m_thistSvc
ServiceHandle< ITHistSvc > m_thistSvc
Definition: SCT_DetailedSurfaceChargesGenerator.h:154
python.SystemOfUnits.micrometer
int micrometer
Definition: SystemOfUnits.py:71
python.SystemOfUnits.volt
int volt
Definition: SystemOfUnits.py:204
ReadTripsProbsFromCool.denominator
denominator
Definition: ReadTripsProbsFromCool.py:96
SCT_DetailedSurfaceChargesGenerator::m_vs_h
double m_vs_h
Definition: SCT_DetailedSurfaceChargesGenerator.h:173
SCT_DetailedSurfaceChargesGenerator::ehTransport
@ ehTransport
Definition: SCT_DetailedSurfaceChargesGenerator.h:77
plotBeamSpotCompare.xd
xd
Definition: plotBeamSpotCompare.py:220
r_e
const std::string r_e
Definition: ASCIICondDbSvc.cxx:16
SCT_DetailedSurfaceChargesGenerator::ExValue150
static double ExValue150(int ix, int iy)
Definition: GetExEy_150V.cxx:442
SCT_DetailedSurfaceChargesGenerator::uniformEFieldModel
@ uniformEFieldModel
Definition: SCT_DetailedSurfaceChargesGenerator.h:81
InDetDD::SolidStateDetectorElementBase::hitLocalToLocal
Amg::Vector2D hitLocalToLocal(double xEta, double xPhi) const
Simulation/Hit local frame to reconstruction local frame.
Definition: SolidStateDetectorElementBase.cxx:95
SCT_DetailedSurfaceChargesGenerator::FEMsolution
@ FEMsolution
Definition: SCT_DetailedSurfaceChargesGenerator.h:83
SCT_DetailedSurfaceChargesGenerator::m_bulk_depth
double m_bulk_depth
Definition: SCT_DetailedSurfaceChargesGenerator.h:163
SCT_DetailedSurfaceChargesGenerator::m_siPropertiesTool
ToolHandle< ISiPropertiesTool > m_siPropertiesTool
Definition: SCT_DetailedSurfaceChargesGenerator.h:150
SiHit::energyLoss
double energyLoss() const
Definition: SiHit.h:175
SCT_DetailedSurfaceChargesGenerator::fixedChargeMap
@ fixedChargeMap
Definition: SCT_DetailedSurfaceChargesGenerator.h:78
SCT_DetailedSurfaceChargesGenerator::m_h_yzRamo
TProfile2D * m_h_yzRamo
Definition: SCT_DetailedSurfaceChargesGenerator.h:199
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
VP1PartSpect::E
@ E
Definition: VP1PartSpectFlags.h:21
charge
double charge(const T &p)
Definition: AtlasPID.h:494
SiHit::xDep
@ xDep
Definition: SiHit.h:162
SCT_DetailedSurfaceChargesGenerator::DriftTime
float DriftTime(float zhit, const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
calculate drift time perpandicular to the surface for a charge at distance zhit from mid gap
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:153
InDetDD::SiDetectorElement
Definition: SiDetectorElement.h:109
InDetDD::SiDetectorElement::isBarrel
bool isBarrel() const
SiHit::truthID
int truthID() const
Definition: SiHit.cxx:208
SiCharge::Process
Process
Definition: SiCharge.h:28
python.PhysicalConstants.c_light
float c_light
Definition: PhysicalConstants.py:63
SiHit::xEta
@ xEta
Definition: SiHit.h:162
SCT_DetailedSurfaceChargesGenerator::m_beta_h
double m_beta_h
Definition: SCT_DetailedSurfaceChargesGenerator.h:176
SiDetectorElement.h
SCT_DetailedSurfaceChargesGenerator::m_h_yzEfield
TProfile2D * m_h_yzEfield
Definition: SCT_DetailedSurfaceChargesGenerator.h:200
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:18
SCT_DetailedSurfaceChargesGenerator::process
virtual void process(const InDetDD::SiDetectorElement *element, const TimedHitPtr< SiHit > &phit, ISiSurfaceChargesInserter &inserter, CLHEP::HepRandomEngine *rndmEngine, const EventContext &ctx) override
create a list of surface charges from a hit
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:249
SCT_DetailedSurfaceChargesGenerator::m_tfix
FloatProperty m_tfix
Definition: SCT_DetailedSurfaceChargesGenerator.h:127
SCT_DetailedSurfaceChargesGenerator::initialize
virtual StatusCode initialize() override
AlgTool initialize.
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:43
SCT_DetailedSurfaceChargesGenerator::m_h_yEfield
TProfile2D * m_h_yEfield
Definition: SCT_DetailedSurfaceChargesGenerator.h:201
SCT_DetailedSurfaceChargesGenerator::electronTransport
void electronTransport(double &x0, double &y0, double *Q_m2, double *Q_m1, double *Q_00, double *Q_p1, double *Q_p2, CLHEP::HepRandomEngine *rndmEngine) const
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:884
SCT_DetailedSurfaceChargesGenerator::m_transportTimeStep
DoubleProperty m_transportTimeStep
Definition: SCT_DetailedSurfaceChargesGenerator.h:144
SiCharge::cut_track
@ cut_track
Definition: SiCharge.h:28
SCT_DetailedSurfaceChargesGenerator::m_biasVoltage
DoubleProperty m_biasVoltage
Definition: SCT_DetailedSurfaceChargesGenerator.h:141
SCT_DetailedSurfaceChargesGenerator::m_tSurfaceDrift
FloatProperty m_tSurfaceDrift
related to the surface drift
Definition: SCT_DetailedSurfaceChargesGenerator.h:125
SCT_BarrelModuleSideDesign.h
y
#define y
TProfile::Fill
int Fill(double, double)
Definition: rootspy.cxx:523
CaloSwCorrections.time
def time(flags, cells_name, *args, **kw)
Definition: CaloSwCorrections.py:242
TimedHitPtr::eventId
unsigned short eventId() const
the index of the component event in PileUpEventInfo.
Definition: TimedHitPtr.h:42
SCT_DetailedSurfaceChargesGenerator::DiffusionSigma
float DiffusionSigma(float zhit, const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
calculate diffusion sigma from a gaussian dist scattered charge
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:185
GlobalVariables.Emax
Emax
Definition: GlobalVariables.py:185
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
SCT_DetailedSurfaceChargesGenerator::m_EyValue150
double m_EyValue150[17][115]
Definition: SCT_DetailedSurfaceChargesGenerator.h:182
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
SCT_DetailedSurfaceChargesGenerator::m_sensorTemperature
DoubleProperty m_sensorTemperature
Definition: SCT_DetailedSurfaceChargesGenerator.h:143
makeTRTBarrelCans.dx
tuple dx
Definition: makeTRTBarrelCans.py:20
python.CaloCondTools.log
log
Definition: CaloCondTools.py:20
SCT_DetailedSurfaceChargesGenerator::m_h_efieldz
TProfile * m_h_efieldz
Definition: SCT_DetailedSurfaceChargesGenerator.h:198
SCT_DetailedSurfaceChargesGenerator::m_vs_e
double m_vs_e
Definition: SCT_DetailedSurfaceChargesGenerator.h:171
SCT_DetailedSurfaceChargesGenerator::m_stripCharge_dx
double m_stripCharge_dx
Definition: SCT_DetailedSurfaceChargesGenerator.h:194
python.SystemOfUnits.ns
int ns
Definition: SystemOfUnits.py:130
SCT_DetailedSurfaceChargesGenerator::flatDiodeModel
@ flatDiodeModel
Definition: SCT_DetailedSurfaceChargesGenerator.h:82
SCT_DetailedSurfaceChargesGenerator::m_strip_pitch
double m_strip_pitch
Definition: SCT_DetailedSurfaceChargesGenerator.h:164
hitTime
float hitTime(const AFP_SIDSimHit &hit)
Definition: AFP_SIDSimHit.h:39
SCT_DetailedSurfaceChargesGenerator::holeTransport
void holeTransport(double &x0, double &y0, double *Q_m2, double *Q_m1, double *Q_00, double *Q_p1, double *Q_p2, CLHEP::HepRandomEngine *rndmEngine)
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:788
SCT_DetailedSurfaceChargesGenerator::m_Ec_h
double m_Ec_h
Definition: SCT_DetailedSurfaceChargesGenerator.h:174
IdentifierHash
Definition: IdentifierHash.h:38
SCT_DetailedSurfaceChargesGenerator::m_eFieldModel
IntegerProperty m_eFieldModel
Definition: SCT_DetailedSurfaceChargesGenerator.h:137
InDetDD::SiDetectorElement::design
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
SCT_DetailedSurfaceChargesGenerator::m_magneticField
DoubleProperty m_magneticField
Definition: SCT_DetailedSurfaceChargesGenerator.h:142
SCT_DetailedSurfaceChargesGenerator::m_Ec_e
double m_Ec_e
Definition: SCT_DetailedSurfaceChargesGenerator.h:172
ISiSurfaceChargesInserter
Definition: ISurfaceChargesGenerator.h:32
SCT_DetailedSurfaceChargesGenerator::m_stripCharge_iymax
int m_stripCharge_iymax
Definition: SCT_DetailedSurfaceChargesGenerator.h:193
SCT_DetailedSurfaceChargesGenerator::m_doTrapping
BooleanProperty m_doTrapping
Definition: SCT_DetailedSurfaceChargesGenerator.h:132
SiHit::localStartPosition
HepGeom::Point3D< double > localStartPosition() const
Definition: SiHit.cxx:146
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35
SCT_DetailedSurfaceChargesGenerator::m_lorentzAngleTool
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
Definition: SCT_DetailedSurfaceChargesGenerator.h:152
SCT_DetailedSurfaceChargesGenerator::MaxDriftTime
float MaxDriftTime(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max drift charge equivalent to the detector thickness
Definition: SCT_DetailedSurfaceChargesGenerator.cxx:198