Garfield++ 3.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
ComponentBase.cc
Go to the documentation of this file.
1#include <iostream>
2#include <cmath>
3
6
7namespace Garfield {
8
10
12 // Make sure the geometry is defined
13 if (!geo) {
14 std::cerr << m_className << "::SetGeometry: Null pointer.\n";
15 return;
16 }
17
18 m_geometry = geo;
19}
20
21Medium* ComponentBase::GetMedium(const double x, const double y,
22 const double z) {
23 if (!m_geometry) return nullptr;
24 return m_geometry->GetMedium(x, y, z);
25}
28 m_geometry = nullptr;
29 Reset();
30}
31
32void ComponentBase::WeightingField(const double /*x*/, const double /*y*/,
33 const double /*z*/, double& wx, double& wy,
34 double& wz, const std::string& /*label*/) {
35 if (m_debug) {
36 std::cerr << m_className << "::WeightingField: Function not implemented.\n";
37 }
38 wx = wy = wz = 0.;
39}
40
41void ComponentBase::DelayedWeightingField(const double /*x*/,
42 const double /*y*/,
43 const double /*z*/,
44 const double /*t*/,
45 double& wx, double& wy, double& wz,
46 const std::string& /*label*/) {
47 if (m_debug) {
48 std::cerr << m_className << "::DelayedWeightingField: "
49 << "Function not implemented.\n";
50 }
51 wx = wy = wz = 0.;
52}
53
54double ComponentBase::WeightingPotential(const double /*x*/, const double /*y*/,
55 const double /*z*/,
56 const std::string& /*label*/) {
57 if (m_debug) {
58 std::cerr << m_className << "::WeightingPotential: "
59 << "Function not implemented.\n";
60 }
61 return 0.;
62}
63
64void ComponentBase::MagneticField(const double x, const double y,
65 const double z, double& bx, double& by,
66 double& bz, int& status) {
67 bx = m_bx0;
68 by = m_by0;
69 bz = m_bz0;
70 if (m_debug) {
71 std::cout << m_className << "::MagneticField: Field at (" << x << ", " << y
72 << ", " << z << ") is (" << bx << ", " << by << ", " << bz
73 << ")\n";
74 }
75 status = 0;
76}
77
78void ComponentBase::SetMagneticField(const double bx, const double by,
79 const double bz) {
80 m_bx0 = bx;
81 m_by0 = by;
82 m_bz0 = bz;
83}
84
85bool ComponentBase::GetBoundingBox(double& xmin, double& ymin, double& zmin,
86 double& xmax, double& ymax, double& zmax) {
87 if (!m_geometry) return false;
88 return m_geometry->GetBoundingBox(xmin, ymin, zmin, xmax, ymax, zmax);
89}
90
91bool ComponentBase::IsWireCrossed(const double /*x0*/, const double /*y0*/,
92 const double /*z0*/, const double /*x1*/,
93 const double /*y1*/, const double /*z1*/,
94 double& /*xc*/, double& /*yc*/,
95 double& /*zc*/, const bool /*centre*/,
96 double& /*rc*/) {
97 return false;
98}
99
100bool ComponentBase::IsInTrapRadius(const double /*q0*/, const double x0,
101 const double y0, const double /*z0*/,
102 double& xw, double& yw, double& rw) {
103 xw = x0;
104 yw = y0;
105 rw = 0.;
106 return false;
107}
108
109double ComponentBase::IntegrateFluxCircle(const double xc, const double yc,
110 const double r,
111 const unsigned int nI) {
112 // FLDIN2, FCHK3
113 if (nI == 0) {
114 std::cerr << m_className << "::IntegrateFlux:\n"
115 << " Number of intervals must be > 0.\n";
116 return 0.;
117 }
118 // Number of Gaussian quadrature points per interval.
119 constexpr unsigned int nG = 6;
120 constexpr std::array<double, nG> t = {
121 -0.932469514203152028, -0.661209386466264514, -0.238619186083196909,
122 0.238619186083196909, 0.661209386466264514, 0.932469514203152028};
123 constexpr std::array<double, nG> w = {
124 0.171324492379170345, 0.360761573048138608, 0.467913934572691047,
125 0.467913934572691047, 0.360761573048138608, 0.171324492379170345};
126
127 // Width and half-width of intervals.
128 const double d = TwoPi / nI;
129 const double h = 0.5 * d;
130 // Arguments of ElectricField.
131 double ex = 0., ey = 0., ez = 0.;
132 Medium* m = nullptr;
133 int status = 0;
134 // Perform the integration.
135 double s = 0.;
136 for (unsigned int i = 0; i < nG; ++i) {
137 const double phi0 = h * (1. + t[i]);
138 for (unsigned int k = 0; k < nI; ++k) {
139 const double phi = phi0 + k * d;
140 const double cp = cos(phi);
141 const double sp = sin(phi);
142 ElectricField(xc + cp * r, yc + sp * r, 0., ex, ey, ez, m, status);
143 s += w[i] * r * (ex * cp + ey * sp);
144 }
145 }
146 return h * s * VacuumPermittivity;
147}
148
149double ComponentBase::IntegrateFluxSphere(const double xc, const double yc,
150 const double zc, const double r,
151 const unsigned int nI) {
152 // FLDIN3, FCHK2, FCHK1
153 if (nI == 0) {
154 std::cerr << m_className << "::IntegrateFlux:\n"
155 << " Number of intervals must be > 0.\n";
156 return 0.;
157 }
158 // Number of Gaussian quadrature points.
159 constexpr unsigned int nG = 6;
160 constexpr std::array<double, nG> t = {
161 -0.932469514203152028, -0.661209386466264514, -0.238619186083196909,
162 0.238619186083196909, 0.661209386466264514, 0.932469514203152028};
163 constexpr std::array<double, nG> w = {
164 0.171324492379170345, 0.360761573048138608, 0.467913934572691047,
165 0.467913934572691047, 0.360761573048138608, 0.171324492379170345};
166
167 const double r2 = r * r;
168 // Width and half-width of theta intervals.
169 const double dt = Pi / nI;
170 const double ht = 0.5 * dt;
171 // Width and half-width of phi intervals.
172 const double dp = TwoPi / nI;
173 const double hp = 0.5 * dp;
174 // Arguments of ElectricField.
175 double ex = 0., ey = 0., ez = 0.;
176 Medium* m = nullptr;
177 int status = 0;
178 // Perform the integration.
179 double s2 = 0.;
180 // Loop over theta.
181 for (unsigned int i = 0; i < nG; ++i) {
182 const double theta0 = ht * (1. + t[i]) - HalfPi;
183 for (unsigned int k = 0; k < nI; ++k) {
184 const double theta = theta0 + k * dt;
185 const double ct = cos(theta);
186 const double st = sin(theta);
187 const double z = zc + st * r;
188 double s1 = 0.;
189 // Loop over phi.
190 for (unsigned int ii = 0; ii < nG; ++ii) {
191 const double phi0 = hp * (1. + t[ii]);
192 for (unsigned int kk = 0; kk < nI; ++kk) {
193 const double phi = phi0 + kk * dp;
194 const double cp = cos(phi);
195 const double sp = sin(phi);
196 const double x = xc + cp * ct * r;
197 const double y = yc + sp * ct * r;
198 ElectricField(x, y, z, ex, ey, ez, m, status);
199 s1 += w[ii] * ((ex * cp + ey * sp) * ct + ez * st);
200 }
201 }
202 s2 += w[i] * r2 * ct * hp * s1;
203 }
204 }
205 return ht * s2 * VacuumPermittivity;
206}
207
209 const double x0, const double y0, const double z0,
210 const double dx1, const double dy1, const double dz1,
211 const double dx2, const double dy2, const double dz2,
212 const unsigned int nU, const unsigned int nV) {
213
214 // FLDIN4, FCHK4, FCHK5
215 if (nU <= 1 || nV <= 1) {
216 std::cerr << m_className << "::IntegrateFlux:\n"
217 << " Number of points to integrate over must be > 1.\n";
218 return 0.;
219 }
220 // Number of Gaussian quadrature points.
221 constexpr unsigned int nG = 6;
222 constexpr std::array<double, nG> t = {
223 -0.932469514203152028, -0.661209386466264514, -0.238619186083196909,
224 0.238619186083196909, 0.661209386466264514, 0.932469514203152028};
225 constexpr std::array<double, nG> w = {
226 0.171324492379170345, 0.360761573048138608, 0.467913934572691047,
227 0.467913934572691047, 0.360761573048138608, 0.171324492379170345};
228
229 // Compute the normal vector.
230 const double xn = dy1 * dz2 - dz1 * dy2;
231 const double yn = dz1 * dx2 - dx1 * dz2;
232 const double zn = dx1 * dy2 - dy1 * dx2;
233 if (m_debug) {
234 std::cout << m_className << "::IntegrateFlux: Normal vector = "
235 << xn << ", " << yn << ", " << zn << ".\n";
236 }
237 // If this vector has zero norm, return 0 flux.
238 const double d1 = dx1 * dx1 + dy1 * dy1 + dz1 * dz1;
239 const double d2 = dx2 * dx2 + dy2 * dy2 + dz2 * dz2;
240 if (xn * xn + yn * yn + zn * zn < 1.e-10 * sqrt(d1 * d2) ||
241 d1 < 1.e-10 * d2 || d2 < 1.e-10 * d1) {
242 std::cerr << m_className << "::IntegrateFlux:\n"
243 << " Parallelogram does not have non-zero area.\n";
244 return 0.;
245 }
246
247 // (Half-)step sizes in the two directions.
248 const double du = 1. / nU;
249 const double hu = 0.5 * du;
250 const double dv = 1. / nV;
251 const double hv = 0.5 * dv;
252 // Arguments of ElectricField.
253 double ex = 0., ey = 0., ez = 0.;
254 Medium* m = nullptr;
255 int status = 0;
256 // Perform the integration.
257 double s2 = 0.;
258 for (unsigned int i = 0; i < nG; ++i) {
259 const double v0 = hv * (1. + t[i]);
260 for (unsigned int k = 0; k < nV; ++k) {
261 const double v = v0 + k * dv;
262 double s1 = 0.;
263 for (unsigned int ii = 0; ii < nG; ++ii) {
264 const double u0 = hu * (1. + t[ii]);
265 for (unsigned int kk = 0; kk < nU; ++kk) {
266 const double u = u0 + kk * du;
267 const double x = x0 + u * dx1 + v * dx2;
268 const double y = y0 + u * dy1 + v * dy2;
269 const double z = z0 + u * dz1 + v * dz2;
270 ElectricField(x, y, z, ex, ey, ez, m, status);
271 s1 += w[ii] * (ex * xn + ey * yn + ez * zn);
272 }
273 }
274 s2 += w[i] * hu * s1;
275 }
276 }
277 return hv * s2;
278}
279
280}
double IntegrateFluxSphere(const double xc, const double yc, const double zc, const double r, const unsigned int nI=20)
virtual void ElectricField(const double x, const double y, const double z, double &ex, double &ey, double &ez, Medium *&m, int &status)=0
ComponentBase()
Constructor.
Definition: ComponentBase.cc:9
double IntegrateFluxCircle(const double xc, const double yc, const double r, const unsigned int nI=50)
virtual double WeightingPotential(const double x, const double y, const double z, const std::string &label)
virtual void Clear()
Reset.
virtual bool IsWireCrossed(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)
GeometryBase * m_geometry
Pointer to the geometry.
void SetMagneticField(const double bx, const double by, const double bz)
Set a constant magnetic field.
virtual void Reset()=0
Reset the component.
virtual void MagneticField(const double x, const double y, const double z, double &bx, double &by, double &bz, int &status)
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)
virtual bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)
Get the bounding box coordinates.
virtual void WeightingField(const double x, const double y, const double z, double &wx, double &wy, double &wz, const std::string &label)
double IntegrateFlux(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)
std::string m_className
Class name.
virtual void SetGeometry(GeometryBase *geo)
Define the geometry.
virtual bool IsInTrapRadius(const double q0, const double x0, const double y0, const double z0, double &xw, double &yw, double &rw)
bool m_debug
Switch on/off debugging messages.
virtual Medium * GetMedium(const double x, const double y, const double z)
Get the medium at a given location (x, y, z).
Abstract base class for geometry classes.
Definition: GeometryBase.hh:13
virtual Medium * GetMedium(const double x, const double y, const double z) const =0
Retrieve the medium at a given point.
virtual bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax)=0
Get the bounding box (envelope of the geometry).
Abstract base class for media.
Definition: Medium.hh:13