ATLAS Offline Software
Loading...
Searching...
No Matches
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
35SCT_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
95 m_smallStepLength.setValue(m_smallStepLength.value() * CLHEP::micrometer);
96 m_tSurfaceDrift.setValue(m_tSurfaceDrift.value() * CLHEP::ns);
97
98 // Surface drift time calculation Stuff
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//----------------------------------------------------------------------
153float 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//----------------------------------------------------------------------
185float 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//----------------------------------------------------------------------
198float 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//----------------------------------------------------------------------
211float 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 {
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//-------------------------------------------------------------------------------------------
249void 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//-------------------------------------------------------------------------------------------
259void 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,ctx)};
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 ------------
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//---------------------------------------------------------------
613bool 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//---------------------------------------------------------------
639bool 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//-------------------------------------------------------------------
669double 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//--------------------------------------------------------------
699void 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 {
724 Ey = Emax*(1-(m_bulk_depth-y)/m_depletion_depth);
725 }
726 return;
727 }
728
729 //---------- case for FEM analysis solution -------------------------
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//---------------------------------------------------------------------
788void 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//---------------------------------------------------------------------
884void 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;
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) {
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//---------------------------------------------------------------------
969double 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.;
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}
float hitTime(const AFP_SIDSimHit &hit)
const std::string r_e
#define M_PI
Scalar mag() const
mag method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
double charge(const T &p)
Definition AtlasPID.h:997
static Double_t P(Double_t *tt, Double_t *par)
static Double_t rc
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...
#define y
#define x
constexpr int pow(int base, int exp) noexcept
This is a "hash" representation of an Identifier.
double thickness() const
Method which returns thickness of the silicon wafer.
int readoutSide() const
ReadoutSide.
Barrel module design description for the SCT.
double phiStripPatternCentre() const
centre of the strip pattern in phi
Base class for the SCT module side design, extended by the Forward and Barrel module design.
virtual double scaledDistanceToNearestDiode(const SiLocalPosition &chargePos) const =0
give distance to the nearest diode in units of pitch, from 0.0 to 0.5, this method should be fast as ...
virtual bool inActiveArea(const SiLocalPosition &chargePos, bool checkBondGap=true) const =0
check if the position is in active area
virtual double stripPitch(const SiLocalPosition &chargePos) const =0
give the strip pitch (dependence on position needed for forward)
Class to hold geometrical description of a silicon detector element.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT For Pixel: ...
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
virtual const Amg::Vector3D & center() const override final
Center in global coordinates.
Amg::Vector2D hitLocalToLocal(double xEta, double xPhi) const
Simulation/Hit local frame to reconstruction local frame.
ToolHandle< ISiliconConditionsTool > m_siConditionsTool
bool electron(double x_e, double y_e, double &vx_e, double &vy_e, double &D_e) const
FloatProperty m_tSurfaceDrift
related to the surface drift
virtual StatusCode finalize() override
AlgTool finalize.
virtual StatusCode initialize() override
AlgTool initialize.
float MaxDriftTime(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max drift charge equivalent to the detector thickness
float m_distInterStrip
Inter strip distance normalized to 1.
float MaxDiffusionSigma(const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
max sigma diffusion
void processSiHit(const InDetDD::SiDetectorElement *element, const SiHit &phit, ISiSurfaceChargesInserter &inserter, const float eventTime, const unsigned short eventID, CLHEP::HepRandomEngine *rndmEngine, const EventContext &ctx)
SCT_DetailedSurfaceChargesGenerator(const std::string &type, const std::string &name, const IInterface *parent)
constructor
void EField(double x, double y, double &Ex, double &Ey) const
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
float m_distHalfInterStrip
Half way distance inter strip.
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
FloatProperty m_smallStepLength
max internal step along the larger G4 step
void holeTransport(double &x0, double &y0, double *Q_m2, double *Q_m1, double *Q_00, double *Q_p1, double *Q_p2, CLHEP::HepRandomEngine *rndmEngine)
double induced(int istrip, double x, double y) const
float DiffusionSigma(float zhit, const InDetDD::SiDetectorElement *element, const EventContext &ctx) const
calculate diffusion sigma from a gaussian dist scattered charge
float SurfaceDriftTime(float ysurf) const
Calculate of the surface drift time.
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
static double ExValue150(int ix, int iy)
bool hole(double x_h, double y_h, double &vx_h, double &vy_h, double &D_h)
static double EyValue150(int ix, int iy)
double inducedCharge(int &istrip, double &x, double &y, double &t) const
@ cut_track
Definition SiCharge.h:28
Definition SiHit.h:19
double energyLoss() const
Definition SiHit.h:175
int truthID() const
Definition SiHit.cxx:208
HepGeom::Point3D< double > localStartPosition() const
Definition SiHit.cxx:146
@ xPhi
Definition SiHit.h:162
@ xEta
Definition SiHit.h:162
@ xDep
Definition SiHit.h:162
int truthBarcode() const
Definition SiHit.cxx:202
const HepMcParticleLink & particleLink() const
Definition SiHit.h:190
HepGeom::Point3D< double > localEndPosition() const
Definition SiHit.cxx:153
a smart pointer to a hit that also provides access to the extended timing info of the host event.
Definition TimedHitPtr.h:18
unsigned short eventId() const
the index of the component event in PileUpEventInfo.
Definition TimedHitPtr.h:47
float eventTime() const
t0 offset of the bunch xing containing the hit in ns.
Definition TimedHitPtr.h:55