Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Component.cc
Go to the documentation of this file.
1#include <cmath>
2#include <iostream>
3
8
9namespace Garfield {
10
11Component::Component(const std::string& name) {
12 m_className = "Component" + name;
13}
14
16 // Make sure the geometry is defined
17 if (!geo) {
18 std::cerr << m_className << "::SetGeometry: Null pointer.\n";
19 return;
20 }
21 m_geometry = geo;
22}
23
24Medium* Component::GetMedium(const double x, const double y, const double z) {
25 if (!m_geometry) return nullptr;
26 return m_geometry->GetMedium(x, y, z);
27}
28
30 m_geometry = nullptr;
31 m_ready = false;
32 // Reset periodicities.
33 m_periodic.fill(false);
34 m_mirrorPeriodic.fill(false);
35 m_axiallyPeriodic.fill(false);
36 m_rotationSymmetric.fill(false);
37 // Reset the magnetic field.
38 m_b0.fill(0.);
39 Reset();
40}
41
42std::array<double, 3> Component::ElectricField(
43 const double x, const double y, const double z) {
44 double ex = 0., ey = 0., ez = 0.;
45 Medium* medium = nullptr;
46 int status = 0;
47 ElectricField(x, y, z, ex, ey, ez, medium, status);
48 std::array<double, 3> efield = {ex, ey, ez};
49 return efield;
50}
51
52double Component::ElectricPotential(const double x, const double y,
53 const double z) {
54 double ex = 0., ey = 0., ez = 0., v = 0.;
55 Medium* medium = nullptr;
56 int status = 0;
57 ElectricField(x, y, z, ex, ey, ez, v, medium, status);
58 return v;
59}
60
61void Component::WeightingField(const double /*x*/, const double /*y*/,
62 const double /*z*/, double& wx, double& wy,
63 double& wz, const std::string& /*label*/) {
64 if (m_debug) {
65 std::cerr << m_className << "::WeightingField: Function not implemented.\n";
66 }
67 wx = wy = wz = 0.;
68}
69
70void Component::DelayedWeightingField(const double /*x*/, const double /*y*/,
71 const double /*z*/, const double /*t*/,
72 double& wx, double& wy, double& wz,
73 const std::string& /*label*/) {
74 if (m_debug) {
75 std::cerr << m_className << "::DelayedWeightingField: Not implemented.\n";
76 }
77 wx = wy = wz = 0.;
78}
79
80double Component::WeightingPotential(const double /*x*/, const double /*y*/,
81 const double /*z*/,
82 const std::string& /*label*/) {
83 if (m_debug) {
84 std::cerr << m_className << "::WeightingPotential: Not implemented.\n";
85 }
86 return 0.;
87}
88
89double Component::DelayedWeightingPotential(const double /*x*/,
90 const double /*y*/,
91 const double /*z*/,
92 const double /*t*/,
93 const std::string& /*label*/) {
94 if (m_debug) {
95 std::cerr << m_className
96 << "::DelayedWeightingPotential: Not implemented.\n";
97 }
98 return 0.;
99}
100
101
102void Component::MagneticField(const double x, const double y, const double z,
103 double& bx, double& by, double& bz, int& status) {
104 bx = m_b0[0];
105 by = m_b0[1];
106 bz = m_b0[2];
107 if (m_debug) {
108 std::cout << m_className << "::MagneticField: Field at (" << x << ", " << y
109 << ", " << z << ") is (" << bx << ", " << by << ", " << bz
110 << ")\n";
111 }
112 status = 0;
113}
114
115void Component::SetMagneticField(const double bx, const double by,
116 const double bz) {
117 m_b0 = {bx, by, bz};
118}
119
120bool Component::GetBoundingBox(double& xmin, double& ymin, double& zmin,
121 double& xmax, double& ymax, double& zmax) {
122 if (!m_geometry) return false;
123 return m_geometry->GetBoundingBox(xmin, ymin, zmin, xmax, ymax, zmax);
124}
125
126bool Component::GetElementaryCell(double& xmin, double& ymin, double& zmin,
127 double& xmax, double& ymax, double& zmax) {
128 return GetBoundingBox(xmin, ymin, zmin, xmax, ymax, zmax);
129}
130
132 const double /*x0*/, const double /*y0*/, const double /*z0*/,
133 const double /*x1*/, const double /*y1*/, const double /*z1*/,
134 double& /*xc*/, double& /*yc*/, double& /*zc*/,
135 const bool /*centre*/, double& /*rc*/) {
136 return false;
137}
138
139bool Component::InTrapRadius(const double /*q0*/, const double x0,
140 const double y0, const double /*z0*/, double& xw,
141 double& yw, double& rw) {
142 xw = x0;
143 yw = y0;
144 rw = 0.;
145 return false;
146}
147
149 const double /*x0*/, const double /*y0*/, const double /*z0*/,
150 const double /*x1*/, const double /*y1*/, const double /*z1*/,
151 double& /*xc*/, double& /*yc*/, double& /*zc*/) {
152 return false;
153}
154
156 return fabs(m_b0[0]) > Small || fabs(m_b0[1]) > Small ||
157 fabs(m_b0[2]) > Small;
158}
159
160double Component::IntegrateFluxCircle(const double xc, const double yc,
161 const double r, const unsigned int nI) {
162 // FLDIN2, FCHK3
163 if (nI == 0) {
164 std::cerr << m_className << "::IntegrateFluxCircle:\n"
165 << " Number of intervals must be > 0.\n";
166 return 0.;
167 }
168 // Number of Gaussian quadrature points per interval.
169 constexpr size_t nG = 6;
172
173 // Width and half-width of intervals.
174 const double d = TwoPi / nI;
175 const double h = 0.5 * d;
176 // Arguments of ElectricField.
177 double ex = 0., ey = 0., ez = 0.;
178 Medium* m = nullptr;
179 int status = 0;
180 // Perform the integration.
181 double s = 0.;
182 for (size_t i = 0; i < nG; ++i) {
183 const double phi0 = h * (1. + tg[i]);
184 for (unsigned int k = 0; k < nI; ++k) {
185 const double phi = phi0 + k * d;
186 const double cp = cos(phi);
187 const double sp = sin(phi);
188 ElectricField(xc + cp * r, yc + sp * r, 0., ex, ey, ez, m, status);
189 s += wg[i] * r * (ex * cp + ey * sp);
190 }
191 }
192 return h * s * VacuumPermittivity;
193}
194
195double Component::IntegrateFluxSphere(const double xc, const double yc,
196 const double zc, const double r,
197 const unsigned int nI) {
198 // FLDIN3, FCHK2, FCHK1
199 if (nI == 0) {
200 std::cerr << m_className << "::IntegrateFluxSphere:\n"
201 << " Number of intervals must be > 0.\n";
202 return 0.;
203 }
204 // Number of Gaussian quadrature points.
205 constexpr size_t nG = 6;
208
209 const double r2 = r * r;
210 // Width and half-width of theta intervals.
211 const double dt = Pi / nI;
212 const double ht = 0.5 * dt;
213 // Width and half-width of phi intervals.
214 const double dp = TwoPi / nI;
215 const double hp = 0.5 * dp;
216 // Arguments of ElectricField.
217 double ex = 0., ey = 0., ez = 0.;
218 Medium* m = nullptr;
219 int status = 0;
220 // Perform the integration.
221 double s2 = 0.;
222 // Loop over theta.
223 for (size_t i = 0; i < nG; ++i) {
224 const double theta0 = ht * (1. + tg[i]) - HalfPi;
225 for (unsigned int k = 0; k < nI; ++k) {
226 const double theta = theta0 + k * dt;
227 const double ct = cos(theta);
228 const double st = sin(theta);
229 const double z = zc + st * r;
230 double s1 = 0.;
231 // Loop over phi.
232 for (size_t ii = 0; ii < nG; ++ii) {
233 const double phi0 = hp * (1. + tg[ii]);
234 for (unsigned int kk = 0; kk < nI; ++kk) {
235 const double phi = phi0 + kk * dp;
236 const double cp = cos(phi);
237 const double sp = sin(phi);
238 const double x = xc + cp * ct * r;
239 const double y = yc + sp * ct * r;
240 ElectricField(x, y, z, ex, ey, ez, m, status);
241 s1 += wg[ii] * ((ex * cp + ey * sp) * ct + ez * st);
242 }
243 }
244 s2 += wg[i] * r2 * ct * hp * s1;
245 }
246 }
247 return ht * s2 * VacuumPermittivity;
248}
249
251 const double x0, const double y0, const double z0, const double dx1,
252 const double dy1, const double dz1, const double dx2, const double dy2,
253 const double dz2, const unsigned int nU, const unsigned int nV) {
254
256 x0, y0, z0, dx1, dy1, dz1, dx2, dy2, dz2, nU, nV, false, "");
257}
258
260 const double x0, const double y0, const double z0, const double dx1,
261 const double dy1, const double dz1, const double dx2, const double dy2,
262 const double dz2, const unsigned int nU, const unsigned int nV) {
263
265 x0, y0, z0, dx1, dy1, dz1, dx2, dy2, dz2, nU, nV, true, id);
266}
267
269 const double x0, const double y0, const double z0, const double dx1,
270 const double dy1, const double dz1, const double dx2, const double dy2,
271 const double dz2, const unsigned int nU, const unsigned int nV,
272 const bool wfield, const std::string& label) {
273
274 // FLDIN4, FCHK4, FCHK5
275 if (nU <= 1 || nV <= 1) {
276 std::cerr << m_className << "::IntegrateFluxParallelogram:\n"
277 << " Number of points to integrate over must be > 1.\n";
278 return 0.;
279 }
280 // Number of Gaussian quadrature points.
281 constexpr size_t nG = 6;
284
285 // Compute the normal vector.
286 const double xn = dy1 * dz2 - dz1 * dy2;
287 const double yn = dz1 * dx2 - dx1 * dz2;
288 const double zn = dx1 * dy2 - dy1 * dx2;
289 if (m_debug) {
290 std::cout << m_className << "::IntegrateFluxParallelogram:\n"
291 << " Normal vector = " << xn << ", " << yn << ", " << zn
292 << ".\n";
293 }
294 // If this vector has zero norm, return 0 flux.
295 const double d1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1;
296 const double d2 = dx2 * dx2 + dy2 * dy2 + dz2 * dz2;
297 if (xn * xn + yn * yn + zn * zn < 1.e-10 * sqrt(d1 * d2) ||
298 d1 < 1.e-10 * d2 || d2 < 1.e-10 * d1) {
299 std::cerr << m_className << "::IntegrateFluxParallelogram:\n"
300 << " Parallelogram does not have non-zero area.\n";
301 return 0.;
302 }
303
304 // (Half-)step sizes in the two directions.
305 const double du = 1. / nU;
306 const double hu = 0.5 * du;
307 const double dv = 1. / nV;
308 const double hv = 0.5 * dv;
309 // Arguments of ElectricField.
310 double fx = 0., fy = 0., fz = 0.;
311 Medium* m = nullptr;
312 int status = 0;
313 // Perform the integration.
314 double s2 = 0.;
315 for (size_t i = 0; i < nG; ++i) {
316 const double v0 = hv * (1. + tg[i]);
317 for (unsigned int k = 0; k < nV; ++k) {
318 const double v = v0 + k * dv;
319 double s1 = 0.;
320 for (size_t ii = 0; ii < nG; ++ii) {
321 const double u0 = hu * (1. + tg[ii]);
322 for (unsigned int kk = 0; kk < nU; ++kk) {
323 const double u = u0 + kk * du;
324 const double x = x0 + u * dx1 + v * dx2;
325 const double y = y0 + u * dy1 + v * dy2;
326 const double z = z0 + u * dz1 + v * dz2;
327 if (wfield) {
328 WeightingField(x, y, z, fx, fy, fz, label);
329 } else {
330 ElectricField(x, y, z, fx, fy, fz, m, status);
331 }
332 s1 += wg[ii] * (fx * xn + fy * yn + fz * zn);
333 }
334 }
335 s2 += wg[i] * hu * s1;
336 }
337 }
338 return hv * s2;
339}
340
341double Component::IntegrateFluxLine(const double x0, const double y0,
342 const double z0, const double x1,
343 const double y1, const double z1,
344 const double xp, const double yp,
345 const double zp, const unsigned int nI,
346 const int isign) {
347 // FLDIN5
348 // Normalise the norm vector.
349 const double pmag2 = xp * xp + yp * yp + zp * zp;
350 if (pmag2 <= 0.) {
351 std::cerr << m_className << "::IntegrateFluxLine:\n"
352 << " Normal vector has zero length; flux set to 0.\n";
353 return 0.;
354 }
355 const double pmag = sqrt(pmag2);
356 const double xn = xp / pmag;
357 const double yn = yp / pmag;
358 const double zn = zp / pmag;
359
360 // Check integration points.
361 if (nI <= 1) {
362 std::cerr << m_className << "::IntegrateFluxLine:\n"
363 << " Number of points to integrate over must be > 1.\n";
364 return 0.;
365 }
366 // Ensure the segment has non-zero length.
367 const double vx = x1 - x0;
368 const double vy = y1 - y0;
369 const double vz = z1 - z0;
370 const double vmag2 = vx * vx + vy * vy + vz * vz;
371 if (vmag2 <= 0.) {
372 std::cerr << m_className << "::IntegrateFluxLine:\n"
373 << " Segment has zero length; flux set to 0.\n";
374 return 0.;
375 }
376 const double vmag = sqrt(vmag2);
377 // Segment should be perpendicular to the norm vector.
378 if (fabs(vx * xn + vy * yn + vz * zn) > 1.e-4 * vmag) {
379 std::cerr << m_className << "::IntegrateFluxLine:\n"
380 << " Segment is not perpendicular to norm vector.\n";
381 return 0.;
382 }
383
384 // Perform the integration.
385 constexpr size_t nG = 6;
388
389 const double d = 1. / nI;
390 const double h = 0.5 * d;
391 // Arguments of ElectricField.
392 double ex = 0., ey = 0., ez = 0.;
393 Medium* m = nullptr;
394 int status = 0;
395 double s = 0.;
396 for (size_t i = 0; i < nG; ++i) {
397 const double u0 = h * (1. + tg[i]);
398 for (unsigned int k = 0; k < nI; ++k) {
399 const double u = u0 + k * d;
400 const double x = x0 + u * vx;
401 const double y = y0 + u * vy;
402 const double z = z0 + u * vz;
403 ElectricField(x, y, z, ex, ey, ez, m, status);
404 double fn = ex * xn + ey * yn + ez * zn;
405 if (isign != 0) {
406 // TODO: -1?
407 fn = isign * fn > 0 ? fabs(fn) : -1.;
408 }
409 s += wg[i] * fn;
410 }
411 }
412 return s * vmag;
413}
414
415} // namespace Garfield
virtual double WeightingPotential(const double x, const double y, const double z, const std::string &label)
Definition Component.cc:80
virtual bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Get the bounding box coordinates.
Definition Component.cc:120
std::array< bool, 3 > m_rotationSymmetric
Rotation symmetry around x-axis, y-axis, z-axis.
Definition Component.hh:380
std::array< bool, 3 > m_mirrorPeriodic
Mirror periodicity in x, y, z.
Definition Component.hh:376
virtual void Reset()=0
Reset the component.
virtual void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)=0
virtual Medium * GetMedium(const double x, const double y, const double z)
Get the medium at a given location (x, y, z).
Definition Component.cc:24
virtual void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)
Definition Component.cc:61
virtual bool CrossedWire(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc, const bool centre, double &rc)
Definition Component.cc:131
bool m_debug
Switch on/off debugging messages.
Definition Component.hh:371
virtual void DelayedWeightingField(const double x, const double y, const double z, const double t, double &wx, double &wy, double &wz, const std::string &label)
Definition Component.cc:70
double IntegrateWeightingFluxParallelogram(const std::string &label, const double x0, const double y0, const double z0, const double dx1, const double dy1, const double dz1, const double dx2, const double dy2, const double dz2, const unsigned int nU=20, const unsigned int nV=20)
Definition Component.cc:259
virtual bool InTrapRadius(const double q0, const double x0, const double y0, const double z0, double &xw, double &yw, double &rw)
Definition Component.cc:139
virtual bool CrossedPlane(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, double &xc, double &yc, double &zc)
Definition Component.cc:148
Component()=delete
Default constructor.
std::array< bool, 3 > m_periodic
Simple periodicity in x, y, z.
Definition Component.hh:374
virtual bool HasMagneticField() const
Does the component have a non-zero magnetic field?
Definition Component.cc:155
virtual void Clear()
Reset.
Definition Component.cc:29
virtual double ElectricPotential(const double x, const double y, const double z)
Calculate the (drift) electrostatic potential [V] at (x, y, z).
Definition Component.cc:52
std::string m_className
Class name.
Definition Component.hh:359
double IntegrateFluxCircle(const double xc, const double yc, const double r, const unsigned int nI=50)
Definition Component.cc:160
Geometry * m_geometry
Pointer to the geometry.
Definition Component.hh:362
double IntegrateFluxSphere(const double xc, const double yc, const double zc, const double r, const unsigned int nI=20)
Definition Component.cc:195
virtual void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
Definition Component.cc:102
bool m_ready
Ready for use?
Definition Component.hh:368
void SetMagneticField(const double bx, const double by, const double bz)
Set a constant magnetic field.
Definition Component.cc:115
std::array< double, 3 > m_b0
Constant magnetic field.
Definition Component.hh:365
std::array< bool, 3 > m_axiallyPeriodic
Axial periodicity in x, y, z.
Definition Component.hh:378
virtual bool GetElementaryCell(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Get the coordinates of the elementary cell.
Definition Component.cc:126
virtual double DelayedWeightingPotential(const double x, const double y, const double z, const double t, const std::string &label)
Definition Component.cc:89
double IntegrateFluxParallelogram(const double x0, const double y0, const double z0, const double dx1, const double dy1, const double dz1, const double dx2, const double dy2, const double dz2, const unsigned int nU=20, const unsigned int nV=20)
Definition Component.cc:250
virtual void SetGeometry(Geometry *geo)
Define the geometry.
Definition Component.cc:15
double IntegrateFluxLine(const double x0, const double y0, const double z0, const double x1, const double y1, const double z1, const double xp, const double yp, const double zp, const unsigned int nI, const int isign=0)
Definition Component.cc:341
Abstract base class for geometry classes.
Definition Geometry.hh:13
Abstract base class for media.
Definition Medium.hh:16
constexpr std::array< double, 6 > GaussLegendreWeights6()
Definition Numerics.hh:49
constexpr std::array< double, 6 > GaussLegendreNodes6()
Definition Numerics.hh:44
DoubleAc sqrt(const DoubleAc &f)
Definition DoubleAc.cpp:314