ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_ChargeTrappingTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
10
13
17
18#include "GaudiKernel/PhysicalConstants.h"
19#include "GaudiKernel/SystemOfUnits.h"
20
21#include "CLHEP/Random/RandFlat.h"
22
23#include <algorithm>
24#include <cmath>
25
26SCT_ChargeTrappingTool::SCT_ChargeTrappingTool(const std::string& type, const std::string& name, const IInterface* parent) :
27 base_class(type, name, parent)
28{
29}
30
31StatusCode
33{
34 if (m_detectorName!="SCT") {
35 ATH_MSG_FATAL("Invalid detector name: " << m_detectorName << ". Must be SCT.");
36 return StatusCode::FAILURE;
37 }
38
39 m_isSCT = (m_detectorName=="SCT");
40
41 // Get conditions summary tool
43 if (not m_siConditionsTool.empty()) {
44 ATH_CHECK(m_siConditionsTool.retrieve());
46 } else {
47 m_siConditionsTool.disable();
49 }
50
51 // Read CondHandle Key
52 ATH_CHECK(m_SCTDetEleCollKey.initialize());
53
54 // initialize PotentialValue
55 for (int ix{0}; ix<81; ix++) {
56 for (int iy{0}; iy<115; iy++) {
57 m_PotentialValue[ix][iy] = getPotentialValue(ix, iy);
58 }
59 }
60
61 return StatusCode::SUCCESS;
62}
63
65{
66 return StatusCode::SUCCESS;
67}
68
69SCT_ChargeTrappingCondData SCT_ChargeTrappingTool::getCondData(const IdentifierHash& elementHash, double pos, const EventContext& ctx) const
70{
71 return calculate(elementHash, pos, ctx);
72}
73
75{
76 const EventContext& ctx{Gaudi::Hive::currentContext()};
77 return getCondData(elementHash, pos, ctx);
78}
79
80void SCT_ChargeTrappingTool::getHoleTransport(double& x0, double& y0, double& xfin, double& yfin, double& Q_m2, double& Q_m1, double& Q_00, double& Q_p1, double& Q_p2, const EventContext& /*ctx*/) const
81{
82 holeTransport(x0, y0, xfin, yfin, Q_m2, Q_m1, Q_00, Q_p1, Q_p2);
83}
84
85void SCT_ChargeTrappingTool::getHoleTransport(double& x0, double& y0, double& xfin, double& yfin, double& Q_m2, double& Q_m1, double& Q_00, double& Q_p1, double& Q_p2) const
86{
87 const EventContext& ctx{Gaudi::Hive::currentContext()};
88 getHoleTransport(x0, y0, xfin, yfin, Q_m2, Q_m1, Q_00, Q_p1, Q_p2, ctx);
89}
90
91
92SCT_ChargeTrappingCondData SCT_ChargeTrappingTool::calculate(const IdentifierHash& elementHash, double pos, const EventContext& ctx) const
93{
94 ATH_MSG_VERBOSE("Updating cache for elementHash = " << elementHash);
95
97 // Only print the warning once.
99 ATH_MSG_WARNING("Conditions Summary Tool is not used. Will use temperature and voltages from job options. "
100 << "Effects of radiation damage may be wrong!");
101 }
102
104
105 const InDetDD::SiDetectorElement* element{getDetectorElement(elementHash, ctx)};
106
107 double temperature{0.};
108 double deplVoltage{0.};
109 double biasVoltage{0.};
110 if (not m_conditionsToolValid) {
111 temperature = m_temperature + Gaudi::Units::STP_Temperature;
112 deplVoltage = m_deplVoltage * Gaudi::Units::volt;
113 biasVoltage = m_biasVoltage * Gaudi::Units::volt;
114 } else {
115 temperature = m_siConditionsTool->temperature(elementHash, ctx) + Gaudi::Units::STP_Temperature;
116 deplVoltage = m_siConditionsTool->depletionVoltage(elementHash, ctx) * Gaudi::Units::volt;
117 biasVoltage = m_siConditionsTool->biasVoltage(elementHash, ctx) * Gaudi::Units::volt;
118 }
119
120 // Protect against invalid temperature
121 double temperatureC{temperature - Gaudi::Units::STP_Temperature};
122 if (not (temperatureC > m_temperatureMin and temperatureC < m_temperatureMax)) {
123 ATH_MSG_WARNING("Invalid temperature: " << temperatureC << " C. "
124 << "Setting to " << m_temperature << " C.");
125 temperature = m_temperature + Gaudi::Units::STP_Temperature;
126 }
127
128 // Calculate depletion depth. If biasVoltage is less than depletionVoltage
129 // the detector is not fully depleted and we need to take this into account.
130 // We take absolute values just in case voltages are signed .
131 double depletionDepth{element->thickness()};
132 if (std::abs(biasVoltage) < std::abs(deplVoltage)) {
133 depletionDepth *= std::sqrt(std::abs(biasVoltage / deplVoltage));
134 // -- if this was the case would need to re-calculate the Ramo Potential and other parameters.
135 }
136
137 double electricField{m_electricFieldTool->getElectricField(pos,//posZ
138 m_fluence,
139 deplVoltage,
140 element->thickness(),
141 std::abs(biasVoltage))};
142 //electric field will be a function of bias voltage and fluence...
143
144 condData.setElectricField(electricField);
145
146 InDet::SiliconProperties siProperties;
147 siProperties.setConditions(temperature, electricField);
148
149 // -- Calculate electron and holes drift mobility and velocity for these conditions (temperature, electricField)
150 // using parametrizations in SiliconProperties (SiPropertiesTool). These will be used later for the trapping model.
151 // In the SCT we collect holes.
152 double electronDriftMobility{0.};
153 double holeDriftMobility{0.};
154 double electronDriftVelocity{0.};
155 double holeDriftVelocity{0.};
156 if(element->carrierType()==InDetDD::electrons) {
157 // electronDriftMobility = siProperties.calcElectronDriftMobility(temperature,electricField);
158 // electronDriftVelocity = electronDriftMobility*electricField;
159 } else {
160 if (m_calcHoles){
161 holeDriftMobility = siProperties.calcHoleDriftMobility(temperature,electricField*Gaudi::Units::volt)*Gaudi::Units::volt;
162 //in this way you could put the electric field in V/mm and the mobility will be in [V mm^2 ns^-1]
163 condData.setHoleDriftMobility(holeDriftMobility);
164 holeDriftVelocity = holeDriftMobility*electricField;
165 }
166 }
167
168 // -- Calculate Trapping Times
169 const double trappingElectrons{1./(m_fluence*m_betaElectrons)};
170 condData.setTrappingElectrons(trappingElectrons);
171
172 double trappingHoles{0.};
173 if (m_calcHoles) {
174 trappingHoles = 1./(m_fluence*m_betaHoles);
175 condData.setTrappingHoles(trappingHoles);
176 }
177
178 // -- Calculate Mean Free Path
179 const double meanFreePathElectrons{electronDriftVelocity*trappingElectrons};
180 condData.setMeanFreePathElectrons(meanFreePathElectrons);
181
182 double meanFreePathHoles{0.};
183 if (m_calcHoles) {
184 meanFreePathHoles = holeDriftVelocity*trappingHoles;
185 condData.setMeanFreePathHoles(meanFreePathHoles);
186 }
187
188 // -- Trapping probability
189 double trappingProbability_electron{0.0};
190 double trappingProbability_hole{0.0};
191 double trappingProbability{0.0};
192 if (element->carrierType()==InDetDD::electrons) {
193 trappingProbability = 1.0 - std::exp(-std::abs(pos/meanFreePathElectrons));
194 trappingProbability_electron = trappingProbability;
195 } else {
196 if (m_calcHoles) {
197 trappingProbability = 1.0 - std::exp(-std::abs(pos/meanFreePathHoles));
198 trappingProbability_hole = trappingProbability;
199 } else {
200 trappingProbability = 0.0;
201 }
202 }
203 condData.setTrappingProbability(trappingProbability);
204
205 // -- Drift time without being trapped
206 const double u{CLHEP::RandFlat::shoot(0., 1.)};
207 const double drift_time{-std::log(u)*trappingHoles};
208 condData.setTrappingTime(drift_time);
209
210 // -- Time to arrive to the electrode
211 const double t_electrode_hole{pos/holeDriftVelocity};
212 condData.setTimeToElectrode(t_electrode_hole);
213
214 // -- Position at which the trapping happened
215 const double trappingPosition_hole{holeDriftVelocity*drift_time};
216 condData.setTrappingPositionZ(trappingPosition_hole);
217
218 //-------------------
219
220 ATH_MSG_VERBOSE("Temperature (C), bias voltage, depletion voltage: "
221 << temperature - Gaudi::Units::STP_Temperature << ", "
222 << biasVoltage/Gaudi::Units::volt << ", "
223 << deplVoltage/Gaudi::Units::volt);
224 ATH_MSG_VERBOSE("Depletion depth: " << depletionDepth/Gaudi::Units::mm);
225 ATH_MSG_VERBOSE("Electric Field: " << electricField/(Gaudi::Units::volt/Gaudi::Units::mm));
226 ATH_MSG_VERBOSE("Electron drift mobility (cm2/V/s): " << electronDriftMobility/(Gaudi::Units::cm2/Gaudi::Units::volt/Gaudi::Units::s));
227 ATH_MSG_VERBOSE("Electron drift velocity (cm/s): " << electronDriftVelocity);
228 ATH_MSG_VERBOSE("Electron mean free path (cm): " << condData.getMeanFreePathElectrons());
229 ATH_MSG_VERBOSE("Electron trapping probability: " << trappingProbability_electron);
230
231 if (m_calcHoles) {
232 ATH_MSG_VERBOSE("Hole drift mobility (cm2/V/s): " << holeDriftMobility/(Gaudi::Units::cm2/Gaudi::Units::volt/Gaudi::Units::s));
233 ATH_MSG_VERBOSE("Hole drift velocity (cm/s): " << holeDriftVelocity);
234 ATH_MSG_VERBOSE("Hole mean free path (cm): " << condData.getMeanFreePathHoles());
235 ATH_MSG_VERBOSE("Hole trapping probability: " << trappingProbability_hole);
236 }
237
238 return condData;
239}
240
241
242
243//-------------------------------------------------------------------------------------------------------------------
244// RAMO POTENTIAL
245//-------------------------------------------------------------------------------------------------------------------
246
247//-------------------------------------------------------------------
248// calculation of induced charge using Weighting (Ramo) function
249//-------------------------------------------------------------------
250double SCT_ChargeTrappingTool::induced(int istrip, double x, double y) const {
251 // x and y are the coorlocation of charge (e or hole)
252 // induced chardege on the strip "istrip" situated at the height y = d
253 // the center of the strip (istrip=0) is x = 0.004 [cm]
254 static const double deltax{0.0005};
255 static const double deltay{0.00025};
256
257 static const double bulk_depth{0.0285}; // in [cm]
258 static const double strip_pitch{0.0080}; // in [cm]
259 // x is width, y is depth
260
261 if ((y < 0.) or (y > bulk_depth)) return 0.;
262 const double xc{strip_pitch * (istrip + 0.5)};
263 const double dx{std::abs(x-xc)};
264 const int ix{static_cast<int>(dx/deltax)};
265 if (ix > 79) return 0.;
266 const int iy{static_cast<int>(y/deltay)};
267 const double fx{(dx - ix*deltax) / deltax};
268 const double fy{(y - iy*deltay) / deltay};
269 const int ix1{ix + 1};
270 const int iy1{iy + 1};
271 const double P{m_PotentialValue[ix ][iy ] * (1.-fx) * (1.-fy)
272 + m_PotentialValue[ix1][iy ] * fx * (1.-fy)
273 + m_PotentialValue[ix ][iy1] * (1.-fx) * fy
274 + m_PotentialValue[ix1][iy1] * fx * fy};
275 ATH_MSG_DEBUG("induced: x,y,iy="<<x<<" "<<y<<" "<<iy<<" istrip,xc,dx,ix="
276 <<istrip<<" "<<xc<<" " <<dx<<" "<<ix<<" fx,fy="<<fx <<" " <<fy<< ", P="<<P);
277
278 return P;
279}
280
281
282//---------------------------------------------------------------------
283// holeTransport
284//---------------------------------------------------------------------
285void SCT_ChargeTrappingTool::holeTransport(double& x0, double& y0, double& xfin, double& yfin, double& Q_m2, double& Q_m1, double& Q_00, double& Q_p1, double& Q_p2) const {
286 // transport holes in the bulk
287 // T. Kondo, 2010.9.9
288 // External parameters to be specified
289 // m_transportTimeMax [nsec]
290 // m_transportTimeStep [nsec]
291 // bulk_depth [cm]
292 // Induced currents are added to
293 // Q_m2,Q_m1,Q_00,Q_p1,Q_p2
294 //
295 // initPotentialValue(); // <-this has to go into the main
296
297 // x is width, y is depth
298
299 double x{x0/10.}; // original hole position [cm]
300 double y{y0/10.}; // original hole position [cm]
301 double qstrip[5];
302
303 for (int istrip{-2}; istrip < 3 ; istrip++) {
304 qstrip[istrip+2] = induced(istrip, x, y);
305 }
306 ATH_MSG_DEBUG("h:qstrip=" << qstrip[0] << " " << qstrip[1] << " " << qstrip[2] << " " << qstrip[3] << " " << qstrip[4]);
307
308 // Get induced current by subtracting induced charges
309 for (int istrip{-2}; istrip < 3 ; istrip++) {
310 x = xfin/10.;
311 y = yfin/10.;
312 const double qnew{induced(istrip, x, y)};
313 int jj{istrip + 2};
314 const double dq{qnew - qstrip[jj]};
315 qstrip[jj] = qnew;
316 ATH_MSG_DEBUG("dq= " << dq);
317 switch(istrip) {
318 case -2: Q_m2 += dq ; break;
319 case -1: Q_m1 += dq ; break;
320 case 0: Q_00 += dq ; break;
321 case +1: Q_p1 += dq ; break;
322 case +2: Q_p2 += dq ; break;
323 // default: break; // Coverity complains the default is deadcode.
324 }
325 }
326 ATH_MSG_DEBUG("h:qstrip=" << qstrip[0] << " " << qstrip[1] << " " << qstrip[2] << " " << qstrip[3] << " " << qstrip[4]);
327}
328
329double
331 return ::getPotentialValue(ix, iy);
332}
333
334const InDetDD::SiDetectorElement* SCT_ChargeTrappingTool::getDetectorElement(const IdentifierHash& waferHash, const EventContext& ctx) const {
336 if (not condData.isValid()) return nullptr;
337 return condData->getDetectorElement(waferHash);
338}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
static Double_t P(Double_t *tt, Double_t *par)
#define y
#define x
This is a "hash" representation of an Identifier.
Class to hold geometrical description of a silicon detector element.
InDetDD::CarrierType carrierType() const
carrier type for readout.
void setConditions(double temperature, double electricField)
double calcHoleDriftMobility(double temperature, double electricField) const
Data object for SCT_ChargeTrappingTool, SCT_RadDamageSummaryTool, SCT_SurfaceChargesGenerator.
void setTrappingTime(const double trappingTime)
void setHoleDriftMobility(const double holeDriftMobility)
void setTrappingHoles(const double trappingHoles)
void setTrappingProbability(const double trappingProbability)
void setTimeToElectrode(const double electrodeTime)
void setTrappingPositionZ(const double trappingPosition)
void setMeanFreePathHoles(const double meanFreePathHoles)
void setTrappingElectrons(const double trappingElectrons)
void setMeanFreePathElectrons(const double meanFreePathElectrons)
void setElectricField(const double electricField)
ToolHandle< ISiliconConditionsTool > m_siConditionsTool
virtual StatusCode initialize() override
SCT_ChargeTrappingCondData calculate(const IdentifierHash &elementHash, double pos, const EventContext &ctx) const
void holeTransport(double &x0, double &y0, double &xfin, double &yfin, double &Q_m2, double &Q_m1, double &Q_00, double &Q_p1, double &Q_p2) const
ToolHandle< ISCT_ElectricFieldTool > m_electricFieldTool
virtual void getHoleTransport(double &x0, double &y0, double &xfin, double &yfin, double &Q_m2, double &Q_m1, double &Q_00, double &Q_p1, double &Q_p2, const EventContext &ctx) const override
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_SCTDetEleCollKey
std::atomic_bool m_conditionsToolWarning
virtual SCT_ChargeTrappingCondData getCondData(const IdentifierHash &elementHash, double pos, const EventContext &ctx) const override
double induced(int istrip, double x, double y) const
static double getPotentialValue(int &ix, int &iy)
SCT_ChargeTrappingTool(const std::string &type, const std::string &name, const IInterface *parent)
virtual StatusCode finalize() override
const InDetDD::SiDetectorElement * getDetectorElement(const IdentifierHash &waferHash, const EventContext &ctx) const