Garfield++ 5.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
SolidSphere.cc
Go to the documentation of this file.
1#include <cmath>
2#include <iostream>
3
6#include "Garfield/Polygon.hh"
8
9namespace {
10
11bool InPolyhedron(const std::vector<Garfield::Panel>& panels,
12 const double x, const double y, const double z,
13 const bool inv = false) {
14
15 for (const auto& panel : panels) {
16 double d = panel.a * (panel.xv[0] - x) + panel.b * (panel.yv[0] - y) +
17 panel.c * (panel.zv[0] - z);
18 if (inv) d *= -1;
19 if (d < 0.) return false;
20 }
21 return true;
22}
23
24}
25
26namespace Garfield {
27
28SolidSphere::SolidSphere(const double cx, const double cy, const double cz,
29 const double r)
30 : Solid(cx, cy, cz, "SolidSphere") {
31 SetRadius(r);
32 UpdatePanels();
33}
34
35SolidSphere::SolidSphere(const double cx, const double cy, const double cz,
36 const double rmin, const double rmax)
37 : Solid(cx, cy, cz, "SolidSphere") {
38 SetRadii(rmin, rmax);
39 UpdatePanels();
40}
41
42bool SolidSphere::IsInside(const double x, const double y, const double z,
43 const bool tesselated) const {
44 // Transform the point to local coordinates.
45 const double dx = x - m_cX;
46 const double dy = y - m_cY;
47 const double dz = z - m_cZ;
48
49 if (fabs(dx) > m_rMax || fabs(dy) > m_rMax || fabs(dz) > m_rMax) {
50 return false;
51 }
52 const double r = sqrt(dx * dx + dy * dy + dz * dz);
53 if (!tesselated) return (r >= m_rMin && r <= m_rMax);
54 if (r > m_rMax || !InPolyhedron(m_panelsO, dx, dy, dz)) return false;
55 if (m_rMin > 0.) {
56 return (r >= m_rMin || !InPolyhedron(m_panelsI, dx, dy, dz, true));
57 }
58 return true;
59}
60
61bool SolidSphere::GetBoundingBox(double& xmin, double& ymin, double& zmin,
62 double& xmax, double& ymax,
63 double& zmax) const {
64 xmin = m_cX - m_rMax;
65 xmax = m_cX + m_rMax;
66 ymin = m_cY - m_rMax;
67 ymax = m_cY + m_rMax;
68 zmin = m_cZ - m_rMax;
69 zmax = m_cZ + m_rMax;
70 return true;
71}
72
73void SolidSphere::SetRadius(const double r) {
74 if (r <= 0.) {
75 std::cerr << "SolidSphere::SetRadius: Radius must be > 0.\n";
76 return;
77 }
78 m_rMax = r;
79 m_rMin = 0.;
80 UpdatePanels();
81}
82
83void SolidSphere::SetRadii(const double rmin, const double rmax) {
84 if (rmax <= 0.) {
85 std::cerr << "SolidSphere::SetRadii: Outer radius must be > 0.\n";
86 return;
87 }
88 if (rmin >= rmax) {
89 std::cerr << "SolidSphere::SetRadii:\n"
90 << " Outer radius must be > inner radius.\n";
91 return;
92 }
93 m_rMin = rmin;
94 m_rMax = rmax;
95 UpdatePanels();
96}
97
98void SolidSphere::SetMeridians(const unsigned int n) {
99 if (n < 3) {
100 std::cerr << "SolidSphere::SetMeridians: Number must be >= 3.\n";
101 return;
102 }
103 m_n = n;
104 UpdatePanels();
105}
106
107bool SolidSphere::SolidPanels(std::vector<Panel>& panels) {
108
109 const auto nPanels = panels.size();
110 panels.insert(panels.begin(), m_panelsO.begin(), m_panelsO.end());
111 panels.insert(panels.begin(), m_panelsI.begin(), m_panelsI.end());
112 std::cout << "SolidSphere::SolidPanels: " << panels.size() - nPanels
113 << " panels.\n";
114 return true;
115}
116
117void SolidSphere::UpdatePanels() {
118 std::lock_guard<std::mutex> guard(m_mutex);
119 m_panelsO.clear();
120 m_panelsI.clear();
121 const auto id = GetId();
122 MakePanels(id, m_rMax, true, m_panelsO);
123 if (m_rMin > 0.) {
124 MakePanels(id, m_rMin, false, m_panelsI);
125 }
126}
127
128void SolidSphere::MakePanels(const int vol, const double r, const bool out,
129 std::vector<Panel>& panels) const {
130
131 const double dphi = TwoPi / m_n;
132 const double dtheta = Pi / m_n;
133 // Loop over the sphere.
134 for (unsigned int i = 1; i <= m_n; ++i) {
135 const double phi0 = (i - 1.) * dphi;
136 const double phi1 = phi0 + dphi;
137 const double cphi0 = cos(phi0);
138 const double sphi0 = sin(phi0);
139 const double cphi1 = cos(phi1);
140 const double sphi1 = sin(phi1);
141 for (unsigned int j = 1; j <= m_n; ++j) {
142 const double theta0 = -HalfPi + (j - 1.) * dtheta;
143 const double theta1 = theta0 + dtheta;
144 const double ctheta0 = cos(theta0);
145 const double stheta0 = sin(theta0);
146 const double ctheta1 = cos(theta1);
147 const double stheta1 = sin(theta1);
148 Panel panel;
149 panel.colour = m_colour;
150 // Corners of this parcel.
151 if (j == 1) {
152 const double xv0 = m_cX + r * cphi0 * ctheta0;
153 const double yv0 = m_cY + r * sphi0 * ctheta0;
154 const double zv0 = m_cZ + r * stheta0;
155 const double xv1 = m_cX + r * cphi1 * ctheta1;
156 const double yv1 = m_cY + r * sphi1 * ctheta1;
157 const double zv1 = m_cZ + r * stheta1;
158 const double xv2 = m_cX + r * cphi0 * ctheta1;
159 const double yv2 = m_cY + r * sphi0 * ctheta1;
160 const double zv2 = m_cZ + r * stheta1;
161 panel.xv = {xv0, xv1, xv2};
162 panel.yv = {yv0, yv1, yv2};
163 panel.zv = {zv0, zv1, zv2};
164 } else if (j == m_n) {
165 const double xv0 = m_cX + r * cphi0 * ctheta0;
166 const double yv0 = m_cY + r * sphi0 * ctheta0;
167 const double zv0 = m_cZ + r * stheta0;
168 const double xv1 = m_cX + r * cphi1 * ctheta0;
169 const double yv1 = m_cY + r * sphi1 * ctheta0;
170 const double zv1 = m_cZ + r * stheta0;
171 const double xv2 = m_cX + r * cphi1 * ctheta1;
172 const double yv2 = m_cY + r * sphi1 * ctheta1;
173 const double zv2 = m_cZ + r * stheta1;
174 panel.xv = {xv0, xv1, xv2};
175 panel.yv = {yv0, yv1, yv2};
176 panel.zv = {zv0, zv1, zv2};
177 } else {
178 const double xv0 = m_cX + r * cphi0 * ctheta0;
179 const double yv0 = m_cY + r * sphi0 * ctheta0;
180 const double zv0 = m_cZ + r * stheta0;
181 const double xv1 = m_cX + r * cphi1 * ctheta0;
182 const double yv1 = m_cY + r * sphi1 * ctheta0;
183 const double zv1 = m_cZ + r * stheta0;
184 const double xv2 = m_cX + r * cphi1 * ctheta1;
185 const double yv2 = m_cY + r * sphi1 * ctheta1;
186 const double zv2 = m_cZ + r * stheta1;
187 const double xv3 = m_cX + r * cphi0 * ctheta1;
188 const double yv3 = m_cY + r * sphi0 * ctheta1;
189 const double zv3 = m_cZ + r * stheta1;
190 panel.xv = {xv0, xv1, xv2, xv3};
191 panel.yv = {yv0, yv1, yv2, yv3};
192 panel.zv = {zv0, zv1, zv2, zv3};
193 }
194 // Inclination angle in theta.
195 const double alpha =
196 atan2((ctheta0 - ctheta1) * sqrt((1. + cos(phi1 - phi0)) / 2),
197 stheta1 - stheta0);
198 const double calpha = cos(alpha);
199 const double salpha = sin(alpha);
200 // Store the panel.
201 if (out) {
202 panel.a = cos(0.5 * (phi0 + phi1)) * calpha;
203 panel.b = sin(0.5 * (phi0 + phi1)) * calpha;
204 panel.c = salpha;
205 } else {
206 panel.a = -cos(0.5 * (phi0 + phi1)) * calpha;
207 panel.b = -sin(0.5 * (phi0 + phi1)) * calpha;
208 panel.c = -salpha;
209 }
210 panel.volume = vol;
211 panels.push_back(std::move(panel));
212 }
213 }
214}
215
217 return m_dis;
218}
219
220void SolidSphere::Cut(const double x0, const double y0, const double z0,
221 const double xn, const double yn, const double zn,
222 std::vector<Panel>& panels) {
223
224 //-----------------------------------------------------------------------
225 // PLASPC - Cuts sphere IVOL with a plane.
226 //-----------------------------------------------------------------------
227 std::vector<double> xv;
228 std::vector<double> yv;
229 std::vector<double> zv;
230 // Loop over the sphere.
231 const double r = m_rMax;
232 for (unsigned int i = 1; i <= m_n; ++i) {
233 // phi-Coordinates.
234 const double phi0 = TwoPi * (i - 1.) / m_n;
235 const double phi1 = TwoPi * i / m_n;
236 for (unsigned int j = 1; j <= m_n; ++j) {
237 // theta-Coordinates.
238 const double theta0 = -HalfPi + Pi * (j - 1.) / m_n;
239 const double theta1 = -HalfPi + Pi * j / m_n;
240 // Reference point of this square.
241 const double x1 = x0 + r * cos(phi0) * cos(theta0);
242 const double y1 = y0 + r * sin(phi0) * cos(theta0);
243 const double z1 = z0 + r * sin(theta0);
244 // The meridian segment, doesn't exist at the S pole.
245 if (j > 0) {
246 const double x2 = x0 + r * cos(phi1) * cos(theta0);
247 const double y2 = y0 + r * sin(phi1) * cos(theta0);
248 const double z2 = z0 + r * sin(theta0);
249 // Cut with the plane.
250 double xc, yc, zc;
251 if (Intersect(x1, y1, z1, x2, y2, z2,
252 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
253 xv.push_back(xc);
254 yv.push_back(yc);
255 zv.push_back(zc);
256 }
257 }
258 // The latitude.
259 const double x2 = x0 + r * cos(phi0) * cos(theta1);
260 const double y2 = y0 + r * sin(phi0) * cos(theta1);
261 const double z2 = z0 + r * sin(theta1);
262 // Cut with the plane.
263 double xc, yc, zc;
264 if (Intersect(x1, y1, z1, x2, y2, z2,
265 x0, y0, z0, xn, yn, zn, xc, yc, zc)) {
266 xv.push_back(xc);
267 yv.push_back(yc);
268 zv.push_back(zc);
269 }
270 }
271 }
272 // Get rid of butterflies.
274
275 if (xv.size() >= 3) {
276 Panel panel;
277 panel.a = xn;
278 panel.b = yn;
279 panel.c = zn;
280 panel.xv = xv;
281 panel.yv = yv;
282 panel.zv = zv;
283 panel.colour = m_colour;
284 panel.volume = GetId();
285 panels.push_back(std::move(panel));
286 }
287}
288
289}
bool IsInside(const double x, const double y, const double z, const bool tesselated) const override
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) const override
Return the bounding box of the solid.
void SetRadii(const double rmin, const double rmax)
Set the inner and outer radius of the sphere.
void SetRadius(const double r)
Set the radius of the sphere.
void Cut(const double x0, const double y0, const double z0, const double xn, const double yn, const double zn, std::vector< Panel > &panels) override
double GetDiscretisationLevel(const Panel &panel) override
Retrieve the discretisation level of a panel.
bool SolidPanels(std::vector< Panel > &panels) override
Retrieve the surface panels of the solid.
SolidSphere(const double cx, const double cy, const double cz, const double r)
Constructor from centre and outer radius.
void SetMeridians(const unsigned int n)
double m_cZ
Definition Solid.hh:202
static bool Intersect(const double x1, const double y1, const double z1, const double x2, const double y2, const double z2, const double x0, const double y0, const double z0, const double a, const double b, const double c, double &xc, double &yc, double &zc)
Definition Solid.cc:52
unsigned int GetId() const
Get the ID of the solid.
Definition Solid.hh:137
int m_colour
Colour.
Definition Solid.hh:230
double m_cY
Definition Solid.hh:202
double m_cX
Centre of the solid.
Definition Solid.hh:202
Solid()=delete
Default constructor.
void EliminateButterflies(std::vector< double > &xp, std::vector< double > &yp, std::vector< double > &zp)
Definition Polygon.cc:355
DoubleAc cos(const DoubleAc &f)
Definition DoubleAc.cpp:432
DoubleAc sin(const DoubleAc &f)
Definition DoubleAc.cpp:384
DoubleAc sqrt(const DoubleAc &f)
Definition DoubleAc.cpp:314
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
std::vector< double > xv
X-coordinates of vertices.
Definition Solid.hh:15
std::vector< double > yv
Y-coordinates of vertices.
Definition Solid.hh:17
int colour
Colour index.
Definition Solid.hh:21