10void CutBox(
const std::array<double, 8>& xbox,
11 const std::array<double, 8>& ybox,
12 const std::array<double, 8>& zbox,
13 std::vector<double>& xcut,
14 std::vector<double>& ycut,
15 std::vector<double>& zcut,
16 const double x0,
const double y0,
const double z0,
17 const double a,
const double b,
const double c) {
26 for (
unsigned int i = 0; i < 8; ++i) {
28 unsigned int j = i + 1;
35 xbox[j], ybox[j], zbox[j],
36 x0, y0, z0, a, b, c, xc, yc, zc)) {
42 for (
unsigned int i = 0; i < 4; ++i) {
44 const unsigned int j = i + 4;
46 xbox[j], ybox[j], zbox[j],
47 x0, y0, z0, a, b, c, xc, yc, zc)) {
63 const double rup,
const double rlow,
64 const double lx,
const double ly,
const double lz)
65 :
Solid(cx, cy, cz,
"SolidHole"),
75 const double rup,
const double rlow,
76 const double lx,
const double ly,
const double lz,
77 const double dx,
const double dy,
const double dz)
78 :
SolidHole(cx, cy, cz, rup, rlow, lx, ly, lz) {
82void SolidHole::Update() {
83 std::lock_guard<std::mutex> guard(m_mutex);
84 const double alpha = Pi / (4. * (m_n - 1.));
86 m_fp = 2. / (1. + asinh(tan(alpha)) * cos(alpha) / tan(alpha));
94 const bool tesselated)
const {
96 double u = x, v = y, w = z;
99 if (fabs(u) > m_lX || fabs(v) > m_lY || fabs(w) > m_lZ) {
103 double r = m_rLow + (w + m_lZ) * (m_rUp - m_rLow) / (2 * m_lZ);
104 if (!tesselated)
return (u * u + v * v >= r * r);
105 const double rho = sqrt(u * u + v * v);
106 if (m_average) r *= m_fp;
107 if (rho > r)
return true;
108 if (rho < r * m_fi)
return false;
110 std::vector<double> xp;
111 std::vector<double> yp;
112 const double phi0 = -0.5 * HalfPi;
113 const double dphi = HalfPi / double(m_n - 1);
114 const unsigned int nP = 4 * (m_n - 1);
115 for (
unsigned int i = 0; i < nP; ++i) {
117 const double phi = phi0 + dphi * i;
118 xp.push_back(r * cos(phi));
119 yp.push_back(r * sin(phi));
128 double& xmax,
double& ymax,
double& zmax)
const {
139 const double dd = sqrt(m_lX * m_lX + m_lY * m_lY + m_lZ * m_lZ);
151 std::cerr <<
"SolidHole::SetUpperRadius: Radius must be > 0.\n";
159 std::cerr <<
"SolidHole::SetLowerRadius: Radius must be > 0.\n";
167 std::cerr <<
"SolidHole::SetHalfLengthX: Half-length must be > 0.\n";
175 std::cerr <<
"SolidHole::SetHalfLengthY: Half-length must be > 0.\n";
183 std::cerr <<
"SolidHole::SetHalfLengthZ: Half-length must be > 0.\n";
191 std::cerr <<
"SolidHole::SetSectors: Number must be > 0.\n";
199 const auto id =
GetId();
200 const auto nPanels = panels.size();
204 std::cerr <<
"SolidHole::SolidPanels:\n"
205 <<
" Zero norm direction vector; no panels generated.\n";
217 double xv0, yv0, zv0;
218 double xv1, yv1, zv1;
219 double xv2, yv2, zv2;
220 double xv3, yv3, zv3;
222 if (m_lY > 0 && m_lZ > 0) {
223 ToGlobal(-m_lX, -m_lY, -m_lZ, xv0, yv0, zv0);
224 ToGlobal(-m_lX, +m_lY, -m_lZ, xv1, yv1, zv1);
225 ToGlobal(-m_lX, +m_lY, +m_lZ, xv2, yv2, zv2);
226 ToGlobal(-m_lX, -m_lY, +m_lZ, xv3, yv3, zv3);
231 panel.
xv = {xv0, xv1, xv2, xv3};
232 panel.
yv = {yv0, yv1, yv2, yv3};
233 panel.
zv = {zv0, zv1, zv2, zv3};
236 panels.push_back(std::move(panel));
239 if (m_lX > 0 && m_lY > 0 && m_lZ > 0) {
240 ToGlobal(+m_lX, -m_lY, -m_lZ, xv0, yv0, zv0);
241 ToGlobal(+m_lX, +m_lY, -m_lZ, xv1, yv1, zv1);
242 ToGlobal(+m_lX, +m_lY, +m_lZ, xv2, yv2, zv2);
243 ToGlobal(+m_lX, -m_lY, +m_lZ, xv3, yv3, zv3);
248 panel.
xv = {xv0, xv1, xv2, xv3};
249 panel.
yv = {yv0, yv1, yv2, yv3};
250 panel.
zv = {zv0, zv1, zv2, zv3};
253 panels.push_back(std::move(panel));
256 if (m_lX > 0 && m_lZ > 0) {
257 ToGlobal(-m_lX, -m_lY, -m_lZ, xv0, yv0, zv0);
258 ToGlobal(+m_lX, -m_lY, -m_lZ, xv1, yv1, zv1);
259 ToGlobal(+m_lX, -m_lY, +m_lZ, xv2, yv2, zv2);
260 ToGlobal(-m_lX, -m_lY, +m_lZ, xv3, yv3, zv3);
265 panel.
xv = {xv0, xv1, xv2, xv3};
266 panel.
yv = {yv0, yv1, yv2, yv3};
267 panel.
zv = {zv0, zv1, zv2, zv3};
270 panels.push_back(std::move(panel));
273 if (m_lX > 0 && m_lY > 0 && m_lZ > 0) {
274 ToGlobal(-m_lX, +m_lY, -m_lZ, xv0, yv0, zv0);
275 ToGlobal(+m_lX, +m_lY, -m_lZ, xv1, yv1, zv1);
276 ToGlobal(+m_lX, +m_lY, +m_lZ, xv2, yv2, zv2);
277 ToGlobal(-m_lX, +m_lY, +m_lZ, xv3, yv3, zv3);
282 panel.
xv = {xv0, xv1, xv2, xv3};
283 panel.
yv = {yv0, yv1, yv2, yv3};
284 panel.
zv = {zv0, zv1, zv2, zv3};
287 panels.push_back(std::move(panel));
289 const double phi0 = -0.5 * HalfPi;
290 const double dphi = HalfPi / double(m_n - 1);
292 for (
int iside = -1; iside <= 1; iside += 2) {
293 const double r = iside == -1 ? r1 : r2;
294 const double w = m_lZ * iside;
302 for (
unsigned int i = 0; i < m_n - 1; ++i) {
304 const double phi1 = phi0 + dphi * i;
305 const double phi2 = phi1 + dphi;
306 const double t1 = tan(phi1);
307 const double t2 = tan(phi2);
308 ToGlobal(r * cos(phi1), r * sin(phi1), w, xv0, yv0, zv0);
309 ToGlobal(r * cos(phi2), r * sin(phi2), w, xv3, yv3, zv3);
310 ToGlobal(m_lX, m_lY * t1, w, xv1, yv1, zv1);
311 ToGlobal(m_lX, m_lY * t2, w, xv2, yv2, zv2);
312 panel.
xv = {xv0, xv1, xv2, xv3};
313 panel.
yv = {yv0, yv1, yv2, yv3};
314 panel.
zv = {zv0, zv1, zv2, zv3};
315 panels.push_back(panel);
317 const double phi3 = phi1 + HalfPi;
318 const double phi4 = phi3 + dphi;
319 ToGlobal(r * cos(phi3), r * sin(phi3), w, xv0, yv0, zv0);
320 ToGlobal(r * cos(phi4), r * sin(phi4), w, xv3, yv3, zv3);
321 ToGlobal(-m_lX * t1, m_lY, w, xv1, yv1, zv1);
322 ToGlobal(-m_lX * t2, m_lY, w, xv2, yv2, zv2);
323 panel.
xv = {xv0, xv1, xv2, xv3};
324 panel.
yv = {yv0, yv1, yv2, yv3};
325 panel.
zv = {zv0, zv1, zv2, zv3};
326 panels.push_back(panel);
328 const double phi5 = phi3 + HalfPi;
329 const double phi6 = phi5 + dphi;
330 ToGlobal(r * cos(phi5), r * sin(phi5), w, xv0, yv0, zv0);
331 ToGlobal(r * cos(phi6), r * sin(phi6), w, xv3, yv3, zv3);
332 ToGlobal(-m_lX, -m_lY * t1, w, xv1, yv1, zv1);
333 ToGlobal(-m_lX, -m_lY * t2, w, xv2, yv2, zv2);
334 panel.
xv = {xv0, xv1, xv2, xv3};
335 panel.
yv = {yv0, yv1, yv2, yv3};
336 panel.
zv = {zv0, zv1, zv2, zv3};
337 panels.push_back(panel);
339 const double phi7 = phi5 + HalfPi;
340 const double phi8 = phi7 + dphi;
341 ToGlobal(r * cos(phi7), r * sin(phi7), w, xv0, yv0, zv0);
342 ToGlobal(r * cos(phi8), r * sin(phi8), w, xv3, yv3, zv3);
343 ToGlobal(m_lX * t1, -m_lY, w, xv1, yv1, zv1);
344 ToGlobal(m_lX * t2, -m_lY, w, xv2, yv2, zv2);
345 panel.
xv = {xv0, xv1, xv2, xv3};
346 panel.
yv = {yv0, yv1, yv2, yv3};
347 panel.
zv = {zv0, zv1, zv2, zv3};
348 panels.push_back(panel);
352 const double alpha = atan2((r1 - r2) * cos(Pi / (4 * (m_n - 1))),
354 const double ci = cos(alpha);
355 const double si = sin(alpha);
357 ToGlobal(r1 * cos(phi0), r1 * sin(phi0), -m_lZ, xv0, yv0, zv0);
358 ToGlobal(r2 * cos(phi0), r2 * sin(phi0), +m_lZ, xv1, yv1, zv1);
360 const unsigned int nPoints = 4 * m_n - 3;
361 for (
unsigned int i = 1; i < nPoints; ++i) {
363 const double phi = phi0 + dphi * i;
364 ToGlobal(r2 * cos(phi), r2 * sin(phi), +m_lZ, xv2, yv2, zv2);
365 ToGlobal(r1 * cos(phi), r1 * sin(phi), -m_lZ, xv3, yv3, zv3);
368 const double phim = phi0 + dphi * (i - 0.5);
369 const double cm = cos(phim);
370 const double sm = sin(phim);
378 panel.
xv = {xv0, xv1, xv2, xv3};
379 panel.
yv = {yv0, yv1, yv2, yv3};
380 panel.
zv = {zv0, zv1, zv2, zv3};
383 panels.push_back(std::move(panel));
392 std::cout <<
"SolidHole::SolidPanels: " << panels.size() - nPanels
400 double un = 0., vn = 0., wn = 0.;
403 double u1 = 0., v1 = 0., w1 = 0.;
406 if (wn > std::max(std::abs(un), std::abs(vn))) {
408 }
else if (wn < -std::max(std::abs(un), std::abs(vn))) {
410 }
else if (un * u1 + vn * v1 + wn * w1 < 0) {
412 }
else if (un > std::max(std::abs(vn), std::abs(wn))) {
414 }
else if (un < -std::max(std::abs(vn), std::abs(wn))) {
416 }
else if (vn > std::max(std::abs(un), std::abs(wn))) {
418 }
else if (vn < -std::max(std::abs(un), std::abs(wn))) {
422 std::cout <<
m_className <<
"::GetDiscretisationLevel:\n"
423 <<
" Found no match for the panel; returning first value.\n";
429 const double xn,
const double yn,
const double zn,
430 std::vector<Panel>& panels) {
443 std::array<double, 8> xbox;
444 std::array<double, 8> ybox;
445 std::array<double, 8> zbox;
447 const double dphi = HalfPi / (m_n - 1.);
448 for (
unsigned int i = 1; i <= m_n - 1; ++i) {
449 const double phi1 = dphi * (i - 1.);
450 const double phi2 = dphi * i;
451 const double t1 = tan(-0.5 * HalfPi + phi1);
452 const double t2 = tan(-0.5 * HalfPi + phi2);
454 for (
int iside : {-1, 1}) {
455 const double r = iside < 0 ? r1 : r2;
456 const double w = iside * m_lZ;
457 const unsigned int k = iside < 0 ? 0 : 4;
458 const double phi0 = -0.5 * HalfPi;
459 ToGlobal(r * cos(phi0 + phi1), r * sin(phi0 + phi1), w,
460 xbox[k], ybox[k], zbox[k]);
461 ToGlobal(r * cos(phi0 + phi2), r * sin(phi0 + phi2), w,
462 xbox[k + 3], ybox[k + 3], zbox[k + 3]);
463 ToGlobal(m_lX, m_lY * t1, w, xbox[k + 1], ybox[k + 1], zbox[k + 1]);
464 ToGlobal(m_lX, m_lY * t2, w, xbox[k + 2], ybox[k + 2], zbox[k + 2]);
466 std::vector<double> xv;
467 std::vector<double> yv;
468 std::vector<double> zv;
469 CutBox(xbox, ybox, zbox, xv, yv, zv, x0, y0, z0, xn, yn, zn);
470 if (xv.size() >= 3) {
480 panels.push_back(std::move(panel));
486 for (
int iside : {-1, 1}) {
487 const double r = iside < 0 ? r1 : r2;
488 const double w = iside * m_lZ;
489 const unsigned int k = iside < 0 ? 0 : 4;
490 const double phi0 = 0.5 * HalfPi;
491 ToGlobal(r * cos(phi0 + phi1), r * sin(phi0 + phi1), w,
492 xbox[k], ybox[k], zbox[k]);
493 ToGlobal(r * cos(phi0 + phi2), r * sin(phi0 + phi2), w,
494 xbox[k + 3], ybox[k + 3], zbox[k + 3]);
495 ToGlobal(-m_lX * t1, m_lY, w, xbox[k + 1], ybox[k + 1], zbox[k + 1]);
496 ToGlobal(-m_lX * t2, m_lY, w, xbox[k + 2], ybox[k + 2], zbox[k + 2]);
498 CutBox(xbox, ybox, zbox, xv, yv, zv, x0, y0, z0, xn, yn, zn);
499 if (xv.size() >= 3) {
509 panels.push_back(std::move(panel));
515 for (
int iside : {-1, 1}) {
516 const double r = iside < 0 ? r1 : r2;
517 const double w = iside * m_lZ;
518 const unsigned int k = iside < 0 ? 0 : 4;
519 const double phi0 = 1.5 * HalfPi;
520 ToGlobal(r * cos(phi0 + phi1), r * sin(phi0 + phi1), w,
521 xbox[k], ybox[k], zbox[k]);
522 ToGlobal(r * cos(phi0 + phi2), r * sin(phi0 + phi2), w,
523 xbox[k + 3], ybox[k + 3], zbox[k + 3]);
524 ToGlobal(-m_lX, -m_lY * t1, w, xbox[k + 1], ybox[k + 1], zbox[k + 1]);
525 ToGlobal(-m_lX, -m_lY * t2, w, xbox[k + 2], ybox[k + 2], zbox[k + 2]);
527 CutBox(xbox, ybox, zbox, xv, yv, zv, x0, y0, z0, xn, yn, zn);
528 if (xv.size() >= 3) {
538 panels.push_back(std::move(panel));
544 for (
int iside : {-1, 1}) {
545 const double r = iside < 0 ? r1 : r2;
546 const double w = iside * m_lZ;
547 const unsigned int k = iside < 0 ? 0 : 4;
548 const double phi0 = -1.5 * HalfPi;
549 ToGlobal(r * cos(phi0 + phi1), r * sin(phi0 + phi1), w,
550 xbox[k], ybox[k], zbox[k]);
551 ToGlobal(r * cos(phi0 + phi2), r * sin(phi0 + phi2), w,
552 xbox[k + 3], ybox[k + 3], zbox[k + 3]);
553 ToGlobal(m_lX * t1, -m_lY, w, xbox[k + 1], ybox[k + 1], zbox[k + 1]);
554 ToGlobal(m_lX * t2, -m_lY, w, xbox[k + 2], ybox[k + 2], zbox[k + 2]);
557 CutBox(xbox, ybox, zbox, xv, yv, zv, x0, y0, z0, xn, yn, zn);
558 if (xv.size() >= 3) {
568 panels.push_back(std::move(panel));
Box with a cylindrical hole.
void SetHalfLengthY(const double ly)
Set the half-length of the box along y.
bool GetBoundingBox(double &xmin, double &ymin, double &zmin, double &xmax, double &ymax, double &zmax) const override
Return the bounding box of the solid.
double GetDiscretisationLevel(const Panel &panel) override
Retrieve the discretisation level of a panel.
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
void SetSectors(const unsigned int n)
void SetHalfLengthX(const double lx)
Set the half-length of the box along x.
void SetLowerRadius(const double r)
Set the radius at z = -lz.
bool IsInside(const double x, const double y, const double z, const bool tesselated) const override
bool SolidPanels(std::vector< Panel > &panels) override
Retrieve the surface panels of the solid.
void SetHalfLengthZ(const double lz)
Set the half-length of the box along z.
void SetUpperRadius(const double r)
Set the radius at z = +lz.
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.
Abstract base class for solids.
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.
double m_cTheta
Polar angle.
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)
double m_dX
Direction vector.
unsigned int GetId() const
Get the ID of the solid.
void ToLocal(const double x, const double y, const double z, double &u, double &v, double &w) const
void SetDirection(const double dx, const double dy, const double dz)
void ToGlobal(const double u, const double v, const double w, double &x, double &y, double &z) const
double m_cX
Centre of the solid.
double m_cPhi
Azimuthal angle.
std::string m_className
Class name.
void EliminateButterflies(std::vector< double > &xp, std::vector< double > &yp, std::vector< double > &zp)
void Inside(const std::vector< double > &xpl, const std::vector< double > &ypl, const double x, const double y, bool &inside, bool &edge)
DoubleAc cos(const DoubleAc &f)
std::vector< double > zv
Z-coordinates of vertices.
int volume
Reference to solid to which the panel belongs.
double a
Perpendicular vector.
std::vector< double > xv
X-coordinates of vertices.
std::vector< double > yv
Y-coordinates of vertices.