CbmRoot
Loading...
Searching...
No Matches
CbmStsSimSensorDssd.cxx
Go to the documentation of this file.
1/* Copyright (C) 2017-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
10#include "CbmStsSimSensorDssd.h"
11
12#include "CbmStsDefs.h"
13#include "CbmStsDigitize.h"
14#include "CbmStsParSensorCond.h"
15#include "CbmStsParSim.h"
16#include "CbmStsSensorPoint.h"
17#include "CbmStsSetup.h"
18#include "CbmStsSimModule.h"
19
20#include <sstream>
21
22
23using std::string;
24using std::stringstream;
25using namespace CbmSts;
26
27
28// ----- Constructor ---------------------------------------------------
30// -------------------------------------------------------------------------
31
32
33// ----- Process one MC Point -------------------------------------------
35{
36
37 // --- Catch if parameters are not set
38 assert(fIsSet);
39
40 // --- Number of created charge signals (coded front/back side)
41 Int_t nSignals = 0;
42
43 // --- Reset the strip charge arrays
44 fStripCharge[0].Reset(); // front side
45 fStripCharge[1].Reset(); // back side
46
47 // --- Produce charge and propagate it to the readout strips
48 ProduceCharge(point);
49
50 // --- Cross talk
51 if (fSettings->CrossTalk()) {
52 Double_t ctcoeff = GetConditions()->GetCrossTalkCoeff();
53 CrossTalk(ctcoeff);
54 }
55
56 // --- Stop here if no module is connected (e.g. for test purposes)
57 if (!GetModule()) return 0;
58
59 // --- Register charges in strips to the module
60 Int_t nCharges[2] = {0, 0};
61 for (Int_t side = 0; side < 2; side++) { // front and back side
62
63 for (Int_t strip = 0; strip < GetNofStrips(side); strip++) {
64 if (fStripCharge[side][strip] > 0.) {
65 RegisterCharge(side, strip, fStripCharge[side][strip], point->GetTime());
66 nCharges[side]++;
67 } //? charge in strip
68 } //# strips
69
70 } //# front and back side
71
72 // Code number of signals
73 nSignals = 1000 * nCharges[0] + nCharges[1];
74
75 return nSignals;
76}
77// -------------------------------------------------------------------------
78
79
80// ----- Charge status -------------------------------------------------
82{
83 stringstream ss;
84 ss << GetName() << ": Charge status: \n";
85 for (Int_t side = 0; side < 2; side++) {
86 for (Int_t strip = 0; strip < GetNofStrips(side); strip++) {
87 if (fStripCharge[side][strip] > 0.)
88 ss << " " << (side ? "Back " : "Front ") << "strip " << strip << " charge "
89 << fStripCharge[side][strip] << "\n";
90 } //# strips
91 } //# front and back side
92 ss << " Total: front side " << (fStripCharge[0]).GetSum() << ", back side " << (fStripCharge[1]).GetSum();
93 return ss.str();
94}
95// -------------------------------------------------------------------------
96
97
98// ----- Cross talk calculation ----------------------------------------
99void CbmStsSimSensorDssd::CrossTalk(Double_t ctcoeff)
100{
101
102 for (Int_t side = 0; side < 2; side++) { // front and back side
103
104 // Number of strips for this side
105 Int_t nStrips = GetNofStrips(side);
106
107 // First strip
108 Double_t qLeft = 0.;
109 Double_t qCurrent = fStripCharge[side][0];
110 fStripCharge[side][0] = (1. - ctcoeff) * qCurrent + ctcoeff * fStripCharge[side][1];
111
112 // Strips 1 to n-2
113 for (Int_t strip = 1; strip < nStrips - 1; strip++) {
114 qLeft = qCurrent;
115 qCurrent = fStripCharge[side][strip];
116 fStripCharge[side][strip] = ctcoeff * (qLeft + fStripCharge[side][strip + 1]) + (1. - 2. * ctcoeff) * qCurrent;
117 } //# strips
118
119 // Last strip
120 qLeft = qCurrent;
121 qCurrent = fStripCharge[side][nStrips - 1];
122 fStripCharge[side][nStrips - 1] = ctcoeff * qLeft + (1. - ctcoeff) * qCurrent;
123
124 } //# front and back side
125}
126// -------------------------------------------------------------------------
127
128
129// ----- Check whether a point is inside the active area ---------------
130Bool_t CbmStsSimSensorDssd::IsInside(Double_t x, Double_t y)
131{
132 if (x < -fDx / 2.) return kFALSE;
133 if (x > fDx / 2.) return kFALSE;
134 if (y < -fDy / 2.) return kFALSE;
135 if (y > fDy / 2.) return kFALSE;
136 return kTRUE;
137}
138// -------------------------------------------------------------------------
139
140
141// ----- Lorentz shift -------------------------------------------------
142Double_t CbmStsSimSensorDssd::LorentzShift(Double_t z, Int_t chargeType, Double_t bY) const
143{
144
145 assert(chargeType == 0 || chargeType == 1);
146
147 // --- Drift distance to readout plane
148 // Electrons drift to the front side (z = d/2), holes to the back side (z = -d/2)
149 assert(chargeType == 0 || chargeType == 1);
150 Double_t driftZ = 0.;
151 if (chargeType == 0) driftZ = fDz / 2. - z; // electrons
152 else if (chargeType == 1)
153 driftZ = fDz / 2. + z; // holes
154 else
155 driftZ = 0.;
156
157 // --- Hall mobility
158 Double_t vBias = GetConditions()->GetVbias();
159 Double_t vFd = GetConditions()->GetVfd();
160 Double_t eField = CbmStsPhysics::ElectricField(vBias, vFd, fDz, z + fDz / 2.);
161 Double_t eFieldMax = CbmStsPhysics::ElectricField(vBias, vFd, fDz, fDz);
162 Double_t eFieldMin = CbmStsPhysics::ElectricField(vBias, vFd, fDz, 0.);
163
164 Double_t muHall;
165 if (chargeType == 0) // electrons
166 muHall = GetConditions()->GetHallMobility((eField + eFieldMax) / 2., chargeType);
167 else // holes
168 muHall = GetConditions()->GetHallMobility((eField + eFieldMin) / 2., chargeType);
169
170 // --- The direction of the shift is the same for electrons and holes.
171 // --- Holes drift in negative z direction, the field is in
172 // --- positive y direction, thus the Lorentz force v x B acts in positive
173 // --- x direction. Electrons drift in the opposite (positive z) direction,
174 // --- but the have also the opposite charge sign, so the Lorentz force
175 // --- on them is also in the positive x direction.
176 Double_t shift = muHall * bY * driftZ * 1.e-4;
177 // The factor 1.e-4 is because bZ is in T = Vs/m**2, but muHall is in
178 // cm**2/(Vs) and z in cm.
179
180 return shift;
181}
182// -------------------------------------------------------------------------
183
184
185// ----- Produce charge and propagate it to the readout strips ---------
187{
188
189 // Energy-loss model
190 CbmStsELoss eLossModel = fSettings->ELossModel();
191
192 // Total charge created in the sensor: is calculated from the energy loss
193 Double_t chargeTotal = point->GetELoss() / CbmStsPhysics::PairCreationEnergy(); // in e
194
195 // For ideal energy loss, just have all charge in the mid-point of the
196 // trajectory
197 if (eLossModel == CbmStsELoss::kIdeal) {
198 Double_t xP = 0.5 * (point->GetX1() + point->GetX2());
199 Double_t yP = 0.5 * (point->GetY1() + point->GetY2());
200 Double_t zP = 0.5 * (point->GetZ1() + point->GetZ2());
201 PropagateCharge(xP, yP, zP, chargeTotal, point->GetBy(), 0); // front side (n)
202 PropagateCharge(xP, yP, zP, chargeTotal, point->GetBy(), 1); // back side (p)
203 return;
204 }
205
206 // Kinetic energy
207 Double_t mass = CbmStsPhysics::ParticleMass(point->GetPid());
208 Double_t eKin = TMath::Sqrt(point->GetP() * point->GetP() + mass * mass) - mass;
209
210 // Length of trajectory inside sensor and its projections
211 Double_t trajLx = point->GetX2() - point->GetX1();
212 Double_t trajLy = point->GetY2() - point->GetY1();
213 Double_t trajLz = point->GetZ2() - point->GetZ1();
214 Double_t trajLength = TMath::Sqrt(trajLx * trajLx + trajLy * trajLy + trajLz * trajLz);
215
216 // The trajectory is sub-divided into equidistant steps, with a step size
217 // close to 3 micrometer.
218 Double_t stepSizeTarget = 3.e-4; // targeted step size is 3 micrometer
219 Int_t nSteps = TMath::Nint(trajLength / stepSizeTarget);
220 if (nSteps == 0) nSteps = 1; // assure at least one step
221 Double_t stepSize = trajLength / nSteps;
222 Double_t stepSizeX = trajLx / nSteps;
223 Double_t stepSizeY = trajLy / nSteps;
224 Double_t stepSizeZ = trajLz / nSteps;
225
226 // Average charge per step, used for uniform distribution
227 Double_t chargePerStep = chargeTotal / nSteps;
228
229 // Stopping power, needed for energy loss fluctuations
230 Double_t dedx = 0.;
231
232 if (eLossModel == CbmStsELoss::kUrban) dedx = CbmStsPhysics::Instance()->StoppingPower(eKin, point->GetPid());
233
234 // Stepping over the trajectory
235 Double_t chargeSum = 0.;
236 Double_t xStep = point->GetX1() - 0.5 * stepSizeX;
237 Double_t yStep = point->GetY1() - 0.5 * stepSizeY;
238 Double_t zStep = point->GetZ1() - 0.5 * stepSizeZ;
239 for (Int_t iStep = 0; iStep < nSteps; iStep++) {
240 xStep += stepSizeX;
241 yStep += stepSizeY;
242 zStep += stepSizeZ;
243
244 // Charge for this step
245 Double_t chargeInStep = chargePerStep; // uniform energy loss
246 if (eLossModel == CbmStsELoss::kUrban) // energy loss fluctuations
247 chargeInStep =
249 chargeSum += chargeInStep;
250
251 // Propagate charge to strips
252 PropagateCharge(xStep, yStep, zStep, chargeInStep, point->GetBy(), 0); // front
253 PropagateCharge(xStep, yStep, zStep, chargeInStep, point->GetBy(), 1); // back
254
255 } //# steps of the trajectory
256
257 // For fluctuations: normalise to the total charge from GEANT.
258 // Since the number of steps is finite (about 100), the average
259 // charge per step does not coincide with the expectation value.
260 // In order to be consistent with the transport, the charges are
261 // re-normalised.
262 if (eLossModel == CbmStsELoss::kUrban) {
263 for (Int_t side = 0; side < 2; side++) { // front and back side
264 for (Int_t strip = 0; strip < GetNofStrips(side); strip++)
265 fStripCharge[side][strip] *= (chargeTotal / chargeSum);
266 } //# front and back side
267 } //? E loss fluctuations
268}
269// -------------------------------------------------------------------------
270
271
272// ----- Register charge to the module ----------------------------------
273void CbmStsSimSensorDssd::RegisterCharge(Int_t side, Int_t strip, Double_t charge, Double_t time) const
274{
275
276 // --- Check existence of module
277 assert(GetModule());
278
279 // --- Determine module channel for given sensor strip
280 Int_t channel = GetModuleChannel(strip, side, GetSensorId());
281
282 // --- Get the MC link information
283 Int_t index = GetCurrentLink().GetIndex();
284 Int_t entry = GetCurrentLink().GetEntry();
285 Int_t file = GetCurrentLink().GetFile();
286
287 // --- Send signal to module
288 GetModule()->AddSignal(channel, time, charge, index, entry, file);
289}
290// -------------------------------------------------------------------------
291
292
ClassImp(CbmConverterManager)
CbmStsELoss
Energy loss model used in simulation.
Definition CbmStsDefs.h:49
Class representing an element of the STS setup.
Double_t GetVbias() const
Bias voltage.
Double_t GetHallMobility(Double_t eField, Int_t chargeType) const
Hall mobility.
Double_t GetCrossTalkCoeff() const
Cross-talk coefficient.
CbmStsELoss ELossModel() const
Energy loss model.
Bool_t CrossTalk() const
Check whether cross-talk is applied.
static Double_t PairCreationEnergy()
Energy for electron-hole pair creation in silicon.
static Double_t ElectricField(Double_t vBias, Double_t vFd, Double_t dZ, Double_t z)
Electric field magnitude in a silicon sensor as function of z.
static Double_t ParticleMass(Int_t pid)
Particle mass from PDG particle ID.
static CbmStsPhysics * Instance()
Accessor to singleton instance.
Double_t StoppingPower(Double_t eKin, Int_t pid)
Stopping power (average specific energy loss) in Silicon.
Double_t EnergyLoss(Double_t dz, Double_t mass, Double_t eKin, Double_t dedx) const
Energy loss in a Silicon layer.
Container class for a local point in a STS sensor.
Int_t GetPid() const
Particle ID [PDG].
Double_t GetY2() const
Exit y coordinate [cm].
Double_t GetY1() const
Entry y coordinate [cm].
Double_t GetP() const
Momentum magnitude.
Double_t GetX1() const
Entry x coordinate [cm].
Double_t GetZ1() const
Entry z coordinate [cm].
Double_t GetBy() const
By-Field at midpoint [T].
Double_t GetX2() const
Exit x coordinate [cm].
Double_t GetTime() const
Time [ns].
Double_t GetZ2() const
Exit z coordinate [cm].
Double_t GetELoss() const
Energy loss [GeV].
void AddSignal(UShort_t channel, Double_t time, Double_t charge, Int_t index=0, Int_t entry=0, Int_t file=0)
Abstract class for the simulation of double-sided silicon strip sensors.
std::string ChargeStatus() const
Print charge status.
Bool_t IsInside(Double_t x, Double_t y)
Double_t fDz
Thickness in z [cm].
virtual Int_t GetNofStrips(Int_t side) const =0
Number of strips on front and back side.
virtual void PropagateCharge(Double_t x, Double_t y, Double_t z, Double_t charge, Double_t bY, Int_t side)=0
void ProduceCharge(CbmStsSensorPoint *point)
Generate charge as response to a sensor point.
Bool_t fIsSet
Flag whether sensor is properly initialised.
Double_t fDx
Dimension of active area in x [cm].
CbmStsSimSensorDssd(CbmStsElement *element=nullptr)
Standard constructor.
Double_t fDy
Dimension of active area in y [cm].
virtual Int_t CalculateResponse(CbmStsSensorPoint *point)
Analogue response to a track in the sensor.
Double_t LorentzShift(Double_t z, Int_t chargeType, Double_t bY) const
Lorentz shift in the x coordinate.
void CrossTalk(Double_t ctCoeff)
void RegisterCharge(Int_t side, Int_t strip, Double_t charge, Double_t time) const
Register the produced charge in one strip to the module.
virtual Int_t GetModuleChannel(Int_t strip, Int_t side, Int_t sensorId) const =0
Get the readout channel in the module for a given strip.
Class for the simulation of a sensor in the CBM-STS.
CbmStsSimModule * GetModule() const
Simulation module.
Int_t GetSensorId() const
Sensor ID.
const CbmLink & GetCurrentLink() const
Current link object.
const CbmStsParSensorCond * GetConditions() const
Sensor conditions.
const CbmStsParSim * fSettings
Simulation module.