3#if defined(__GPUCOMPILE__) || !defined(G_SENSOR_H)
5#if !defined(__GPUCOMPILE__) && !defined(G_SENSOR_H)
28#if defined(__GPUCONST__)
35#define __GPUCONST__ const
44class GARFIELD_CLASS_NAME(Sensor) {
53 Sensor(Component* comp);
55 void AddComponent(Component* comp);
57 size_t GetNumberOfComponents()
const {
return m_components.size(); }
59 Component* GetComponent(
const unsigned int i);
61 void EnableComponent(
const unsigned int i,
const bool on);
63 void EnableMagneticField(
const unsigned int i,
const bool on);
65 bool HasMagneticField()
const;
68 void AddElectrode(Component* comp,
const std::string& label);
70 size_t GetNumberOfElectrodes()
const {
return m_electrodes.size(); }
72 void ClearElectrodes();
77 void ElectricField(
const double x,
const double y,
const double z,
double& ex,
78 double& ey,
double& ez,
double& v, Medium*& medium,
83 void ElectricField(
const double x,
const double y,
const double z,
double& ex,
84 double& ey,
double& ez,
90 void MagneticField(
const double x,
const double y,
const double z,
double& bx,
91 double& by,
double& bz,
int& status);
94 void WeightingField(
const double x,
const double y,
const double z,
95 double& wx,
double& wy,
double& wz,
96 const std::string& label);
98 double WeightingPotential(
const double x,
const double y,
const double z,
99 const std::string& label);
102 double DelayedWeightingPotential(
const double x,
const double y,
103 const double z,
const double t,
104 const std::string& label);
107 Medium* GetMedium(
const double x,
const double y,
const double z);
110 void EnableDebugging(
const bool on =
true) { m_debug = on; }
113 bool SetArea(
const bool verbose =
false);
115 bool SetArea(
const double xmin,
const double ymin,
const double zmin,
116 const double xmax,
const double ymax,
const double zmax);
118 bool GetArea(
double& xmin,
double& ymin,
double& zmin,
double& xmax,
119 double& ymax,
double& zmax);
123 bool IsInArea(
const double x,
const double y,
const double z)
__GPUCONST__;
125#ifndef __GPUCOMPILE__
127 bool IsInside(
const double x,
const double y,
const double z);
130 bool GetVoltageRange(
double& vmin,
double& vmax);
133 void NewSignal() { ++m_nEvents; }
138 __device__ void AddSignal(
const double q,
const double t0,
const double t1,
139 const double x0,
const double y0,
const double z0,
140 const double x1,
const double y1,
const double z1,
141 const bool integrateWeightingField,
142 const bool useWeightingPotential,
143 const int particle_idx);
146#ifndef __GPUCOMPILE__
152 void SetTimeWindow(
const double tstart,
const double tstep,
153 const unsigned int nsteps);
155 void GetTimeWindow(
double& tstart,
double& tstep,
156 unsigned int& nsteps)
const {
159 nsteps = m_nTimeBins;
163 void EnableDelayedSignal(
const bool on =
true) { m_delayedSignal = on; }
165 void SetDelayedSignalTimes(
const std::vector<double>& ts);
170 void SetDelayedSignalAveragingOrder(
const unsigned int navg) {
171 m_nAvgDelayedSignal = navg;
175 void SetSignal(
const std::string& label,
const unsigned int bin,
176 const double signal);
178 void SetSignal(
const std::string& label,
const std::vector<double>& ts,
179 const std::vector<double>& is);
181 double GetSignal(
const std::string& label,
const unsigned int bin);
183 double GetSignal(
const std::string& label,
const unsigned int bin,
186 double GetPromptSignal(
const std::string& label,
const unsigned int bin);
188 double GetDelayedSignal(
const std::string& label,
const unsigned int bin);
190 double GetElectronSignal(
const std::string& label,
const unsigned int bin);
192 double GetIonSignal(
const std::string& label,
const unsigned int bin);
194 double GetDelayedElectronSignal(
const std::string& label,
195 const unsigned int bin);
197 double GetDelayedIonSignal(
const std::string& label,
const unsigned int bin);
199 double GetInducedCharge(
const std::string& label);
202 void SetTransferFunction(std::function<
double(
double)>);
204 void SetTransferFunction(
const std::vector<double>& times,
205 const std::vector<double>& values);
207 void SetTransferFunction(Shaper& shaper);
209 double GetTransferFunction(
const double t);
211 void PrintTransferFunction();
213 void PlotTransferFunction();
216 void EnableTransferFunctionCache(
const bool on =
true) {
217 m_cacheTransferFunction = on;
221 bool ConvoluteSignal(
const std::string& label,
const bool fft =
false);
223 bool ConvoluteSignals(
const bool fft =
false);
225 bool IntegrateSignal(
const std::string& label);
227 bool IntegrateSignals();
229 bool IsIntegrated(
const std::string& label)
const;
236 bool DelayAndSubtractFraction(
const double td,
const double f);
238 void SetNoiseFunction(
double (*f)(
double t));
240 void AddNoise(
const bool total =
true,
const bool electron =
false,
241 const bool ion =
false);
250 void AddWhiteNoise(
const std::string& label,
const double enc,
251 const bool poisson =
true,
const double q0 = 1.);
253 void AddWhiteNoise(
const double enc,
const bool poisson =
true,
254 const double q0 = 1.);
261 bool ComputeThresholdCrossings(
const double thr,
const std::string& label,
265 size_t GetNumberOfThresholdCrossings()
const {
266 return m_thresholdCrossings.size();
275 bool GetThresholdCrossing(
const unsigned int i,
double& time,
double& level,
280 void AddSignalWeightingPotential(
281 const double q,
const std::vector<double>& ts,
282 const std::vector<std::array<double, 3> >& xs);
285 void AddSignalWeightingPotential(
286 const double q,
const std::vector<double>& ts,
287 const std::vector<std::array<double, 3> >& xs,
288 const std::vector<double>& qs);
291 void AddSignalWeightingField(
const double q,
const std::vector<double>& ts,
292 const std::vector<std::array<double, 3> >& xs,
293 const bool integrateWeightingField);
297 void AddSignalWeightingField(
const double q,
const std::vector<double>& ts,
298 const std::vector<std::array<double, 3> >& xs,
299 const std::vector<std::array<double, 3> >& vs,
300 const std::vector<double>& ns,
const int navg);
303 void PlotSignal(
const std::string& label, TPad* pad,
304 const std::string optTotal =
"t",
305 const std::string optPrompt =
"",
306 const std::string optDelayed =
"");
308 void ExportSignal(
const std::string& label,
const std::string& filename,
309 const bool chargeCariers =
false)
const;
312 void AddInducedCharge(
const double q,
const double x0,
const double y0,
313 const double z0,
const double x1,
const double y1,
318 bool CrossedWire(
const double x0,
const double y0,
const double z0,
319 const double x1,
const double y1,
const double z1,
320 double& xc,
double& yc,
double& zc,
const bool centre,
323 bool InTrapRadius(
const double q0,
const double x0,
const double y0,
324 const double z0,
double& xw,
double& yw,
double& rw);
327 bool CrossedPlane(
const double x0,
const double y0,
const double z0,
328 const double x1,
const double y1,
const double z1,
329 double& xc,
double& yc,
double& zc);
333 double IntegrateFluxLine(
const double x0,
const double y0,
const double z0,
334 const double x1,
const double y1,
const double z1,
335 const double xp,
const double yp,
const double zp,
336 const unsigned int nI,
const int isign = 0);
338 double GetTotalInducedCharge(
const std::string& label);
340 double StepSizeHint();
343 double CreateGPUTransferObject(SensorGPU*& sensor_gpu);
346 void TransferGPUElectrodeSignals(SensorGPU*& sensor_gpu);
350 std::string m_className =
"Sensor";
357 ComponentGPU** m_components =
nullptr;
358 size_t m_numComponents;
361 std::vector<std::tuple<Component*, bool, bool> > m_components;
364#ifndef __GPUCOMPILE__
368 std::vector<double> signal;
369 std::vector<double> delayedSignal;
370 std::vector<double> electronSignal;
371 std::vector<double> ionSignal;
372 std::vector<double> delayedElectronSignal;
373 std::vector<double> delayedIonSignal;
378 std::vector<Electrode> m_electrodes;
380 struct ElectrodeGPU {
386 ElectrodeGPU* m_electrodes =
nullptr;
387 size_t m_numElectrodes;
391 double m_tStart = 0.;
392 double m_tStep = 10.;
393 unsigned int m_nTimeBins = 200;
394 unsigned int m_nEvents = 0;
395#ifndef __GPUCOMPILE__
396 bool m_delayedSignal =
false;
397 std::vector<double> m_delayedSignalTimes;
398 unsigned int m_nAvgDelayedSignal = 0;
401 std::function<double(
double)> m_fTransfer;
402 Shaper* m_shaper =
nullptr;
403 std::vector<std::pair<double, double> > m_fTransferTab;
404 bool m_cacheTransferFunction =
true;
406 double m_fTransferSq = -1.;
408 std::vector<double> m_fTransferFFT;
411 double (*m_fNoise)(
double t) =
nullptr;
413 std::vector<std::pair<double, bool> > m_thresholdCrossings;
414 double m_thresholdLevel = 0.;
418 double m_xMinUser = 0., m_yMinUser = 0., m_zMinUser = 0.;
419 double m_xMaxUser = 0., m_yMaxUser = 0., m_zMaxUser = 0.;
420 bool m_hasUserArea =
false;
422#ifndef __GPUCOMPILE__
424 bool m_debug =
false;
427 bool GetBoundingBox(
double& xmin,
double& ymin,
double& zmin,
double& xmax,
428 double& ymax,
double& zmax);
430 void FillSignal(Electrode& electrode,
const double q,
431 const std::vector<double>& ts,
const std::vector<double>& is,
432 const int navg,
const bool delayed =
false);
433 void FillBin(Electrode& electrode,
const unsigned int bin,
434 const double signal,
const bool electron,
const bool delayed) {
435 std::lock_guard<std::mutex> guard(m_mutex);
436 electrode.signal[bin] += signal;
437 if (delayed) electrode.delayedSignal[bin] += signal;
439 electrode.electronSignal[bin] += signal;
440 if (delayed) electrode.delayedElectronSignal[bin] += signal;
442 electrode.ionSignal[bin] += signal;
443 if (delayed) electrode.delayedIonSignal[bin] += signal;
447 __device__ void FillBin(ElectrodeGPU& electrode,
const unsigned int bin,
448 const double signal,
const bool electron,
449 const bool delayed,
const int particle_idx);
452#ifndef __GPUCOMPILE__
453 void IntegrateSignal(Electrode& electrode);
454 void ConvoluteSignal(Electrode& electrode,
const std::vector<double>& tab);
455 bool ConvoluteSignalFFT();
456 bool ConvoluteSignalFFT(
const std::string& label);
457 void ConvoluteSignalFFT(Electrode& electrode,
const std::vector<double>& tab,
458 const unsigned int nn);
460 double TransferFunctionSq();
461 double InterpolateTransferFunctionTable(
const double t)
const;
462 void MakeTransferFunctionTable(std::vector<double>& tab);
463 void FFT(std::vector<double>& data,
const bool inverse,
const int nn);