Garfield++ 3.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
SolidHole.cc
Go to the documentation of this file.
1#include <cmath>
2#include <iostream>
3
6
7namespace Garfield {
8
9SolidHole::SolidHole(const double cx, const double cy, const double cz,
10 const double rup, const double rlow,
11 const double lx, const double ly, const double lz)
12 : Solid(cx, cy, cz, "SolidHole"),
13 m_rUp(rup),
14 m_rLow(rlow),
15 m_lX(lx),
16 m_lY(ly),
17 m_lZ(lz) {}
18
19SolidHole::SolidHole(const double cx, const double cy, const double cz,
20 const double rup, const double rlow,
21 const double lx, const double ly, const double lz,
22 const double dx, const double dy, const double dz)
23 : SolidHole(cx, cy, cz, rup, rlow, lx, ly, lz) {
24 SetDirection(dx, dy, dz);
25}
26
27bool SolidHole::IsInside(const double x, const double y, const double z) const {
28 // Transform the point to local coordinates.
29 double u = x, v = y, w = z;
30 ToLocal(x, y, z, u, v, w);
31
32 if (fabs(u) > m_lX || fabs(v) > m_lY || fabs(w) > m_lZ) {
33 if (m_debug) {
34 std::cout << "SolidHole::IsInside: (" << x << ", " << y << ", " << z
35 << ") is outside.\n";
36 }
37 return false;
38 }
39
40 const double r = m_rLow + (w + m_lZ) * (m_rUp - m_rLow) / (2 * m_lZ);
41 if (u * u + v * v < r * r) {
42 if (m_debug) {
43 std::cout << "SolidHole::IsInside: (" << x << ", " << y << ", " << z
44 << ") is outside.\n";
45 }
46 return false;
47 }
48
49 if (m_debug) {
50 std::cout << "SolidHole::IsInside: (" << x << ", " << y << ", " << z
51 << ") is inside.\n";
52 }
53 return false;
54}
55
56bool SolidHole::GetBoundingBox(double& xmin, double& ymin, double& zmin,
57 double& xmax, double& ymax, double& zmax) const {
58 if (m_cTheta == 1. && m_cPhi == 1.) {
59 xmin = m_cX - m_lX;
60 xmax = m_cX + m_lX;
61 ymin = m_cY - m_lY;
62 ymax = m_cY + m_lY;
63 zmin = m_cZ - m_lZ;
64 zmax = m_cZ + m_lZ;
65 return true;
66 }
67
68 const double dd = sqrt(m_lX * m_lX + m_lY * m_lY + m_lZ * m_lZ);
69 xmin = m_cX - dd;
70 xmax = m_cX + dd;
71 ymin = m_cY - dd;
72 ymax = m_cY + dd;
73 zmin = m_cZ - dd;
74 zmax = m_cZ + dd;
75 return true;
76}
77
78void SolidHole::SetUpperRadius(const double r) {
79 if (r <= 0.) {
80 std::cerr << "SolidHole::SetUpperRadius: Radius must be > 0.\n";
81 return;
82 }
83 m_rUp = r;
84}
85
86void SolidHole::SetLowerRadius(const double r) {
87 if (r <= 0.) {
88 std::cerr << "SolidHole::SetLowerRadius: Radius must be > 0.\n";
89 return;
90 }
91 m_rLow = r;
92}
93
94void SolidHole::SetHalfLengthX(const double lx) {
95 if (lx <= 0.) {
96 std::cerr << "SolidHole::SetHalfLengthX: Half-length must be > 0.\n";
97 return;
98 }
99 m_lX = lx;
100}
101
102void SolidHole::SetHalfLengthY(const double ly) {
103 if (ly <= 0.) {
104 std::cerr << "SolidHole::SetHalfLengthY: Half-length must be > 0.\n";
105 return;
106 }
107 m_lY = ly;
108}
109
110void SolidHole::SetHalfLengthZ(const double lz) {
111 if (lz <= 0.) {
112 std::cerr << "SolidHole::SetHalfLengthZ: Half-length must be > 0.\n";
113 return;
114 }
115 m_lZ = lz;
116}
117
118void SolidHole::SetSectors(const unsigned int n) {
119 if (n < 1) {
120 std::cerr << "SolidHole::SetSectors: Number must be > 0.\n";
121 return;
122 }
123 m_n = n;
124}
125
126bool SolidHole::SolidPanels(std::vector<Panel>& panels) {
127 const auto id = GetId();
128 const unsigned int nPanels = panels.size();
129 // Direction vector.
130 const double fnorm = sqrt(m_dX * m_dX + m_dY * m_dY + m_dZ * m_dZ);
131 if (fnorm <= 0) {
132 std::cerr << "SolidHole::SolidPanels:\n"
133 << " Zero norm direction vector; no panels generated.\n";
134 return false;
135 }
136
137 // Set the mean or the outer radius.
138 double r1 = m_rLow;
139 double r2 = m_rUp;
140 if (m_average) {
141 const double alpha = Pi / (4. * (m_n - 1.));
142 const double f = 2. / (1. + asinh(tan(alpha)) * cos(alpha) / tan(alpha));
143 r1 *= f;
144 r2 *= f;
145 }
146
147 double xv0, yv0, zv0;
148 double xv1, yv1, zv1;
149 double xv2, yv2, zv2;
150 double xv3, yv3, zv3;
151 // Draw the 6 sides of the box, start with the x=xmin face.
152 if (m_lY > 0 && m_lZ > 0) {
153 ToGlobal(-m_lX, -m_lY, -m_lZ, xv0, yv0, zv0);
154 ToGlobal(-m_lX, +m_lY, -m_lZ, xv1, yv1, zv1);
155 ToGlobal(-m_lX, +m_lY, +m_lZ, xv2, yv2, zv2);
156 ToGlobal(-m_lX, -m_lY, +m_lZ, xv3, yv3, zv3);
157 Panel newpanel;
158 newpanel.a = -m_cPhi * m_cTheta;
159 newpanel.b = -m_sPhi * m_cTheta;
160 newpanel.c = +m_sTheta;
161 newpanel.xv = {xv0, xv1, xv2, xv3};
162 newpanel.yv = {yv0, yv1, yv2, yv3};
163 newpanel.zv = {zv0, zv1, zv2, zv3};
164 newpanel.colour = 0;
165 newpanel.volume = id;
166 panels.push_back(std::move(newpanel));
167 }
168 // The x=xmax face.
169 if (m_lX > 0 && m_lY > 0 && m_lZ > 0) {
170 ToGlobal(+m_lX, -m_lY, -m_lZ, xv0, yv0, zv0);
171 ToGlobal(+m_lX, +m_lY, -m_lZ, xv1, yv1, zv1);
172 ToGlobal(+m_lX, +m_lY, +m_lZ, xv2, yv2, zv2);
173 ToGlobal(+m_lX, -m_lY, +m_lZ, xv3, yv3, zv3);
174 Panel newpanel;
175 newpanel.a = m_cPhi * m_cTheta;
176 newpanel.b = m_sPhi * m_cTheta;
177 newpanel.c = -m_sTheta;
178 newpanel.xv = {xv0, xv1, xv2, xv3};
179 newpanel.yv = {yv0, yv1, yv2, yv3};
180 newpanel.zv = {zv0, zv1, zv2, zv3};
181 newpanel.colour = 0;
182 newpanel.volume = id;
183 panels.push_back(std::move(newpanel));
184 }
185 // The y=ymin face.
186 if (m_lX > 0 && m_lZ > 0) {
187 ToGlobal(-m_lX, -m_lY, -m_lZ, xv0, yv0, zv0);
188 ToGlobal(+m_lX, -m_lY, -m_lZ, xv1, yv1, zv1);
189 ToGlobal(+m_lX, -m_lY, +m_lZ, xv2, yv2, zv2);
190 ToGlobal(-m_lX, -m_lY, +m_lZ, xv3, yv3, zv3);
191 Panel newpanel;
192 newpanel.a = m_sPhi;
193 newpanel.b = -m_cPhi;
194 newpanel.c = 0;
195 newpanel.xv = {xv0, xv1, xv2, xv3};
196 newpanel.yv = {yv0, yv1, yv2, yv3};
197 newpanel.zv = {zv0, zv1, zv2, zv3};
198 newpanel.colour = 0;
199 newpanel.volume = id;
200 panels.push_back(std::move(newpanel));
201 }
202 // The y=ymax face.
203 if (m_lX > 0 && m_lY > 0 && m_lZ > 0) {
204 ToGlobal(-m_lX, +m_lY, -m_lZ, xv0, yv0, zv0);
205 ToGlobal(+m_lX, +m_lY, -m_lZ, xv1, yv1, zv1);
206 ToGlobal(+m_lX, +m_lY, +m_lZ, xv2, yv2, zv2);
207 ToGlobal(-m_lX, +m_lY, +m_lZ, xv3, yv3, zv3);
208 Panel newpanel;
209 newpanel.a = -m_sPhi;
210 newpanel.b = m_cPhi;
211 newpanel.c = 0;
212 newpanel.xv = {xv0, xv1, xv2, xv3};
213 newpanel.yv = {yv0, yv1, yv2, yv3};
214 newpanel.zv = {zv0, zv1, zv2, zv3};
215 newpanel.colour = 0;
216 newpanel.volume = id;
217 panels.push_back(std::move(newpanel));
218 }
219 const double phi0 = -0.5 * HalfPi;
220 const double dphi = HalfPi / double(m_n - 1);
221 // The faces at constant z have a hole, and are drawn in parts.
222 for (int iside = -1; iside <= 1; iside += 2) {
223 const double r = iside == -1 ? r1 : r2;
224 const double w = m_lZ * iside;
225 Panel newpanel;
226 newpanel.a = iside * m_cPhi * m_sTheta;
227 newpanel.b = iside * m_sPhi * m_sTheta;
228 newpanel.c = iside * m_cTheta;
229 newpanel.colour = 0;
230 newpanel.volume = id;
231 // Loop over the panels.
232 for (unsigned int i = 0; i < m_n - 1; ++i) {
233 // The panels for x=xmax.
234 const double phi1 = phi0 + dphi * i;
235 const double phi2 = phi1 + dphi;
236 const double t1 = tan(phi1);
237 const double t2 = tan(phi2);
238 ToGlobal(r * cos(phi1), r * sin(phi1), w, xv0, yv0, zv0);
239 ToGlobal(r * cos(phi2), r * sin(phi2), w, xv3, yv3, zv3);
240 ToGlobal(m_lX, m_lY * t1, w, xv1, yv1, zv1);
241 ToGlobal(m_lX, m_lY * t2, w, xv2, yv2, zv2);
242 newpanel.xv = {xv0, xv1, xv2, xv3};
243 newpanel.yv = {yv0, yv1, yv2, yv3};
244 newpanel.zv = {zv0, zv1, zv2, zv3};
245 panels.push_back(newpanel);
246 // The panels for y=ymax.
247 const double phi3 = phi1 + HalfPi;
248 const double phi4 = phi3 + dphi;
249 ToGlobal(r * cos(phi3), r * sin(phi3), w, xv0, yv0, zv0);
250 ToGlobal(r * cos(phi4), r * sin(phi4), w, xv3, yv3, zv3);
251 ToGlobal(-m_lX * t1, m_lY, w, xv1, yv1, zv1);
252 ToGlobal(-m_lX * t2, m_lY, w, xv2, yv2, zv2);
253 newpanel.xv = {xv0, xv1, xv2, xv3};
254 newpanel.yv = {yv0, yv1, yv2, yv3};
255 newpanel.zv = {zv0, zv1, zv2, zv3};
256 panels.push_back(newpanel);
257 // The panels for x=xmin.
258 const double phi5 = phi3 + HalfPi;
259 const double phi6 = phi5 + dphi;
260 ToGlobal(r * cos(phi5), r * sin(phi5), w, xv0, yv0, zv0);
261 ToGlobal(r * cos(phi6), r * sin(phi6), w, xv3, yv3, zv3);
262 ToGlobal(-m_lX, -m_lY * t1, w, xv1, yv1, zv1);
263 ToGlobal(-m_lX, -m_lY * t2, w, xv2, yv2, zv2);
264 newpanel.xv = {xv0, xv1, xv2, xv3};
265 newpanel.yv = {yv0, yv1, yv2, yv3};
266 newpanel.zv = {zv0, zv1, zv2, zv3};
267 panels.push_back(newpanel);
268 // The panels for y=ymin.
269 const double phi7 = phi5 + HalfPi;
270 const double phi8 = phi7 + dphi;
271 ToGlobal(r * cos(phi7), r * sin(phi7), w, xv0, yv0, zv0);
272 ToGlobal(r * cos(phi8), r * sin(phi8), w, xv3, yv3, zv3);
273 ToGlobal(m_lX * t1, -m_lY, w, xv1, yv1, zv1);
274 ToGlobal(m_lX * t2, -m_lY, w, xv2, yv2, zv2);
275 newpanel.xv = {xv0, xv1, xv2, xv3};
276 newpanel.yv = {yv0, yv1, yv2, yv3};
277 newpanel.zv = {zv0, zv1, zv2, zv3};
278 panels.push_back(newpanel);
279 }
280 }
281 // The panels of the central cylinder, compute the projection angles.
282 const double alpha = atan2((r1 - r2) * cos(Pi / (4 * (m_n - 1))),
283 2 * m_lZ);
284 const double ci = cos(alpha);
285 const double si = sin(alpha);
286 // Initialise loop.
287 ToGlobal(r1 * cos(phi0), r1 * sin(phi0), -m_lZ, xv0, yv0, zv0);
288 ToGlobal(r2 * cos(phi0), r2 * sin(phi0), +m_lZ, xv1, yv1, zv1);
289 // Go around the cylinder.
290 const unsigned int nPoints = 4 * m_n - 3;
291 for (unsigned int i = 1; i < nPoints; ++i) {
292 // Bottom and top of the line along the axis of the cylinder.
293 const double phi = phi0 + dphi * i;
294 ToGlobal(r2 * cos(phi), r2 * sin(phi), +m_lZ, xv2, yv2, zv2);
295 ToGlobal(r1 * cos(phi), r1 * sin(phi), -m_lZ, xv3, yv3, zv3);
296 // Store the plane.
297 Panel newpanel;
298 const double phim = phi0 + dphi * (i - 0.5);
299 const double cm = cos(phim);
300 const double sm = sin(phim);
301 newpanel.a = -m_cPhi * m_cTheta * cm * ci +
302 m_sPhi * sm * ci -
303 m_cPhi * m_sTheta * si;
304 newpanel.b = -m_sPhi * m_cTheta * cm * ci -
305 m_cPhi * sm * ci -
306 m_sPhi * m_sTheta * si;
307 newpanel.c = m_sTheta * cm * ci - m_cTheta * si;
308 newpanel.xv = {xv0, xv1, xv2, xv3};
309 newpanel.yv = {yv0, yv1, yv2, yv3};
310 newpanel.zv = {zv0, zv1, zv2, zv3};
311 newpanel.colour = 0;
312 newpanel.volume = id;
313 panels.push_back(std::move(newpanel));
314 // Shift the points.
315 xv0 = xv3;
316 yv0 = yv3;
317 zv0 = zv3;
318 xv1 = xv2;
319 yv1 = yv2;
320 zv1 = zv2;
321 }
322 std::cout << "SolidHole::SolidPanels: " << panels.size() - nPanels
323 << " panels.\n";
324 return true;
325}
326
328
329 // Transform the normal vector to local coordinates.
330 double un = 0., vn = 0., wn = 0.;
331 VectorToLocal(panel.a, panel.b, panel.c, un, vn, wn);
332 // Transform one of the points (first).
333 double u1 = 0., v1 = 0., w1 = 0.;
334 ToLocal(panel.xv[0], panel.yv[0], panel.zv[0], u1, v1, w1);
335 // Identify the vector.
336 if (wn > std::max(std::abs(un), std::abs(vn))) {
337 return m_dis[0];
338 } else if (wn < -std::max(std::abs(un), std::abs(vn))) {
339 return m_dis[1];
340 } else if (un * u1 + vn * v1 + wn * w1 < 0) {
341 return m_dis[2];
342 } else if (un > std::max(std::abs(vn), std::abs(wn))) {
343 return m_dis[3];
344 } else if (un < -std::max(std::abs(vn), std::abs(wn))) {
345 return m_dis[4];
346 } else if (vn > std::max(std::abs(un), std::abs(wn))) {
347 return m_dis[5];
348 } else if (vn < -std::max(std::abs(un), std::abs(wn))) {
349 return m_dis[6];
350 }
351 if (m_debug) {
352 std::cout << m_className << "::GetDiscretisationLevel:\n"
353 << " Found no match for the panel; returning first value.\n";
354 }
355 return m_dis[0];
356}
357
358}
Box with a cylindrical hole.
Definition: SolidHole.hh:10
void SetHalfLengthY(const double ly)
Set the half-length of the box along y.
Definition: SolidHole.cc:102
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) const override
Return the bounding box of the solid.
Definition: SolidHole.cc:56
double GetDiscretisationLevel(const Panel &panel) override
Retrieve the discretization level of a panel.
Definition: SolidHole.cc:327
void SetSectors(const unsigned int n)
Definition: SolidHole.cc:118
void SetHalfLengthX(const double lx)
Set the half-length of the box along x.
Definition: SolidHole.cc:94
void SetLowerRadius(const double r)
Set the radius at z = -lz.
Definition: SolidHole.cc:86
bool SolidPanels(std::vector< Panel > &panels) override
Retrieve the surface panels of the solid.
Definition: SolidHole.cc:126
void SetHalfLengthZ(const double lz)
Set the half-length of the box along z.
Definition: SolidHole.cc:110
bool IsInside(const double x, const double y, const double z) const override
Check whether a given point is inside the solid.
Definition: SolidHole.cc:27
void SetUpperRadius(const double r)
Set the radius at z = +lz.
Definition: SolidHole.cc:78
SolidHole(const double cx, const double cy, const double cz, const double rup, const double rlow, const double lx, const double ly, const double lz)
Constructor from centre, upper/lower radii, half-lengths of the box.
Definition: SolidHole.cc:9
Abstract base class for solids.
Definition: Solid.hh:28
double m_dZ
Definition: Solid.hh:167
double m_cZ
Definition: Solid.hh:164
void VectorToLocal(const double x, const double y, const double z, double &u, double &v, double &w)
Transform a vector from global to local coordinates.
Definition: Solid.hh:209
double m_cTheta
Polar angle.
Definition: Solid.hh:171
double m_dX
Direction vector.
Definition: Solid.hh:167
unsigned int GetId() const
Get the ID of the solid.
Definition: Solid.hh:117
void ToLocal(const double x, const double y, const double z, double &u, double &v, double &w) const
Definition: Solid.hh:190
void SetDirection(const double dx, const double dy, const double dz)
Definition: Solid.cc:12
double m_sPhi
Definition: Solid.hh:169
void ToGlobal(const double u, const double v, const double w, double &x, double &y, double &z) const
Definition: Solid.hh:202
double m_sTheta
Definition: Solid.hh:171
double m_cY
Definition: Solid.hh:164
bool m_debug
Debug flag.
Definition: Solid.hh:177
double m_dY
Definition: Solid.hh:167
double m_cX
Centre of the solid.
Definition: Solid.hh:164
double m_cPhi
Azimuthal angle.
Definition: Solid.hh:169
std::string m_className
Class name.
Definition: Solid.hh:174
Surface panel.
Definition: Solid.hh:11
std::vector< double > zv
Z-coordinates of vertices.
Definition: Solid.hh:19
int volume
Reference to solid to which the panel belongs.
Definition: Solid.hh:23
double a
Perpendicular vector.
Definition: Solid.hh:13
double c
Definition: Solid.hh:13
double colour
Colour index.
Definition: Solid.hh:21
double b
Definition: Solid.hh:13
std::vector< double > xv
X-coordinates of vertices.
Definition: Solid.hh:15
std::vector< double > yv
Y-coordinates of vertices.
Definition: Solid.hh:17