29 #ifndef MAX_NUM_THREADS_
30 #define MAX_NUM_THREADS_ 8
49 inline double x()
const {
return _x[0]; }
50 inline double y()
const {
return _x[1]; }
51 inline double z()
const {
return _x[2]; }
52 inline double lc()
const {
return _lc; }
53 inline double &
x() {
return _x[0]; }
54 inline double &
y() {
return _x[1]; }
55 inline double &
z() {
return _x[2]; }
56 inline double &
lc() {
return _lc; }
57 inline operator double *() {
return _x; }
58 Vert(
double X = 0,
double Y = 0,
double Z = 0,
double lc = 0,
int num = 0)
68 return Vert(
x() + other.
x(),
y() + other.
y(),
z() + other.
z(),
73 return Vert(
x() * other,
y() * other,
z() * other,
_lc * other);
81 const double adx = pa[0] - pd[0];
82 const double bdx = pb[0] - pd[0];
83 const double cdx = pc[0] - pd[0];
84 const double ady = pa[1] - pd[1];
85 const double bdy = pb[1] - pd[1];
86 const double cdy = pc[1] - pd[1];
87 const double adz = pa[2] - pd[2];
88 const double bdz = pb[2] - pd[2];
89 const double cdz = pc[2] - pd[2];
91 return adx * (bdy * cdz - bdz * cdy) + bdx * (cdy * adz - cdz * ady) +
92 cdx * (ady * bdz - adz * bdy);
98 (
double *)va, (
double *)vb, (
double *)vc, (
double *)vd, (
double *)ve);
100 Msg::Info(
"Symbolic perturbation needed vol %22.15E",
105 Vert *pt[5] = {va, vb, vc, vd, ve};
111 for(
int i = 0; i < n; i++) {
112 if(pt[i] > pt[i + 1]) {
113 Vert *swappt = pt[i];
122 (
double *)pt[3], (
double *)pt[4]);
125 if((swaps % 2) != 0) oriA = -oriA;
130 (
double *)pt[0], (
double *)pt[2], (
double *)pt[3], (
double *)pt[4]);
132 Msg::Error(
"Symbolic perturbation failed in icCircle Predicate");
135 if((swaps % 2) != 0) oriB = -oriB;
150 #define cswap(a, b) \
165 return v[0] == other.
v[0] &&
v[1] == other.
v[1] &&
v[2] == other.
v[2];
170 if(
v[0] < other.
v[0])
return true;
171 if(
v[0] > other.
v[0])
return false;
172 if(
v[1] < other.
v[1])
return true;
173 if(
v[1] > other.
v[1])
return false;
174 if(
v[2] < other.
v[2])
return true;
187 V[0] =
V[1] =
V[2] =
V[3] =
nullptr;
188 T[0] =
T[1] =
T[2] =
T[3] =
nullptr;
198 for(
int i = 0; i < 4; i++)
199 if(
V[i])
V[i]->
setT(
this);
206 (
double *)v2, (
double *)v3);
211 for(
int i = 0; i < 4; i++)
212 if(
V[i])
V[i]->
setT(
this);
213 if(val > 0) {
return 1; }
228 T[0] =
T[1] =
T[2] =
T[3] =
nullptr;
236 void set(
int thread,
int iPnt) {
_bitset[thread] |= (1 << iPnt); }
239 return _bitset[thread] & (1 << iPnt);
243 const int fac[4][3] = {{0, 1, 2}, {1, 3, 2}, {2, 3, 0}, {1, 0, 3}};
244 return Face(
V[fac[k][0]],
V[fac[k][1]],
V[fac[k][2]]);
248 const int o[4] = {3, 0, 1, 2};
261 conn() :
f(nullptr, nullptr, nullptr),
i(0),
t(nullptr) {}
278 const std::size_t _array = i /
_nbAlloc;
279 const std::size_t _offset = i %
_nbAlloc;
280 return _all[_array] + _offset;
289 for(std::size_t i = 0; i <
_all.size(); i++) {
delete[]
_all[i]; }
307 std::size_t
size(
int thread)
const
309 if((
int)
_perThread.size() <= thread)
return 0;
316 for(std::size_t i = 0; i <
_perThread.size(); i++) {
339 int Split(
Vert **vertices,
int arraysize,
int GrayCode0,
int GrayCode1,
340 double BoundingBoxXmin,
double BoundingBoxXmax,
341 double BoundingBoxYmin,
double BoundingBoxYmax,
342 double BoundingBoxZmin,
double BoundingBoxZmax);
343 void Sort(
Vert **vertices,
int arraysize,
int e,
int d,
344 double BoundingBoxXmin,
double BoundingBoxXmax,
345 double BoundingBoxYmin,
double BoundingBoxYmax,
346 double BoundingBoxZmin,
double BoundingBoxZmax,
int depth);
352 double ratio,
int *depth,
353 std::vector<int> &indices)
356 if(arraysize >= threshold) {
358 middle = (int)(arraysize * ratio);
361 indices.push_back(middle);
362 Sort(&(vertices[middle]), arraysize - middle, 0, 0,
bbox.
min().
x(),
366 void Apply(std::vector<Vert *> &v, std::vector<int> &indices)
369 if(v.empty())
return;
370 for(
size_t i = 0; i < v.size(); i++) {
379 indices.push_back(v.size());
385 int gc[8], N, mask, travel_bit;
390 N = (n == 2) ? 4 : 8;
391 mask = (n == 2) ? 3 : 7;
394 for(i = 0; i < N; i++) { gc[i] = i ^ (i >> 1); }
396 for(e = 0; e < N; e++) {
397 for(d = 0; d < n; d++) {
402 for(i = 0; i < N; i++) {
404 k = gc[i] * (travel_bit * 2);
405 g = ((k | (k / N)) & mask);
416 for(i = 1; i < N; i++) {
418 v = (v ^ (v - 1)) >> 1;
419 for(
c = 0; v;
c++) { v >>= 1; }
425 int GrayCode1,
double BoundingBoxXmin,
426 double BoundingBoxXmax,
double BoundingBoxYmin,
427 double BoundingBoxYmax,
double BoundingBoxZmin,
428 double BoundingBoxZmax)
436 axis = (GrayCode0 ^ GrayCode1) >> 1;
439 if(axis == 0) { split = 0.5 * (BoundingBoxXmin + BoundingBoxXmax); }
441 split = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
444 split = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
449 d = ((GrayCode0 & (1 << axis)) == 0) ? 1 : -1;
454 int j = arraysize - 1;
459 for(; i < arraysize; i++) {
460 if(vertices[i]->point()[axis] >= split)
break;
463 if(vertices[j]->point()[axis] < split)
break;
466 if(i >= (j + 1))
break;
468 swapvert = vertices[i];
469 vertices[i] = vertices[j];
470 vertices[j] = swapvert;
476 for(; i < arraysize; i++) {
477 if(vertices[i]->point()[axis] <= split)
break;
480 if(vertices[j]->point()[axis] > split)
break;
483 if(i >= (j + 1))
break;
485 swapvert = vertices[i];
486 vertices[i] = vertices[j];
487 vertices[j] = swapvert;
497 double BoundingBoxXmin,
double BoundingBoxXmax,
498 double BoundingBoxYmin,
double BoundingBoxYmax,
499 double BoundingBoxZmin,
double BoundingBoxZmax,
502 double x1, x2, y1, y2, z1, z2;
503 int p[9], w, e_w, d_w, k, ei, di;
510 BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
511 BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
513 BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
514 BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
516 BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin,
517 BoundingBoxYmax, BoundingBoxZmin, BoundingBoxZmax);
520 BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
521 BoundingBoxZmin, BoundingBoxZmax) +
525 BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
526 BoundingBoxZmin, BoundingBoxZmax) +
530 BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
531 BoundingBoxZmin, BoundingBoxZmax) +
535 BoundingBoxXmin, BoundingBoxXmax, BoundingBoxYmin, BoundingBoxYmax,
536 BoundingBoxZmin, BoundingBoxZmax) +
547 for(w = 0; w < 8; w++) {
548 if((p[w + 1] - p[w]) >
Limit) {
549 if(w == 0) { e_w = 0; }
551 k = 2 * ((w - 1) / 2);
555 e_w = ((k << (d + 1)) & mask) | ((k >> (n - d - 1)) & mask);
557 if(w == 0) { d_w = 0; }
561 di = (d + d_w + 1) % n;
563 x1 = 0.5 * (BoundingBoxXmin + BoundingBoxXmax);
564 x2 = BoundingBoxXmax;
567 x1 = BoundingBoxXmin;
568 x2 = 0.5 * (BoundingBoxXmin + BoundingBoxXmax);
571 y1 = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
572 y2 = BoundingBoxYmax;
575 y1 = BoundingBoxYmin;
576 y2 = 0.5 * (BoundingBoxYmin + BoundingBoxYmax);
579 z1 = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
580 z2 = BoundingBoxZmax;
583 z1 = BoundingBoxZmin;
584 z2 = 0.5 * (BoundingBoxZmin + BoundingBoxZmax);
586 Sort(&(vertices[p[w]]), p[w + 1] - p[w], ei, di, x1, x2, y1, y2, z1, z2,
592 static void SortHilbert(std::vector<Vert *> &v, std::vector<int> &indices)
601 auto it = std::find(faceToTet.begin(), faceToTet.end(),
c);
602 if(it == faceToTet.end()) { faceToTet.push_back(
c); }
626 std::vector<std::size_t> &_negatives)
629 for(std::size_t i = 0; i < bndK.size(); i++) {
632 (
double *)bndK[i].
f.V[0], (
double *)bndK[i].f.V[1],
633 (
double *)bndK[i].f.V[2], (
double *)v);
634 if(val <= 0.0) { _negatives.push_back(i); }
640 for(std::size_t i = 0; i < cavity.size(); i++) {
641 std::size_t count = 0;
642 for(std::size_t j = 0; j < 4; j++) {
643 Face f = cavity[i]->getFace(j);
645 (
double *)
f.V[0], (
double *)
f.V[1], (
double *)
f.V[2], (
double *)v);
646 if(val >= 0) { count++; }
648 if(count == 4)
return cavity[i];
656 for(std::size_t i = 0; i < cavity.size(); i++) {
658 for(std::size_t iFace = 0; iFace < 4; iFace++) {
659 Tet *neigh = t->
T[iFace];
661 auto it = std::find(faceToTet.begin(), faceToTet.end(),
c);
662 if(it == faceToTet.end()) { faceToTet.push_back(
c); }
674 cc.push_back(containsV);
675 std::stack<Tet *> _stack;
676 _stack.push(containsV);
678 while(!_stack.empty()) {
679 Tet *t = _stack.top();
681 for(
int i = 0; i < 4; i++) {
682 Tet *neigh = t->
T[i];
683 if(neigh && (std::find(cc.begin(), cc.end(), neigh) == cc.end()) &&
684 (std::find(cavity.begin(), cavity.end(), neigh) != cavity.end())) {
690 if(cc.size() == cavity.size())
return false;
700 for(std::size_t i = 0; i < cavity.size(); i++) {
702 for(std::size_t iFace = 0; iFace < 4; iFace++) {
703 if(t->
getFace(iFace) ==
f) {
return t; }
711 std::vector<std::size_t> &_negatives)
715 if(_negatives.empty())
return false;
718 for(std::size_t i = 0; i < cavity.size(); i++) cavity[i]->unset(myThread, K);
719 for(std::size_t i = 0; i < bndK.size(); i++)
720 if(bndK[i].t) bndK[i].t->unset(myThread, K);
724 Msg::Debug(
"Fixing cavity (%3ld,%3ld) : %ld negatives", cavity.size(),
725 bndK.size(), _negatives.size());
729 if(!containsV)
return true;
731 while(!_negatives.empty()) {
732 for(std::size_t i = 0; i < _negatives.size(); i++) {
733 conn &
c = bndK[_negatives[i]];
736 auto it = std::find(cavity.begin(), cavity.end(), toRemove);
737 if(it != cavity.end()) { cavity.erase(it); }
739 Msg::Error(
"Datastructure Broken in %s line %5d", __FILE__, __LINE__);
748 for(std::size_t i = 0; i < cavity.size(); i++) cavity[i]->set(myThread, K);
749 for(std::size_t i = 0; i < bndK.size(); i++)
750 if(bndK[i].t) bndK[i].t->set(myThread, K);
756 int thread,
int iPnt)
758 std::stack<std::pair<std::pair<Tet *, Tet *>, std::pair<int, int> > > stack;
759 bool finished =
false;
763 const int maxNumberNeigh = 4;
764 int iNeighEnd = maxNumberNeigh;
766 if(iNeighStart == 0) {
767 t->
set(thread, iPnt);
771 for(
int iNeigh = iNeighStart; iNeigh < iNeighEnd; iNeigh++) {
772 Tet *neigh = t->
T[iNeigh];
773 if(neigh ==
nullptr) {
774 bnd.push_back(
conn(t->
getFace(iNeigh), iNeigh, neigh));
776 else if(neigh == prev) {
778 else if(!neigh->
inSphere(v, thread)) {
779 bnd.push_back(
conn(t->
getFace(iNeigh), iNeigh, neigh));
780 neigh->
set(thread, iPnt);
782 else if(!(neigh->
isSet(thread, iPnt))) {
784 stack.push(std::make_pair(std::make_pair(prev, t),
785 std::make_pair(iNeigh + 1, maxNumberNeigh)));
788 stack.push(std::make_pair(std::make_pair(t, neigh),
789 std::make_pair(0, maxNumberNeigh)));
796 if(stack.empty()) { finished =
true; }
798 const std::pair<std::pair<Tet *, Tet *>, std::pair<int, int> > &next =
800 prev = next.first.first;
801 t = next.first.second;
802 iNeighStart = next.second.first;
803 iNeighEnd = next.second.second;
811 std::set<Tet *> investigatedTets;
812 std::queue<Tet *> tets;
813 investigatedTets.insert(t);
823 for(
int iNeigh = 0; iNeigh < 4; iNeigh++) {
826 (
double *)
f.V[0], (
double *)
f.V[1], (
double *)
f.V[2], (
double *)v);
827 if(val >= 0.0) count++;
829 if(!investigatedTets.count(t->
T[iNeigh])) {
834 tets.push(t->
T[iNeigh]);
838 if(count == 4 && t->
inSphere(v, thread))
return t;
841 investigatedTets.insert(t);
843 else if(tets.empty()) {
844 Msg::Error(
"Jump-and-walk failed (no neighbor)");
852 Msg::Error(
"Jump-and-walk failed (no neighbor)");
916 std::size_t cSize = cavity.size();
917 for(std::size_t j = 0; j < cSize; j++) {
919 for(std::size_t index = 0; index < myThread; index++) {
920 if(
f->_bitset[index])
return false;
923 if(
f->_bitset[myThread] & ((1 << iPt) - 1))
return false;
956 std::size_t N = allocator.
size(thread);
959 Tet *t = allocator(thread, rand() % N);
960 if(t->
V[0])
return t;
966 void delaunayTrgl(
const std::size_t numThreads,
const std::size_t NPTS_AT_ONCE,
967 std::size_t Npts, std::vector<Vert *> assignTo[],
971 double totSearchGlob = 0;
972 double totCavityGlob = 0;
973 printf(
"%d threads for inserting %d points\n", numThreads, Npts);
978 std::vector<int> invalidCavities(numThreads);
979 std::vector<int> cacheMisses(numThreads, 0);
981 std::size_t maxLocSizeK = 0;
982 for(std::size_t i = 0; i < numThreads * NPTS_AT_ONCE; i++) {
983 std::size_t s = assignTo[i].size();
984 maxLocSizeK = std::max(maxLocSizeK, s);
987 #pragma omp parallel num_threads(numThreads)
990 int myThread = omp_get_thread_num();
995 double totSearch = 0;
996 std::vector<std::size_t> _negatives;
997 std::vector<cavityContainer> cavity(NPTS_AT_ONCE);
998 std::vector<connContainer> bnd(NPTS_AT_ONCE);
999 std::vector<bool> ok(NPTS_AT_ONCE);
1001 std::vector<Tet *> Choice(NPTS_AT_ONCE);
1002 for(std::size_t K = 0; K < NPTS_AT_ONCE; K++)
1005 invalidCavities[myThread] = 0;
1006 for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1007 for(std::size_t iP = 0; iP < assignTo[K + myThread * NPTS_AT_ONCE].size();
1010 assignTo[K + myThread * NPTS_AT_ONCE][iP]->_thread = myThread;
1014 std::vector<Vert *> vToAdd(NPTS_AT_ONCE);
1019 for(std::size_t iPGlob = 0; iPGlob < maxLocSizeK; iPGlob++) {
1021 std::vector<Tet *> t(NPTS_AT_ONCE);
1024 for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1025 vToAdd[K] = (iPGlob < assignTo[K + myThread * NPTS_AT_ONCE].size()) ?
1026 assignTo[K + myThread * NPTS_AT_ONCE][iPGlob] :
1031 if(!Choice[K]->V[0]) Choice[K] =
randomTet(0, allocator);
1033 t[K] =
walk(Choice[K], vToAdd[K], Npts, totSearch, myThread);
1043 for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1047 for(std::size_t i = 0; i < cavityK.size(); i++)
1048 cavityK[i]->unset(myThread, K);
1049 for(std::size_t i = 0; i < bndK.size(); i++)
1050 if(bndK[i].t) bndK[i].t->unset(myThread, K);
1053 delaunayCavity2(t[K],
nullptr, vToAdd[K], cavityK, bndK, myThread, K);
1057 vToAdd[K] =
nullptr;
1058 invalidCavities[myThread]++;
1064 for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1071 for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1076 const std::size_t cSize = cavityK.size();
1077 const std::size_t bSize = bndK.size();
1078 Choice[K] = cavityK[0];
1079 for(std::size_t i = 0; i < bSize; i++) {
1081 Tet *t = (i < cSize) ? cavityK[i] : allocator.
newTet(myThread);
1082 if(i < cSize && t->V[0]->_thread != myThread)
1083 cacheMisses[myThread]++;
1086 Tet *neigh = bndK[i].t;
1088 t->
T[1] = t->
T[2] = t->
T[3] =
nullptr;
1090 if(neigh->
getFace(0) == bndK[i].f)
1092 else if(neigh->
getFace(1) == bndK[i].f)
1094 else if(neigh->
getFace(2) == bndK[i].f)
1096 else if(neigh->
getFace(3) == bndK[i].f)
1099 Msg::Error(
"Datastructure broken in triangulation");
1107 for(std::size_t i = bSize; i < cSize; i++) {
1108 cavityK[i]->V[0] =
nullptr;
1113 #if defined(VERBOSE)
1114 #pragma omp critical
1116 totCavityGlob += totCavity;
1117 totSearchGlob += totSearch;
1122 for(std::size_t K = 0; K < NPTS_AT_ONCE; K++) {
1123 for(std::size_t i = 0; i < cavity[K].size(); i++)
1124 cavity[K][i]->unset(myThread, K);
1125 for(std::size_t i = 0; i < bnd[K].size(); i++)
1126 if(bnd[K][i].t) bnd[K][i].t->unset(myThread, K);
1130 if(invalidCavities[0])
Msg::Error(
"%d invalid cavities", invalidCavities[0]);
1132 #if defined(VERBOSE)
1133 printf(
"average searches per point %12.5E\n", totSearchGlob / Npts);
1134 printf(
"average size for del cavity %12.5E\n", totCavityGlob / Npts);
1135 printf(
"cache misses: ");
1136 for(std::size_t i = 0; i < numThreads; i++) {
1137 printf(
"%4ud ", (
int)cacheMisses[i]);
1142 for(std::size_t myThread = 0; myThread < numThreads; myThread++)
1143 for(std::size_t i = 0; i < allocator.size(myThread); i++)
1144 allocator(myThread, i)->setAllDeleted();
1151 for(
size_t i = 0; i < v.size(); i++) {
1187 for(
int i = 0; i < 4; i++) {
1198 std::vector<Vert *> &
S,
Vert *
box[8],
1203 std::vector<int> indices;
1207 int nbBlocks = nptsatonce * numThreads;
1209 std::vector<std::vector<Vert *> > assignTo(nbBlocks);
1211 for(std::size_t i = 1; i < indices.size(); i++) {
1212 int start = indices[i - 1];
1213 int end = indices[i];
1214 int sizePerBlock = (nbBlocks * ((end - start) / nbBlocks)) / nbBlocks;
1215 int currentBlock = 0;
1216 int localCounter = 0;
1217 for(
int jPt = start; jPt < end; jPt++) {
1218 if(localCounter++ >= sizePerBlock && currentBlock != nbBlocks - 1) {
1222 assignTo[currentBlock].push_back(
S[jPt]);
1226 delaunayTrgl(numThreads, nptsatonce, N, &assignTo[0], allocator);
1231 std::vector<MVertex *> &
S,
1232 std::vector<MTetrahedron *> &T,
bool removeBox)
1234 std::vector<MVertex *> _temp;
1235 std::vector<Vert *> _vertices;
1236 std::size_t N =
S.size();
1237 _temp.resize(N + 1 + 8);
1238 double maxx = 0, maxy = 0, maxz = 0;
1239 for(std::size_t i = 0; i < N; i++) {
1241 maxx = std::max(maxx, fabs(mv->
x()));
1242 maxy = std::max(maxy, fabs(mv->
y()));
1243 maxz = std::max(maxz, fabs(mv->
z()));
1245 double d = 1 * sqrt(maxx * maxx + maxy * maxy + maxz * maxz);
1249 for(std::size_t i = 0; i < N; i++) {
1260 Vert *v =
new Vert(mv->
x(), mv->
y(), mv->
z(), 1.e22, i + 1);
1261 _vertices.push_back(v);
1271 for(
int i = 0; i < 8; i++) {
1273 if(removeBox) { v->
setNum(0); }
1282 for(
int myThread = 0; myThread < numThreads; myThread++) {
1283 for(std::size_t i = 0; i < allocator.
size(myThread); i++) {
1284 Tet *t = allocator(myThread, i);
1295 else if(!removeBox) {
1302 for(
int i = 0; i < 8; i++)
delete box[i];
1303 for(std::size_t i = 0; i < _vertices.size(); i++)
delete _vertices[i];