40#include <boost/filesystem.hpp>
42#include <gsl/gsl_sys.h>
46#define SQR(x) ((x)*(x))
47#define PointID(triangle_id, vertex_id) Triangles_m[triangle_id][vertex_id]
48#define Point(triangle_id, vertex_id) Points_m[Triangles_m[triangle_id][vertex_id]]
62#define FUNC_EQ(x, y) inline bool eq(double x, double y) { \
63 return almost_eq(x, y); \
66#define FUNC_EQ_ZERO(x) inline bool eq_zero(double x) { \
67 return almost_eq_zero(x); \
70#define FUNC_LE(x, y) inline bool le(double x, double y) { \
71 if (almost_eq(x, y)) { \
77#define FUNC_LE_ZERO(x) inline bool le_zero(double x) { \
78 if (almost_eq_zero(x)) { \
84#define FUNC_LT(x, y) inline bool lt(double x, double y) { \
85 if (almost_eq(x, y)) { \
91#define FUNC_LT_ZERO(x) inline bool lt_zero(double x) { \
92 if (almost_eq_zero(x)) { \
98#define FUNC_GE(x, y) inline bool ge(double x, double y) { \
99 if (almost_eq(x, y)) { \
105#define FUNC_GE_ZERO(x) inline bool ge_zero(double x) { \
106 if (almost_eq_zero(x)) { \
112#define FUNC_GT(x, y) inline bool gt(double x, double y) { \
113 if (almost_eq(x, y)) { \
119#define FUNC_GT_ZERO(x) inline bool gt_zero(double x) { \
120 if (almost_eq_zero(x)) { \
132 inline bool almost_eq(
double A,
double B,
double maxDiff = 1
e-15,
double maxRelDiff = DBL_EPSILON) {
135 const double diff =
std::abs(A - B);
141 const double largest = (B > A) ? B : A;
143 if (diff <= largest * maxRelDiff)
150 return (diff <= maxDiff);
170 inline bool almost_eq(
double A,
double B,
double maxDiff = 1
e-20,
int maxUlps = 1000) {
185#pragma GCC diagnostic push
186#pragma GCC diagnostic ignored "-Wstrict-aliasing"
187 auto aInt = *(int64_t*)&A;
188#pragma GCC diagnostic pop
191 aInt = 0x8000000000000000 - aInt;
194#pragma GCC diagnostic push
195#pragma GCC diagnostic ignored "-Wstrict-aliasing"
196 auto bInt = *(int64_t*)&B;
197#pragma GCC diagnostic pop
200 bInt = 0x8000000000000000 - bInt;
203 if (
std::abs (aInt - bInt) <= maxUlps) {
232 inline bool almost_eq (
double A,
double B,
double maxDiff = 1
e-20,
int maxUlps = 1000) {
243#pragma GCC diagnostic push
244#pragma GCC diagnostic ignored "-Wstrict-aliasing"
245 auto aInt = *(int64_t*)&A;
246 auto bInt = *(int64_t*)&B;
247#pragma GCC diagnostic pop
251 if (std::signbit (aInt) != std::signbit (bInt))
255 return (
std::abs (aInt - bInt) <= maxUlps);
308Vector_t get_max_extent (std::vector<Vector_t>& coords) {
310 coords.begin (), coords.end (), VectorLessX ());
312 coords.begin (), coords.end (), VectorLessY ());
314 coords.begin (), coords.end (), VectorLessZ ());
322Vector_t get_min_extent (std::vector<Vector_t>& coords) {
324 coords.begin (), coords.end (), VectorLessX ());
326 coords.begin (), coords.end (), VectorLessY ());
328 coords.begin (), coords.end (), VectorLessZ ());
335static void write_voxel_mesh (
337 const std::unordered_map<
int, std::unordered_set<int> >& ids,
343 const size_t numpoints = 8 * ids.size ();
346 *
gmsg <<
level2 <<
"* Writing VTK file of voxel mesh '" << fname <<
"'" <<
endl;
351 of <<
"# vtk DataFile Version 2.0" <<
std::endl;
352 of <<
"generated using BoundaryGeometry::computeMeshVoxelization"
355 of <<
"DATASET UNSTRUCTURED_GRID" <<
std::endl;
356 of <<
"POINTS " << numpoints <<
" float" <<
std::endl;
358 const auto nr0_times_nr1 =
nr[0] *
nr[1];
359 for (
auto& elem: ids) {
360 auto id = elem.first;
361 int k = (
id - 1) / nr0_times_nr1;
362 int rest = (
id - 1) % nr0_times_nr1;
363 int j = rest /
nr[0];
364 int i = rest %
nr[0];
367 P[0] = i * hr_m[0] + origin[0];
368 P[1] = j * hr_m[1] + origin[1];
369 P[2] = k * hr_m[2] + origin[2];
371 of << P[0] <<
" " << P[1] <<
" " << P[2] <<
std::endl;
372 of << P[0] + hr_m[0] <<
" " << P[1] <<
" " << P[2] <<
std::endl;
373 of << P[0] <<
" " << P[1] + hr_m[1] <<
" " << P[2] <<
std::endl;
374 of << P[0] + hr_m[0] <<
" " << P[1] + hr_m[1] <<
" " << P[2] <<
std::endl;
375 of << P[0] <<
" " << P[1] <<
" " << P[2] + hr_m[2] <<
std::endl;
376 of << P[0] + hr_m[0] <<
" " << P[1] <<
" " << P[2] + hr_m[2] <<
std::endl;
377 of << P[0] <<
" " << P[1] + hr_m[1] <<
" " << P[2] + hr_m[2] <<
std::endl;
378 of << P[0] + hr_m[0] <<
" " << P[1] + hr_m[1] <<
" " << P[2] + hr_m[2] <<
std::endl;
381 const auto num_cells = ids.size ();
382 of <<
"CELLS " << num_cells <<
" " << 9 * num_cells <<
std::endl;
383 for (
size_t i = 0; i < num_cells; i++)
385 << 8 * i <<
" " << 8 * i + 1 <<
" " << 8 * i + 2 <<
" " << 8 * i + 3 <<
" "
386 << 8 * i + 4 <<
" " << 8 * i + 5 <<
" " << 8 * i + 6 <<
" " << 8 * i + 7 <<
std::endl;
387 of <<
"CELL_TYPES " << num_cells <<
std::endl;
388 for (
size_t i = 0; i < num_cells; i++)
390 of <<
"CELL_DATA " << num_cells <<
std::endl;
391 of <<
"SCALARS " <<
"cell_attribute_data" <<
" float " <<
"1" <<
std::endl;
392 of <<
"LOOKUP_TABLE " <<
"default" <<
std::endl;
393 for (
size_t i = 0; i < num_cells; i++)
396 of <<
"COLOR_SCALARS " <<
"BBoxColor " << 4 <<
std::endl;
397 for (
size_t i = 0; i < num_cells; i++) {
398 of <<
"1.0" <<
" 1.0 " <<
"0.0 " <<
"1.0" <<
std::endl;
429 inline double v1(
int i)
const {
435 inline double v2(
int i)
const {
441 inline double v3(
int i)
const {
450 pts[0][0] *= scaleby[0];
451 pts[0][1] *= scaleby[1];
452 pts[0][2] *= scaleby[2];
453 pts[1][0] *= scaleby[0];
454 pts[1][1] *= scaleby[1];
455 pts[1][2] *= scaleby[2];
456 pts[2][0] *= scaleby[0];
457 pts[2][1] *= scaleby[1];
458 pts[2][2] *= scaleby[2];
476 int outcode_fcmp = 0;
478 if (
cmp::gt(p[0], 0.5)) outcode_fcmp |= 0x01;
479 if (
cmp::lt(p[0], -0.5)) outcode_fcmp |= 0x02;
480 if (
cmp::gt(p[1], 0.5)) outcode_fcmp |= 0x04;
481 if (
cmp::lt(p[1], -0.5)) outcode_fcmp |= 0x08;
482 if (
cmp::gt(p[2], 0.5)) outcode_fcmp |= 0x10;
483 if (
cmp::lt(p[2], -0.5)) outcode_fcmp |= 0x20;
485 return(outcode_fcmp);
496 int outcode_fcmp = 0;
498 if (
cmp::gt( p[0] + p[1], 1.0)) outcode_fcmp |= 0x001;
499 if (
cmp::gt( p[0] - p[1], 1.0)) outcode_fcmp |= 0x002;
500 if (
cmp::gt(-p[0] + p[1], 1.0)) outcode_fcmp |= 0x004;
501 if (
cmp::gt(-p[0] - p[1], 1.0)) outcode_fcmp |= 0x008;
502 if (
cmp::gt( p[0] + p[2], 1.0)) outcode_fcmp |= 0x010;
503 if (
cmp::gt( p[0] - p[2], 1.0)) outcode_fcmp |= 0x020;
504 if (
cmp::gt(-p[0] + p[2], 1.0)) outcode_fcmp |= 0x040;
505 if (
cmp::gt(-p[0] - p[2], 1.0)) outcode_fcmp |= 0x080;
506 if (
cmp::gt( p[1] + p[2], 1.0)) outcode_fcmp |= 0x100;
507 if (
cmp::gt( p[1] - p[2], 1.0)) outcode_fcmp |= 0x200;
508 if (
cmp::gt(-p[1] + p[2], 1.0)) outcode_fcmp |= 0x400;
509 if (
cmp::gt(-p[1] - p[2], 1.0)) outcode_fcmp |= 0x800;
511 return(outcode_fcmp);
522 int outcode_fcmp = 0;
524 if (
cmp::gt( p[0] + p[1] + p[2], 1.5)) outcode_fcmp |= 0x01;
525 if (
cmp::gt( p[0] + p[1] - p[2], 1.5)) outcode_fcmp |= 0x02;
526 if (
cmp::gt( p[0] - p[1] + p[2], 1.5)) outcode_fcmp |= 0x04;
527 if (
cmp::gt( p[0] - p[1] - p[2], 1.5)) outcode_fcmp |= 0x08;
528 if (
cmp::gt(-p[0] + p[1] + p[2], 1.5)) outcode_fcmp |= 0x10;
529 if (
cmp::gt(-p[0] + p[1] - p[2], 1.5)) outcode_fcmp |= 0x20;
530 if (
cmp::gt(-p[0] - p[1] + p[2], 1.5)) outcode_fcmp |= 0x40;
531 if (
cmp::gt(-p[0] - p[1] - p[2], 1.5)) outcode_fcmp |= 0x80;
533 return(outcode_fcmp);
552#define LERP(a, b, t) (a + t * (b - a))
554 plane_point[0] =
LERP(p1[0], p2[0],
alpha);
555 plane_point[1] =
LERP(p1[1], p2[1],
alpha);
556 plane_point[2] =
LERP(p1[2], p2[2],
alpha);
558 return(face_plane(plane_point) & mask);
572 const int outcode_diff
574 if ((0x01 & outcode_diff) != 0)
575 if (check_point(p1,p2,( .5-p1[0])/(p2[0]-p1[0]),0x3e) ==
INSIDE)
return(
INSIDE);
576 if ((0x02 & outcode_diff) != 0)
577 if (check_point(p1,p2,(-.5-p1[0])/(p2[0]-p1[0]),0x3d) ==
INSIDE)
return(
INSIDE);
578 if ((0x04 & outcode_diff) != 0)
579 if (check_point(p1,p2,( .5-p1[1])/(p2[1]-p1[1]),0x3b) ==
INSIDE)
return(
INSIDE);
580 if ((0x08 & outcode_diff) != 0)
581 if (check_point(p1,p2,(-.5-p1[1])/(p2[1]-p1[1]),0x37) ==
INSIDE)
return(
INSIDE);
582 if ((0x10 & outcode_diff) != 0)
583 if (check_point(p1,p2,( .5-p1[2])/(p2[2]-p1[2]),0x2f) ==
INSIDE)
return(
INSIDE);
584 if ((0x20 & outcode_diff) != 0)
585 if (check_point(p1,p2,(-.5-p1[2])/(p2[2]-p1[2]),0x1f) ==
INSIDE)
return(
INSIDE);
598 return (((A[0] <
EPS) ? 4 : 0) | ((A[0] > -
EPS) ? 32 : 0) |
599 ((A[1] <
EPS) ? 2 : 0) | ((A[1] > -
EPS) ? 16 : 0) |
600 ((A[2] <
EPS) ? 1 : 0) | ((A[2] > -
EPS) ? 8 : 0));
604point_triangle_intersection (
629 const int sign12 = SIGN3(cross12_1p);
634 const int sign23 = SIGN3(cross23_2p);
639 const int sign31 = SIGN3(cross31_3p);
659triangle_intersects_cube (
678 if ((v1_test & v2_test & v3_test) != 0)
return(
OUTSIDE);
683 v1_test |= bevel_2d(t.
v1()) << 8;
684 v2_test |= bevel_2d(t.
v2()) << 8;
685 v3_test |= bevel_2d(t.
v3()) << 8;
686 if ((v1_test & v2_test & v3_test) != 0)
return(
OUTSIDE);
691 v1_test |= bevel_3d(t.
v1()) << 24;
692 v2_test |= bevel_3d(t.
v2()) << 24;
693 v3_test |= bevel_3d(t.
v3()) << 24;
694 if ((v1_test & v2_test & v3_test) != 0)
return(
OUTSIDE);
704 if ((v1_test & v2_test) == 0)
706 if ((v1_test & v3_test) == 0)
708 if ((v2_test & v3_test) == 0)
738 double d = norm[0] * t.
v1(0) + norm[1] * t.
v1(1) + norm[2] * t.
v1(2);
744 double denom = norm[0] + norm[1] + norm[2];
749 if (point_triangle_intersection(hitpp,t) ==
INSIDE)
752 denom = norm[0] + norm[1] - norm[2];
755 hitpn[2] = -(hitpn[0] = hitpn[1] = d / denom);
757 if (point_triangle_intersection(hitpn,t) ==
INSIDE)
760 denom = norm[0] - norm[1] + norm[2];
763 hitnp[1] = -(hitnp[0] = hitnp[2] = d / denom);
765 if (point_triangle_intersection(hitnp,t) ==
INSIDE)
768 denom = norm[0] - norm[1] - norm[2];
771 hitnn[1] = hitnn[2] = -(hitnn[0] = d / denom);
773 if (point_triangle_intersection(hitnn,t) ==
INSIDE)
892 t_.
scale (scaleby , v_.
pts[0] + 0.5);
893 return triangle_intersects_cube (t_);
915static inline Vector_t normalVector (
923 return N / magnitude;
927static inline double computeArea (
949 SIZE,
"GEOMETRY",
"The \"GEOMETRY\" statement defines the beam pipe geometry.") {
953 "Specifies the geometry file [H5hut]",
958 "If FGEOM is selected topo is over-written. ",
959 {
"RECTANGULAR",
"BOXCORNER",
"ELLIPTIC"},
964 "Specifies the length of a tube shaped elliptic beam pipe [m]",
969 "Specifies the start of a tube shaped elliptic beam pipe [m]",
974 "Specifies the major semi-axis of a tube shaped elliptic beam pipe [m]",
979 "Specifies the major semi-axis of a tube shaped elliptic beam pipe [m]",
984 "In case of BOXCORNER Specifies first part with height == B [m]",
989 "In case of BOXCORNER Specifies first second with height == B-C [m]",
994 "In case of BOXCORNER Specifies height of corner C [m]",
999 "Multiplicative scaling factor for coordinates ",
1004 "Multiplicative scaling factor for X coordinates ",
1009 "Multiplicative scaling factor for Y coordinates ",
1014 "Multiplicative scaling factor for Z coordinates ",
1019 "Shift in z direction",
1023 (
"INSIDEPOINT",
"A point inside the geometry");
1044 gsl_rng_env_setup();
1045 randGen_m = gsl_rng_alloc(gsl_rng_default);
1052 const std::string&
name,
1055 gsl_rng_env_setup();
1056 randGen_m = gsl_rng_alloc(gsl_rng_default);
1101 throw OpalException (
"BoundaryGeometry::find()",
"Geometry \""
1102 +
name +
"\" not found.");
1111 const int triangle_id,
1177 const int triangle_id,
1193 const double a = -
dot(
n,w0);
1194 const double b =
dot(
n,dir);
1204 const double r =
a / b;
1222 const double uu =
dot(u,u);
1223 const double uv =
dot(u,v);
1224 const double vv =
dot(v,v);
1226 const double wu =
dot(w,u);
1227 const double wv =
dot(w,v);
1228 const double D = uv * uv - uu * vv;
1231 const double s = (uv * wv - vv * wu) / D;
1235 const double t = (uv * wu - uu * wv) / D;
1249static inline double magnitude (
1265 double distance = P[0] - x;
1270 if (
cmp::lt(x - P[0], distance)) {
1271 distance = x - P[0];
1272 ref_pt = {x, P[1], P[2]};
1277 if (
cmp::lt(P[1] - y, distance)) {
1279 ref_pt = {P[0], y, P[1]};
1284 if (
cmp::lt(y - P[1], distance)) {
1285 distance = y - P[1];
1286 ref_pt = {P[0], y, P[2]};
1290 if (
cmp::lt(P[2] - z, distance)) {
1291 distance = P[2] - z;
1292 ref_pt = {P[0], P[1], z};
1296 if (
cmp::lt(z - P[2], distance)) {
1297 ref_pt = {P[0], P[1], z};
1306 return (k % 2) == 1;
1365 *
gmsg <<
level2 <<
"* Searching for a point inside the geometry..." <<
endl;
1370 std::vector<Vector_t> P_outs {
1380 for (
const auto& P: P_outs) {
1405 }
else if (
n == n_i) {
1431 if (!
c.isInside (P))
return 1;
1436 *
gmsg <<
"* " << __func__ <<
": "
1437 <<
"reference_pt=" << reference_pt
1438 <<
", P=" << P <<
endl;
1442 const Vector_t v = reference_pt - P;
1450 int triangle_id = -1;
1452 for (
int i = 0; i < N; i++) {
1459 *
gmsg <<
"* " << __func__ <<
": "
1460 <<
"result: " << result <<
endl;
1486 *
gmsg <<
"* " << __func__ <<
": "
1503 c.intersect (r, tmin, tmax);
1504 int triangle_id = -1;
1507 I, triangle_id) > 0) ? 1 : 0;
1510 *
gmsg <<
"* " << __func__ <<
": "
1511 <<
" result=" << result
1542#define mapPoint2VoxelIndices(pt, i, j, k) { \
1543 i = floor ((pt[0] - voxelMesh_m.minExtent [0]) / voxelMesh_m.sizeOfVoxel[0]); \
1544 j = floor ((pt[1] - voxelMesh_m.minExtent [1]) / voxelMesh_m.sizeOfVoxel[1]); \
1545 k = floor ((pt[2] - voxelMesh_m.minExtent [2]) / voxelMesh_m.sizeOfVoxel[2]); \
1546 if (!(0 <= i && i < voxelMesh_m.nr_m[0] && \
1547 0 <= j && j < voxelMesh_m.nr_m[1] && \
1548 0 <= k && k < voxelMesh_m.nr_m[2])) { \
1550 << "* " << __func__ << ":" \
1551 << " WARNING: pt=" << pt \
1552 << " is outside the bbox" \
1587 for (
unsigned int triangle_id = 0; triangle_id <
Triangles_m.size(); triangle_id++) {
1599 int i_min, j_min, k_min;
1600 int i_max, j_max, k_max;
1604 for (
int i = i_min; i <= i_max; i++) {
1605 for (
int j = j_min; j <= j_max; j++) {
1606 for (
int k = k_min; k <= k_max; k++) {
1624 bool writeVTK =
false;
1626 if (!boost::filesystem::exists(vtkFileName)) {
1629 std::time_t t_geom = boost::filesystem::last_write_time(
h5FileName_m);
1630 std::time_t t_vtk = boost::filesystem::last_write_time(vtkFileName);
1631 if (std::difftime(t_geom,t_vtk) > 0)
1636 write_voxel_mesh (vtkFileName,
1660 double longest_edge_max_m = 0.0;
1661 for (
unsigned int i = 0; i < bg->
Triangles_m.size(); i++) {
1667 SQR (x1[0] - x2[0]) +
SQR (x1[1] - x2[1]) +
SQR (x1[2] - x2[2]));
1669 SQR (x3[0] - x2[0]) +
SQR (x3[1] - x2[1]) +
SQR (x3[2] - x2[2]));
1671 SQR (x3[0] - x1[0]) +
SQR (x3[1] - x1[1]) +
SQR (x3[2] - x1[2]));
1673 double max = length_edge1;
1674 if (length_edge2 >
max)
max = length_edge2;
1675 if (length_edge3 >
max)
max = length_edge3;
1678 if (longest_edge_max_m <
max) longest_edge_max_m =
max;
1835 static void computeTriangleNeighbors (
1837 std::vector<std::set<unsigned int>>& neighbors
1839 std::vector<std::set<unsigned int>> adjacencies_to_pt (bg->
Points_m.size());
1842 for (
unsigned int triangle_id = 0; triangle_id < bg->
Triangles_m.size(); triangle_id++) {
1843 for (
unsigned int j = 1; j <= 3; j++) {
1844 auto pt_id = bg->PointID (triangle_id, j);
1846 adjacencies_to_pt [pt_id].insert (triangle_id);
1850 for (
unsigned int triangle_id = 0; triangle_id < bg->
Triangles_m.size(); triangle_id++) {
1851 std::set<unsigned int> to_A = adjacencies_to_pt [bg->PointID (triangle_id, 1)];
1852 std::set<unsigned int> to_B = adjacencies_to_pt [bg->PointID (triangle_id, 2)];
1853 std::set<unsigned int> to_C = adjacencies_to_pt [bg->PointID (triangle_id, 3)];
1855 std::set<unsigned int> intersect;
1856 std::set_intersection (
1857 to_A.begin(), to_A.end(),
1858 to_B.begin(), to_B.end(),
1859 std::inserter(intersect,intersect.begin()));
1860 std::set_intersection(
1861 to_B.begin(), to_B.end(),
1862 to_C.begin(), to_C.end(),
1863 std::inserter(intersect,intersect.begin()));
1864 std::set_intersection(
1865 to_C.begin(), to_C.end(),
1866 to_A.begin(), to_A.end(),
1867 std::inserter(intersect, intersect.begin()));
1868 intersect.erase (triangle_id);
1870 neighbors [triangle_id] = intersect;
1872 *
gmsg <<
level2 <<
"* " << __func__ <<
": Computing neighbors done" <<
endl;
1902 std::vector<Vector_t> intersection_points;
1905 for (
unsigned int triangle_id = 0; triangle_id < bg->
Triangles_m.size(); triangle_id++) {
1908 intersection_points.push_back (result);
1913 return ((intersection_points.size () % 2) == 1);
1917 static bool hasInwardPointingNormal (
1919 const int triangle_id
1924 const Vector_t triNormal = normalVector (
A,
B,
C);
1933 const Vector_t P = (
A+
B+
C)/3 + triNormal * minvoxelmesh;
1943 const bool is_inside =
isInside (bg, P);
1944 const double dotPA_N =
dot (P -
A, triNormal);
1945 return (is_inside && dotPA_N >= 0) || (!is_inside && dotPA_N < 0);
1949 static void orientTriangle (
BoundaryGeometry* bg,
int ref_id,
int triangle_id) {
1954 for (
int i = 1; i <= 3; i++) {
1955 for (
int j = 1; j <= 3; j++) {
1956 if (bg->PointID (triangle_id, j) == bg->PointID (ref_id, i)) {
1960 if (
n == 2)
goto edge_found;
1966 int diff =
id[1] -
id[0];
1967 if ((((ic[1] - ic[0]) == 1) && ((diff == 1) || (diff == -2))) ||
1968 (((ic[1] - ic[0]) == 2) && ((diff == -1) || (diff == 2)))) {
1969 std::swap (bg->PointID (triangle_id,
id[0]), bg->PointID (triangle_id,
id[1]));
1974 std::vector<std::set<unsigned int>> neighbors (bg->
Triangles_m.size());
1976 computeTriangleNeighbors (bg, neighbors);
1979 int triangle_id = 0;
1981 std::vector<unsigned int> triangles (bg->
Triangles_m.size());
1982 std::vector<unsigned int>::size_type queue_cursor = 0;
1983 std::vector<unsigned int>::size_type queue_end = 0;
1984 std::vector <bool> isOriented (bg->
Triangles_m.size(),
false);
1991 while (isOriented[triangle_id])
1995 if (!hasInwardPointingNormal (bg, triangle_id)) {
1996 std::swap (bg->PointID (triangle_id, 2), bg->PointID (triangle_id, 3));
1998 isOriented[triangle_id] =
true;
2001 triangles[queue_end++] = triangle_id;
2003 for (
auto neighbor_id: neighbors[triangle_id]) {
2004 if (isOriented[neighbor_id])
continue;
2005 orientTriangle (bg, triangle_id, neighbor_id);
2006 isOriented[neighbor_id] =
true;
2007 triangles[queue_end++] = neighbor_id;
2010 }
while (queue_cursor < queue_end && (triangle_id = triangles[queue_cursor],
true));
2014 *
gmsg <<
level2 <<
"* " << __func__ <<
": mesh is contiguous" <<
endl;
2016 *
gmsg <<
level2 <<
"* " << __func__ <<
": mesh is discontiguous (" << parts <<
") parts" <<
endl;
2024 *
gmsg <<
level2 <<
"* Initializing Boundary Geometry..." <<
endl;
2030 "', please check if it exists");
2043 rc = H5SetErrorHandler (H5AbortErrorhandler);
2045 H5SetVerbosityLevel (1);
2047 h5_prop_t props = H5CreateFileProp ();
2049 H5SetPropFileMPIOCollective (props, &comm);
2050 h5_file_t f = H5OpenFile (
h5FileName_m.c_str(), H5_O_RDONLY, props);
2051 H5CloseProp (props);
2053 h5t_mesh_t* m =
nullptr;
2054 H5FedOpenTriangleMesh (f,
"0", &m);
2055 H5FedSetLevel (m, 0);
2057 auto numTriangles = H5FedGetNumElementsTotal (m);
2061 h5_loc_id_t local_id;
2063 h5t_iterator_t* iter = H5FedBeginTraverseEntities (m, 0);
2064 while ((local_id = H5FedTraverseEntities (iter)) >= 0) {
2065 h5_loc_id_t local_vids[4];
2066 H5FedGetVertexIndicesOfEntity (m, local_id, local_vids);
2068 PointID (i, 1) = local_vids[0];
2069 PointID (i, 2) = local_vids[1];
2070 PointID (i, 3) = local_vids[2];
2073 H5FedEndTraverseEntities (iter);
2076 int num_points = H5FedGetNumVerticesTotal (m);
2078 for (i = 0; i < num_points; i++) {
2080 H5FedGetVertexCoordsByIndex (m, i, P);
2082 P[0] * xyzscale * xscale,
2083 P[1] * xyzscale * yscale,
2084 P[2] * xyzscale * zscale + zshift));
2090 Local::computeGeometryInterval (
this);
2095 if (pt.size () != 3) {
2097 "BoundaryGeometry::initialize()",
2098 "Dimension of INSIDEPOINT must be 3");
2103 if (is_inside ==
false) {
2105 "BoundaryGeometry::initialize()",
2106 "INSIDEPOINT is not inside the geometry");
2113 *
gmsg <<
level2 <<
"* using as point inside the geometry: ("
2118 *
gmsg <<
level2 <<
"* no point inside the geometry found!" <<
endl;
2121 Local::makeTriangleNormalInwardPointing (
this);
2164 *
gmsg <<
"* " << __func__ <<
": "
2171 const Ray r =
Ray (P, v_);
2202 std::unordered_set<int> triangle_ids;
2203 for (
int i = i_min; i <= i_max; i++) {
2204 for (
int j = j_min; j <= j_max; j++) {
2205 for (
int k = k_min; k <= k_max; k++) {
2210 *
gmsg <<
"* " << __func__ <<
": "
2211 <<
" Test voxel: (" << i <<
", " << j <<
", " << k <<
"), "
2228 const auto triangles_intersecting_voxel =
2230 if (triangles_intersecting_voxel !=
voxelMesh_m.ids.end()) {
2231 triangle_ids.insert (
2232 triangles_intersecting_voxel->second.begin(),
2233 triangles_intersecting_voxel->second.end());
2242 int num_intersections = 0;
2243 int tmp_intersect_result = 0;
2245 for (
auto it = triangle_ids.begin ();
2246 it != triangle_ids.end ();
2256 *
gmsg <<
"* " << __func__ <<
": "
2257 <<
" Test triangle: " << *it
2258 <<
" intersect: " << tmp_intersect_result
2265 switch (tmp_intersect_result) {
2274 t = (tmp_intersect_pt[0] - P[0]) / (Q[0] - P[0]);
2276 t = (tmp_intersect_pt[1] - P[1]) / (Q[1] - P[1]);
2278 t = (tmp_intersect_pt[2] - P[2]) / (Q[2] - P[2]);
2280 num_intersections++;
2284 *
gmsg <<
"* " << __func__ <<
": "
2290 intersect_pt = tmp_intersect_pt;
2291 triangle_id = (*it);
2295 PAssert (tmp_intersect_result != -1);
2299 return num_intersections;
2317 *
gmsg <<
"* " << __func__ <<
": "
2327 int intersect_result = 0;
2329 int i_min, j_min, k_min;
2330 int i_max, j_max, k_max;
2344 }
while (( (i_max-i_min+1) * (j_max-j_min+1) * (k_max-k_min+1)) > 27);
2349 for (
int l = 1; l <=
n; l++, P = Q) {
2352 P, Q, intersect_pt, triangle_id);
2353 if (triangle_id != -1) {
2359 *
gmsg <<
"* " << __func__ <<
": "
2360 <<
" result=" << intersect_result
2361 <<
" intersection pt: " << intersect_pt
2366 return intersect_result;
2388 *
gmsg <<
"* " << __func__ <<
": "
2409 int tmp_triangle_id = -1;
2411 if (tmp_triangle_id >= 0) {
2412 intersect_pt = tmp_intersect_pt;
2413 triangle_id = tmp_triangle_id;
2418 *
gmsg <<
"* " << __func__ <<
":"
2419 <<
" result=" << ret;
2421 *
gmsg <<
" intersetion=" << intersect_pt;
2434 of.open (fn.c_str ());
2437 of <<
"# vtk DataFile Version 2.0" <<
std::endl;
2438 of <<
"generated using DataSink::writeGeoToVtk" <<
std::endl;
2440 of <<
"DATASET UNSTRUCTURED_GRID" <<
std::endl;
2442 for (
unsigned int i = 0; i <
Points_m.size (); i++)
2460 of <<
"SCALARS " <<
"cell_attribute_data" <<
" float " <<
"1" <<
std::endl;
2461 of <<
"LOOKUP_TABLE " <<
"default" <<
std::endl;
2470 os <<
"* ************* B O U N D A R Y G E O M E T R Y *********************************** " <<
endl;
2487 os <<
"* Total triangle num " <<
Triangles_m.size() <<
'\n'
2488 <<
"* Total points num " <<
Points_m.size () <<
'\n'
2489 <<
"* Geometry bounds(m) Max = " <<
maxExtent_m <<
'\n'
2492 <<
"* Resolution of voxel mesh " <<
voxelMesh_m.nr_m <<
'\n'
2493 <<
"* Size of voxel " <<
voxelMesh_m.sizeOfVoxel <<
'\n'
2495 os <<
"* ********************************************************************************** " <<
endl;
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Tps< T > sqrt(const Tps< T > &x)
Square root.
#define PointID(triangle_id, vertex_id)
#define mapPoint2VoxelIndices(pt, i, j, k)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Inform & level2(Inform &inf)
Inform & endl(Inform &inf)
double getReal(const Attribute &attr)
Return real value.
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
Attribute makeRealArray(const std::string &name, const std::string &help)
Create real array attribute.
std::vector< double > getRealArray(const Attribute &attr)
Get array value.
std::string getString(const Attribute &attr)
Get string value.
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
constexpr double alpha
The fine structure constant, no dimension.
constexpr double e
The value of.
constexpr double c
The velocity of light in m/s.
T isnan(T x)
isnan function with adjusted return type
bool enableVTK
If true VTK files are written.
std::string combineFilePath(std::initializer_list< std::string > ilist)
bool almost_eq(double A, double B, double maxDiff=1e-15, double maxRelDiff=DBL_EPSILON)
bool almost_eq_zero(double A, double maxDiff=1e-15)
bool almost_eq(double A, double B, double maxDiff=1e-20, int maxUlps=1000)
bool almost_eq_zero(double A, double maxDiff=1e-15)
bool almost_eq(double A, double B, double maxDiff=1e-20, int maxUlps=1000)
bool ge(double x, double y)
bool gt(double x, double y)
bool almost_eq_zero(double A, double maxDiff=1e-15)
bool lt(double x, double y)
bool le(double x, double y)
The base class for all OPAL definitions.
The base class for all OPAL objects.
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
const std::string & getOpalName() const
Return object name.
void setOpalName(const std::string &name)
Set object name.
std::vector< Attribute > itsAttr
The object attributes.
bool builtin
Built-in flag.
Object * find(const std::string &name)
Find entry.
static OpalData * getInstance()
void define(Object *newObject)
Define a new object.
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Abstract base class for accelerator geometry classes.
Triangle(const Vector_t &v1, const Vector_t &v2, const Vector_t &v3)
const Vector_t & v3() const
const Vector_t & v2() const
const Vector_t & v1() const
void scale(const Vector_t &scaleby, const Vector_t &shiftby)
const Ray & operator=(const Ray &a)=delete
Ray(Vector_t o, Vector_t d)
bool isInside(const Vector_t &P) const
bool intersect(const Ray &r, double &tmin, double &tmax) const
Voxel(const Vector_t &min, const Vector_t &max)
int intersect(const Triangle &t) const
bool intersect(const Ray &r) const
void scale(const Vector_t &scale)
std::vector< std::array< unsigned int, 4 > > Triangles_m
IpplTimings::TimerRef TisInside_m
std::vector< Vector_t > TriNormals_m
int fastIsInside(const Vector_t &reference_pt, const Vector_t &P)
int intersectRayBoundary(const Vector_t &P, const Vector_t &v, Vector_t &I)
std::vector< double > TriAreas_m
struct BoundaryGeometry::@70 voxelMesh_m
virtual void execute()
Execute the command.
const Vector_t & getPoint(const int triangle_id, const int vertex_id)
virtual void update()
Update this object.
IpplTimings::TimerRef TRayTrace_m
virtual bool canReplaceBy(Object *object)
Test if replacement is allowed.
bool isInside(const Vector_t &P)
std::vector< Vector_t > Points_m
static BoundaryGeometry * find(const std::string &name)
int intersectLineSegmentBoundary(const Vector_t &P0, const Vector_t &P1, Vector_t &intersection_pt, int &triangle_id)
IpplTimings::TimerRef Tinitialize_m
int mapVoxelIndices2ID(const int i, const int j, const int k)
IpplTimings::TimerRef TPartInside_m
Vector_t mapPoint2Voxel(const Vector_t &)
IpplTimings::TimerRef TfastIsInside_m
int intersectTriangleVoxel(const int triangle_id, const int i, const int j, const int k)
void writeGeomToVtk(std::string fn)
@ debug_intersectRayBoundary
@ debug_intersectTinyLineSegmentBoundary
@ debug_intersectLineSegmentBoundary
bool findInsidePoint(void)
int partInside(const Vector_t &r, const Vector_t &v, const double dt, Vector_t &intecoords, int &triId)
int intersectTinyLineSegmentBoundary(const Vector_t &, const Vector_t &, Vector_t &, int &)
virtual BoundaryGeometry * clone(const std::string &name)
Return a clone.
Topology getTopology() const
virtual ~BoundaryGeometry()
Inform & printInfo(Inform &os) const
Vector_t mapIndices2Voxel(const int, const int, const int)
int intersectLineTriangle(const enum INTERSECTION_TESTS kind, const Vector_t &P0, const Vector_t &P1, const int triangle_id, Vector_t &I)
void computeMeshVoxelization(void)
void updateElement(ElementBase *element)
The base class for all OPAL exceptions.
static MPI_Comm getComm()
static Communicate * Comm
static TimerRef getTimer(const char *nm)
static void stopTimer(TimerRef t)
static void startTimer(TimerRef t)
Vektor< double, 3 > Vector_t