Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
ComponentParallelPlate.hh
Go to the documentation of this file.
1#ifndef G_COMPONENT_PP_H
2#define G_COMPONENT_PP_H
3
4#include <string>
5
6#include "Component.hh"
7#include "ComponentGrid.hh"
8#include "Medium.hh"
9
10#include <TF1.h>
11#include <TF2.h>
12
13namespace Garfield {
14
15/// Component for parallel-plate geometries.
16
18 public:
19 /// Constructor
21 /// Destructor
23
24 /** Define the geometry.
25 * \param N amount of layers in the geometry, this includes the gas gaps
26 * \f$y\f$. \param d thickness of the layers starting from the bottom to the
27 * top lauer along \f$y\f$. \param eps relative permittivities of the layers
28 * starting from the bottom to the top lauer along \f$y\f$ . Here, the gas
29 * gaps having a value of 1. \param sigmaIndex Indices of the resistive
30 * layers (optional). \param V applied potential difference between the
31 * parallel plates.
32 */
33 void Setup(const int N, std::vector<double> eps, std::vector<double> d,
34 const double V, std::vector<int> sigmaIndex = {});
35
36 void ElectricField(const double x, const double y, const double z, double &ex,
37 double &ey, double &ez, Medium *&m, int &status) override;
38 void ElectricField(const double x, const double y, const double z, double &ex,
39 double &ey, double &ez, double &v, Medium *&m,
40 int &status) override;
42 double WeightingPotential(const double x, const double y, const double z,
43 const std::string &label) override;
44
45 bool GetVoltageRange(double &vmin, double &vmax) override;
46
47 /** Add a pixel electrode.
48 * \param x,z position of the center of the electrode in the xz-plane.
49 * \param lx width in the along \f$x\f$.
50 * \param lz width in the along \f$z\f$.
51 * \param label give name using a string.
52 * \param fromAnode is \f$true\f$ is the electrode is the andode and
53 * \f$false\f$ if it is the cathode.
54 */
55 void AddPixel(double x, double z, double lx, double lz,
56 const std::string &label, bool fromAnode = true);
57 /// Add strip electrode.
58 void AddStrip(double z, double lz, const std::string &label,
59 bool fromAnode = true);
60
61 /// Add plane electrode, if you want to read the signal from the cathode set
62 /// the second argument to false.
63 void AddPlane(const std::string &label, bool fromAnode = true);
64
65 /// Setting the medium
66 void SetMedium(Medium *medium) { m_medium = medium; }
67
68 /** Calculate time-dependent weighting potential on a grid.
69 * \param xmin,ymin,zmin minimum value of the interval in the \f$x\f$-,
70 * \f$y\f$- and \f$z\f$-direction. \param xmax,ymax,zmax maximum value of the
71 * interval in the \f$x\f$-,\f$y\f$- and \f$z\f$-direction. \param
72 * xsteps,ysteps,zsteps mumber of grid nodes in the \f$x\f$-,\f$y\f$- and
73 * \f$z\f$-direction. \param label give name using a string.
74 */
75 void SetWeightingPotentialGrid(const double xmin, const double xmax,
76 const double xsteps, const double ymin,
77 const double ymax, const double ysteps,
78 const double zmin, const double zmax,
79 const double zsteps, const std::string &label);
80
81 /// This will calculate all electrodes time-dependent weighting potential on
82 /// the specified grid.
83 void SetWeightingPotentialGrids(const double xmin, const double xmax,
84 const double xsteps, const double ymin,
85 const double ymax, const double ysteps,
86 const double zmin, const double zmax,
87 const double zsteps);
88
89 /// This will load a previously calculated grid of time-dependant weighting
90 /// potential values.
91 void LoadWeightingPotentialGrid(const std::string &label) {
92 for (auto &electrode : m_readout_p) {
93 if (electrode.label == label) {
94 if (electrode.grid.LoadWeightingField(label + "map", "xyz", true)) {
95 std::cerr
97 << "::LoadWeightingPotentialGrid: Weighting potential set for "
98 << label << ".\n";
99 electrode.m_usegrid = true;
100 return;
101 }
102 }
103 }
104 std::cerr << m_className
105 << "::LoadWeightingPotentialGrid: Could not find file for "
106 << label << ".\n";
107 }
108
109 Medium *GetMedium(const double x, const double y, const double z) override;
110
111 bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax,
112 double &ymax, double &zmax) override;
113
114 // Obtain the index and permitivity of of the layer at hight z.
115 bool getLayer(const double y, int &m, double &epsM) {
116
117 int mholer = -1;
118
119 for (int i = 1; i < m_N; i++) {
120 if (y <= m_z[i]) {
121 mholer = i;
122 break;
123 }
124 }
125 if (mholer == -1) return false;
126
127 m = mholer;
128 epsM = m_epsHolder[m - 1];
129 return true;
130 }
131 int NumberOfLayers() { return m_N - 1; }
132
133 void SetIntegrationPrecision(const double eps) { m_precision = eps; }
134
135 void SetIntegrationUpperbound(const double p) { m_upperBoundIntegration = p; }
136
138 m_getPotentialInPlate = false;
139 }
140
141 private:
142 double m_precision = 1.e-12;
143 static constexpr double m_Vw = 1.;
144 double m_eps0 = 8.85418782e-3;
145 // Voltage difference between the parallel plates.
146 double m_V = 0.;
147
148 bool m_getPotentialInPlate = true;
149
150 double m_dt = 0.;
151
152 int m_N = 0; ///< amount of layers
153
154 double m_upperBoundIntegration = 30;
155
156 std::vector<double> m_eps; ///< relative permittivity of each layer
157 std::vector<double> m_epsHolder;
158 std::vector<double> m_d; ///< thickness of each layer
159 std::vector<double> m_dHolder;
160 std::vector<double> m_z; ///< list of indices of conducting layers
161
162 std::vector<int> m_sigmaIndex; ///< list of indices of conducting layers
163
164 TF2 m_hIntegrand;
165
166 TF1 m_wpStripIntegral; ///< Weighting potential integrant for strips
167 TF2 m_wpPixelIntegral; ///< Weighting potential integrant for pixels
168
169 std::vector<std::vector<std::vector<int>>> m_sigmaMatrix; // sigma_{i,j}^n,
170 // where n goes
171 // from 1 to N;
172 std::vector<std::vector<std::vector<int>>> m_thetaMatrix; // theta_{i,j}^n,
173 // where n goes
174 // from 1 to N;
175
176 std::vector<std::vector<double>> m_cMatrix; ///< c-matrixl.
177 std::vector<std::vector<double>> m_vMatrix; ///< v-matrixl.
178 std::vector<std::vector<double>> m_gMatrix; ///< g-matrixl.
179 std::vector<std::vector<double>> m_wMatrix; ///< w-matrixl.
180
181 int m_currentLayer = 0; ///< Index of the current layer.
182 double m_currentPosition = -1;
183
184 Medium *m_medium = nullptr;
185
186 /// Structure that captures the information of the electrodes under study
187 struct Electrode {
188 std::string label; ///< Label.
189 int ind = structureelectrode::NotSet; ///< Readout group.
190 double xpos, ypos; ///< Coordinates in x/y.
191 double lx, ly; ///< Dimensions in the x-y plane.
192 bool formAnode = true; ///< Dimensions in the x-y plane.
193
194 bool m_usegrid = false; ///< Enabeling grid based calculations.
195 ComponentGrid grid; ///< grid object.
196 };
197
198 enum fieldcomponent {
199 xcomp = 0,
200 ycomp,
201 zcomp
202 };
203
204 /// Possible readout groups
205 enum structureelectrode {
206 NotSet = -1,
207 Plane,
208 Strip,
209 Pixel
210 };
211
212 // Vectors storing the readout electrodes.
213 std::vector<std::string> m_readout;
214 std::vector<Electrode> m_readout_p;
215
216 // Functions that calculate the weighting potential
217
218 double IntegratePromptPotential(const Electrode &el, const double x,
219 const double y, const double z);
220
221 void CalculateDynamicalWeightingPotential(const Electrode &el);
222
223 double FindWeightingPotentialInGrid(Electrode &el, const double x,
224 const double y, const double z);
225
226 // function returning 0 if layer with specific index is conductive.
227 double kroneckerDelta(const int index) {
228 if (std::find(m_sigmaIndex.begin(), m_sigmaIndex.end(), index) !=
229 m_sigmaIndex.end())
230 return 0;
231 else
232 return 1;
233 }
234
235 // function construct the sigma matrix needed to calculate the w, v, c and g
236 // matrices
237 bool Nsigma(int N, std::vector<std::vector<int>> &sigmaMatrix);
238
239 // function construct the theta matrix needed to calculate the w, v, c and g
240 // matrices
241 bool Ntheta(int N, std::vector<std::vector<int>> &thetaMatrix,
242 std::vector<std::vector<int>> &sigmaMatrix);
243
244 // function constructing the sigma an theta matrices.
245 void constructGeometryMatrices(const int N);
246
247 // function connstructing the w, v, c and g matrices needed for constructing
248 // the weighting potentials equations.
249 void constructGeometryFunction(const int N);
250
251 // build function h needed for the integrant of the weighting potential of a
252 // stip and pixel
253 void setHIntegrand();
254
255 // build integrant of weighting potential of a strip
256 void setwpPixelIntegrand();
257
258 // build integrant of weighting potential of a pixel
259 void setwpStripIntegrand();
260
261 // weighting field of a plane in layer with index "indexLayer"
262 double constWEFieldLayer(const int indexLayer) {
263 double invEz = 0;
264 for (int i = 1; i <= m_N - 1; i++) {
265 invEz += (m_z[i] - m_z[i - 1]) / m_epsHolder[i - 1];
266 }
267 return 1 / (m_epsHolder[indexLayer - 1] * invEz);
268 }
269
270 // weighting potential of a plane
271 double wpPlane(const double z) {
272 int im = -1;
273 double epsM = -1;
274 if (!getLayer(z, im, epsM)) return 0.;
275 double v = 1 - (z - m_z[im - 1]) * constWEFieldLayer(im);
276 for (int i = 1; i <= im - 1; i++) {
277 v -= (m_z[i] - m_z[i - 1]) * constWEFieldLayer(i);
278 }
279
280 return v;
281 }
282
283 // electric field in layer with index "indexLayer"
284 double constEFieldLayer(const int indexLayer) {
285 if (kroneckerDelta(indexLayer) == 0) return 0.;
286 double invEz = 0;
287 for (int i = 1; i <= m_N - 1; i++) {
288 invEz += -(m_z[i] - m_z[i - 1]) * kroneckerDelta(i) / m_epsHolder[i - 1];
289 }
290 return m_V / (m_epsHolder[indexLayer - 1] * invEz);
291 }
292
293 // function to convert decimal to binary expressed in n digits.
294 bool decToBinary(int n, std::vector<int> &binaryNum);
295
296 // Rebuilds c, v, g and w matrix.
297 void LayerUpdate(double &z, const int im, const double epsM) {
298
299 if (z == m_currentPosition) {
300
301 return;
302
303 } else {
304 m_currentPosition = z;
305 }
306
307 if (im != m_currentLayer) {
308 m_currentLayer = im;
309 for (int i = 0; i < im - 1; i++) m_eps[i] = m_epsHolder[i];
310 m_eps[im - 1] = epsM;
311 m_eps[im] = epsM;
312 for (int i = im + 1; i < m_N; i++) m_eps[i] = m_epsHolder[i - 1];
313 }
314
315 double diff1 = m_z[im] - z;
316 double diff2 = z - m_z[im - 1];
317
318 for (int i = 0; i < im - 1; i++) m_d[i] = m_dHolder[i];
319 m_d[im - 1] = diff2;
320 m_d[im] = diff1;
321 for (int i = im + 1; i < m_N; i++) m_d[i] = m_dHolder[i - 1];
322 // TODO::Construct c and g matrices only for im != m_currentLayer.
323 constructGeometryFunction(m_N);
324 };
325
326 void UpdatePeriodicity() override;
327 void Reset() override;
328};
329} // namespace Garfield
330#endif
Component for interpolating field maps on a regular mesh.
void AddPlane(const std::string &label, bool fromAnode=true)
void AddStrip(double z, double lz, const std::string &label, bool fromAnode=true)
Add strip electrode.
double WeightingPotential(const double x, const double y, const double z, const std::string &label) override
void LoadWeightingPotentialGrid(const std::string &label)
void SetWeightingPotentialGrids(const double xmin, const double xmax, const double xsteps, const double ymin, const double ymax, const double ysteps, const double zmin, const double zmax, const double zsteps)
void Setup(const int N, std::vector< double > eps, std::vector< double > d, const double V, std::vector< int > sigmaIndex={})
void SetMedium(Medium *medium)
Setting the medium.
void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status) override
void SetWeightingPotentialGrid(const double xmin, const double xmax, const double xsteps, const double ymin, const double ymax, const double ysteps, const double zmin, const double zmax, const double zsteps, const std::string &label)
Medium * GetMedium(const double x, const double y, const double z) override
Get the medium at a given location (x, y, z).
bool getLayer(const double y, int &m, double &epsM)
bool GetVoltageRange(double &vmin, double &vmax) override
Calculate the voltage range [V].
void AddPixel(double x, double z, double lx, double lz, const std::string &label, bool fromAnode=true)
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) override
Get the bounding box coordinates.
virtual void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)=0
Component()=delete
Default constructor.
std::string m_className
Class name.
Definition Component.hh:359
Abstract base class for media.
Definition Medium.hh:16