TTK
Loading...
Searching...
No Matches
PeriodicImplicitTriangulation.cpp
Go to the documentation of this file.
2using namespace std;
3using namespace ttk;
4
6 : dimensionality_{-1}, cellNumber_{}, vertexNumber_{}, edgeNumber_{},
7 triangleNumber_{}, tetrahedronNumber_{}, isAccelerated_{} {
8 setDebugMsgPrefix("PeriodicImplicitTriangulation");
10}
11
13
15 const float &yOrigin,
16 const float &zOrigin,
17 const float &xSpacing,
18 const float &ySpacing,
19 const float &zSpacing,
20 const SimplexId &xDim,
21 const SimplexId &yDim,
22 const SimplexId &zDim) {
23
24 // Dimensionality //
25 if(xDim < 1 or yDim < 1 or zDim < 1)
26 dimensionality_ = -1;
27 else if(xDim > 1 and yDim > 1 and zDim > 1)
29 else if((xDim > 1 and yDim > 1) or (yDim > 1 and zDim > 1)
30 or (xDim > 1 and zDim > 1))
32 else if(xDim > 1 or yDim > 1 or zDim > 1)
34 else
36
37 // Essentials //
38 origin_[0] = xOrigin;
39 origin_[1] = yOrigin;
40 origin_[2] = zOrigin;
41 spacing_[0] = xSpacing;
42 spacing_[1] = ySpacing;
43 spacing_[2] = zSpacing;
44 dimensions_[0] = xDim;
45 dimensions_[1] = yDim;
46 dimensions_[2] = zDim;
47 nbvoxels_[0] = xDim - 1;
48 nbvoxels_[1] = yDim - 1;
49 nbvoxels_[2] = zDim - 1;
50
51 if(dimensionality_ == 3) {
52 // VertexShift
53 vshift_[0] = xDim;
54 vshift_[1] = xDim * yDim;
55 // EdgeSetDimensions
56 esetdims_[0] = xDim * yDim * zDim;
57 esetdims_[1] = xDim * yDim * zDim;
58 esetdims_[2] = xDim * yDim * zDim;
59 esetdims_[3] = xDim * yDim * zDim;
60 esetdims_[4] = xDim * yDim * zDim;
61 esetdims_[5] = xDim * yDim * zDim;
62 esetdims_[6] = xDim * yDim * zDim;
63 // EdgeSetShift
64 esetshift_[0] = esetdims_[0];
65 for(int k = 1; k < 7; ++k)
66 esetshift_[k] = esetshift_[k - 1] + esetdims_[k];
67 // EdgeShift
68 eshift_[0] = xDim;
69 eshift_[1] = xDim * yDim;
70 eshift_[2] = xDim;
71 eshift_[3] = xDim * yDim;
72 eshift_[4] = xDim;
73 eshift_[5] = xDim * yDim;
74 eshift_[6] = xDim;
75 eshift_[7] = xDim * yDim;
76 eshift_[8] = xDim;
77 eshift_[9] = xDim * yDim;
78 eshift_[10] = xDim;
79 eshift_[11] = xDim * yDim;
80 eshift_[12] = xDim;
81 eshift_[13] = xDim * yDim;
82 // TriangleSetDimensions
83 tsetdims_[0] = xDim * yDim * zDim * 2;
84 tsetdims_[1] = xDim * yDim * zDim * 2;
85 tsetdims_[2] = xDim * yDim * zDim * 2;
86 tsetdims_[3] = xDim * yDim * zDim * 2;
87 tsetdims_[4] = xDim * yDim * zDim * 2;
88 tsetdims_[5] = xDim * yDim * zDim * 2;
89 // TriangleSetShift
90 tsetshift_[0] = tsetdims_[0];
91 for(int k = 1; k < 6; ++k)
92 tsetshift_[k] = tsetshift_[k - 1] + tsetdims_[k];
93 // TriangleShift
94 tshift_[0] = xDim * 2;
95 tshift_[1] = xDim * yDim * 2;
96 tshift_[2] = xDim * 2;
97 tshift_[3] = xDim * yDim * 2;
98 tshift_[4] = xDim * 2;
99 tshift_[5] = xDim * yDim * 2;
100 tshift_[6] = xDim * 2;
101 tshift_[7] = xDim * yDim * 2;
102 tshift_[8] = xDim * 2;
103 tshift_[9] = xDim * yDim * 2;
104 tshift_[10] = xDim * 2;
105 tshift_[11] = xDim * yDim * 2;
106 // TetrahedronShift
107 tetshift_[0] = xDim * 6;
108 tetshift_[1] = xDim * yDim * 6;
109
110 wrap_[0] = xDim;
111 wrap_[1] = xDim * yDim;
112 wrap_[2] = xDim * yDim * zDim;
113
114 // Numbers
115 vertexNumber_ = xDim * yDim * zDim;
116 edgeNumber_ = 0;
117 for(int k = 0; k < 7; ++k)
119 triangleNumber_ = 0;
120 for(int k = 0; k < 6; ++k)
122 tetrahedronNumber_ = xDim * yDim * zDim * 6;
124
126 } else if(dimensionality_ == 2) {
127 // dimensions selectors
128 if(xDim == 1) {
129 Di_ = 1;
130 Dj_ = 2;
131 } else if(yDim == 1) {
132 Di_ = 0;
133 Dj_ = 2;
134 } else {
135 Di_ = 0;
136 Dj_ = 1;
137 }
138 // VertexShift
139 vshift_[0] = dimensions_[Di_];
140 // EdgeSetDimensions
144 // EdgeSetShift
145 esetshift_[0] = esetdims_[0];
146 for(int k = 1; k < 3; ++k)
147 esetshift_[k] = esetshift_[k - 1] + esetdims_[k];
148 // EdgeShift
149 eshift_[0] = dimensions_[Di_];
150 eshift_[2] = dimensions_[Di_];
151 eshift_[4] = dimensions_[Di_];
152 // TriangleShift
153 tshift_[0] = dimensions_[Di_] * 2;
154
155 wrap_[0] = dimensions_[Di_];
157
158 // Numbers
160 edgeNumber_ = 0;
161 for(int k = 0; k < 3; ++k)
165
167 } else if(dimensionality_ == 1) {
168 // dimensions selectors
169 for(int k = 0; k < 3; ++k) {
170 if(dimensions_[k] > 1) {
171 Di_ = k;
172 break;
173 }
174 }
175
176 // Numbers
180 }
181
182 return 0;
183}
184
186 isAccelerated_ = false;
187
188 unsigned long long int msb[3];
189 if(dimensionality_ == 3) {
190 bool allDimensionsArePowerOfTwo = true;
191 for(int k = 0; k < 3; ++k)
192 if(!isPowerOfTwo(dimensions_[k], msb[k]))
193 allDimensionsArePowerOfTwo = false;
194
195 if(allDimensionsArePowerOfTwo) {
196 mod_[0] = dimensions_[0] - 1;
197 mod_[1] = dimensions_[0] * dimensions_[1] - 1;
198 div_[0] = msb[0];
199 div_[1] = msb[0] + msb[1];
200 isAccelerated_ = true;
201 }
202 } else if(dimensionality_ == 2) {
203 bool isDi = isPowerOfTwo(dimensions_[Di_], msb[Di_]);
204 bool isDj = isPowerOfTwo(dimensions_[Dj_], msb[Dj_]);
205 bool allDimensionsArePowerOfTwo = (isDi and isDj);
206
207 if(allDimensionsArePowerOfTwo) {
208 mod_[0] = dimensions_[Di_] - 1;
209 div_[0] = msb[Di_];
210 isAccelerated_ = true;
211 }
212 }
213
214 if(isAccelerated_) {
215 printMsg("Accelerated getVertex*() requests.", debug::Priority::INFO);
216 }
217
218 return 0;
219}
220
222 unsigned long long int &r) {
223 if(v && !(v & (v - 1))) {
224 r = 0;
225 while(v >>= 1)
226 r++;
227 return true;
228 }
229 return false;
230}
231
232bool PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
233 isVertexOnBoundary)(const SimplexId &vertexId) const {
234#ifndef TTK_ENABLE_KAMIKAZE
235 if(vertexId < 0 or vertexId >= vertexNumber_)
236 return -1;
237#else
238 TTK_FORCE_USE(vertexId);
239#endif
240
241 return false;
242}
243
244bool PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
245 isEdgeOnBoundary)(const SimplexId &edgeId) const {
246#ifndef TTK_ENABLE_KAMIKAZE
247 if(edgeId < 0 or edgeId >= edgeNumber_)
248 return -1;
249#else
250 TTK_FORCE_USE(edgeId);
251#endif
252
253 return false;
254}
255
256bool PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
257 isTriangleOnBoundary)(const SimplexId &triangleId) const {
258#ifndef TTK_ENABLE_KAMIKAZE
259 if(triangleId < 0 or triangleId >= triangleNumber_)
260 return -1;
261#else
262 TTK_FORCE_USE(triangleId);
263#endif
264
265 return false;
266}
267
268SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
269 getVertexNeighborNumber)(const SimplexId &vertexId) const {
270#ifndef TTK_ENABLE_KAMIKAZE
271 if(vertexId < 0 or vertexId >= vertexNumber_)
272 return -1;
273#else
274 TTK_FORCE_USE(vertexId);
275#endif
276
277 if(dimensionality_ == 3) {
278 return 14; // abcdefgh
279 } else if(dimensionality_ == 2) {
280 return 6; // abcd
281 } else if(dimensionality_ == 1) {
282 return 2; // ab
283 }
284
285 return -1;
286}
287
288template <typename Derived>
290 getVertexNeighbor)(const SimplexId &vertexId,
291 const int &localNeighborId,
292 SimplexId &neighborId) const {
293#ifndef TTK_ENABLE_KAMIKAZE
294 if(localNeighborId < 0
295 or localNeighborId >= getVertexNeighborNumber(vertexId))
296 return -1;
297#endif
298
299 neighborId = -1;
300 const auto &p = this->underlying().getVertexCoords(vertexId);
301
302 if(dimensionality_ == 3) {
303 neighborId = getVertexNeighbor3d(p.data(), vertexId, localNeighborId);
304 } else if(dimensionality_ == 2) {
305 neighborId = getVertexNeighbor2d(p.data(), vertexId, localNeighborId);
306 } else if(dimensionality_ == 1) {
307 // ab
308 if(vertexId > 0 and vertexId < nbvoxels_[Di_]) {
309 if(localNeighborId == 0)
310 neighborId = vertexId + 1;
311 else
312 neighborId = vertexId - 1;
313 } else if(vertexId == 0) {
314 if(localNeighborId == 0)
315 neighborId = vertexId + 1; // a
316 else
317 neighborId = nbvoxels_[Di_];
318 } else {
319 if(localNeighborId == 0)
320 neighborId = 0; // a
321 else
322 neighborId = vertexId - 1; // b
323 }
324 }
325
326 return 0;
327}
328
329const vector<vector<SimplexId>> *
330 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
332 if(vertexNeighborList_.empty()) {
333 Timer t;
334 vertexNeighborList_.resize(vertexNumber_);
335 for(SimplexId i = 0; i < vertexNumber_; ++i) {
336 vertexNeighborList_[i].resize(getVertexNeighborNumber(i));
337 for(SimplexId j = 0; j < (SimplexId)vertexNeighborList_[i].size(); ++j)
338 getVertexNeighbor(i, j, vertexNeighborList_[i][j]);
339 }
340
341 printMsg("Built " + to_string(vertexNumber_) + " vertex neighbors.", 1,
342 t.getElapsedTime(), 1);
343 }
344
345 return &vertexNeighborList_;
346}
347
349 const SimplexId &vertexId) const {
350 return getVertexNeighborNumber(vertexId);
351}
352
353template <typename Derived>
355 const SimplexId &vertexId, const int &localEdgeId, SimplexId &edgeId) const {
356#ifndef TTK_ENABLE_KAMIKAZE
357 if(localEdgeId < 0 or localEdgeId >= getVertexEdgeNumberInternal(vertexId))
358 return -1;
359#endif
360
361 edgeId = -1;
362 const auto &p = this->underlying().getVertexCoords(vertexId);
363
364 if(dimensionality_ == 3) {
365 edgeId = getVertexEdge3d(p.data(), localEdgeId);
366 } else if(dimensionality_ == 2) {
367 edgeId = getVertexEdge2d(p.data(), localEdgeId);
368 } else if(dimensionality_ == 1) {
369 if(vertexId > 0 and vertexId < nbvoxels_[Di_]) {
370 // ab
371 edgeId = localEdgeId == 0 ? vertexId : vertexId - 1;
372 } else if(vertexId == 0) {
373 // a
374 edgeId = localEdgeId == 0 ? vertexId : 0;
375 } else {
376 // b
377 edgeId = localEdgeId == 0 ? 0 : vertexId - 1;
378 }
379 }
380
381 return 0;
382}
383
384const vector<vector<SimplexId>> *
386 if(vertexEdgeList_.empty()) {
387 Timer t;
388
390 for(SimplexId i = 0; i < vertexNumber_; ++i) {
392 for(SimplexId j = 0; j < (SimplexId)vertexEdgeList_[i].size(); ++j)
394 }
395
396 printMsg("Built " + to_string(vertexNumber_) + " vertex edges.", 1,
397 t.getElapsedTime(), 1);
398 }
399
400 return &vertexEdgeList_;
401}
402
404 const SimplexId &vertexId) const {
405#ifndef TTK_ENABLE_KAMIKAZE
406 if(vertexId < 0 or vertexId >= vertexNumber_)
407 return -1;
408#else
409 TTK_FORCE_USE(vertexId);
410#endif
411
412 if(dimensionality_ == 3) {
413 return 36; // abcdefgh
414 }
415
416 return 0;
417}
418
419template <typename Derived>
421 const SimplexId &vertexId,
422 const int &localTriangleId,
423 SimplexId &triangleId) const {
424#ifndef TTK_ENABLE_KAMIKAZE
425 if(localTriangleId < 0
426 or localTriangleId >= getVertexTriangleNumberInternal(vertexId))
427 return -1;
428#endif
429 triangleId = -1;
430
431 const auto &p = this->underlying().getVertexCoords(vertexId);
432
433 if(dimensionality_ == 3) {
434 triangleId = getVertexTriangle3d(p.data(), localTriangleId);
435 }
436
437 return 0;
438}
439
440const vector<vector<SimplexId>> *
442 if(vertexTriangleList_.empty()) {
443 Timer t;
444
446 for(SimplexId i = 0; i < vertexNumber_; ++i) {
448 for(SimplexId j = 0; j < (SimplexId)vertexTriangleList_[i].size(); ++j)
450 }
451
452 printMsg("Built " + to_string(vertexNumber_) + " vertex triangles.", 1,
453 t.getElapsedTime(), 1);
454 }
455
456 return &vertexTriangleList_;
457}
458
459SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
460 getVertexLinkNumber)(const SimplexId &vertexId) const {
461 return getVertexStarNumber(vertexId);
462}
463
464template <typename Derived>
466 getVertexLink)(const SimplexId &vertexId,
467 const int &localLinkId,
468 SimplexId &linkId) const {
469#ifndef TTK_ENABLE_KAMIKAZE
470 if(localLinkId < 0 or localLinkId >= getVertexLinkNumber(vertexId))
471 return -1;
472#endif
473
474 linkId = -1;
475 const auto &p = this->underlying().getVertexCoords(vertexId);
476
477 if(dimensionality_ == 3) {
478 linkId = getVertexLink3d(p.data(), localLinkId);
479 } else if(dimensionality_ == 2) {
480 linkId = getVertexLink2d(p.data(), localLinkId); // abcd
481 }
482
483 return 0;
484}
485
486const vector<vector<SimplexId>> *
487 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getVertexLinks)() {
488 if(vertexLinkList_.empty()) {
489 Timer t;
490
491 vertexLinkList_.resize(vertexNumber_);
492 for(SimplexId i = 0; i < vertexNumber_; ++i) {
493 vertexLinkList_[i].resize(getVertexLinkNumber(i));
494 for(SimplexId j = 0; j < (SimplexId)vertexLinkList_[i].size(); ++j)
495 getVertexLink(i, j, vertexLinkList_[i][j]);
496 }
497
498 printMsg("Built " + to_string(vertexNumber_) + " vertex links.", 1,
499 t.getElapsedTime(), 1);
500 }
501
502 return &vertexLinkList_;
503}
504
505SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
506 getVertexStarNumber)(const SimplexId &vertexId) const {
507#ifndef TTK_ENABLE_KAMIKAZE
508 if(vertexId < 0 or vertexId >= vertexNumber_)
509 return -1;
510#else
511 TTK_FORCE_USE(vertexId);
512#endif
513
514 if(dimensionality_ == 3) {
515 return 24; // abcdefgh
516 } else if(dimensionality_ == 2) {
517 return 6; // abcd
518 }
519
520 return 0;
521}
522
523template <typename Derived>
525 getVertexStar)(const SimplexId &vertexId,
526 const int &localStarId,
527 SimplexId &starId) const {
528#ifndef TTK_ENABLE_KAMIKAZE
529 if(localStarId < 0 or localStarId >= getVertexStarNumber(vertexId))
530 return -1;
531#endif
532
533 starId = -1;
534 const auto &p = this->underlying().getVertexCoords(vertexId);
535
536 if(dimensionality_ == 3) {
537 starId = getVertexStar3d(p.data(), localStarId);
538 } else if(dimensionality_ == 2) {
539 starId = getVertexStar2d(p.data(), localStarId);
540 }
541
542 return 0;
543}
544
545const vector<vector<SimplexId>> *
546 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getVertexStars)() {
547 if(vertexStarList_.empty()) {
548 Timer t;
549 vertexStarList_.resize(vertexNumber_);
550 for(SimplexId i = 0; i < vertexNumber_; ++i) {
551 vertexStarList_[i].resize(getVertexStarNumber(i));
552 for(SimplexId j = 0; j < (SimplexId)vertexStarList_[i].size(); ++j)
553 getVertexStar(i, j, vertexStarList_[i][j]);
554 }
555
556 printMsg("Built " + to_string(vertexNumber_) + " vertex stars.", 1,
557 t.getElapsedTime(), 1);
558 }
559
560 return &vertexStarList_;
562
563#ifdef TTK_ENABLE_MPI
564
565void PeriodicImplicitTriangulation::setIsBoundaryPeriodic(
566 std::array<unsigned char, 6> boundary) {
567 this->isBoundaryPeriodic = boundary;
568}
569
570void PeriodicImplicitTriangulation::createMetaGrid(const double *const bounds) {
571 // only works with 2 processes or more
572 if(!ttk::isRunningWithMPI()) {
573 return;
574 }
575
576 // no need to create it anew?
577 if(this->metaGrid_ != nullptr) {
578 return;
579 }
580
581 // Reorganize bounds to only execute Allreduce twice
582 std::array<double, 6> tempBounds = {
583 bounds[0], bounds[2], bounds[4], bounds[1], bounds[3], bounds[5],
584 };
585
586 for(int i = 0; i < 3; i++) {
587 if(dimensionality_ > i) {
588 if(this->isBoundaryPeriodic[2 * i] == 1) {
589 tempBounds[i] += spacing_[i];
590 }
591 if(this->isBoundaryPeriodic[2 * i + 1] == 1) {
592 tempBounds[3 + i] -= spacing_[i];
593 }
594 }
595 }
596
597 std::array<double, 6> tempGlobalBounds{};
598 // Compute and send to all processes the lower bounds of the data set
599 MPI_Allreduce(tempBounds.data(), tempGlobalBounds.data(), 3, MPI_DOUBLE,
600 MPI_MIN, ttk::MPIcomm_);
601 // Compute and send to all processes the higher bounds of the data set
602 MPI_Allreduce(&tempBounds[3], &tempGlobalBounds[3], 3, MPI_DOUBLE, MPI_MAX,
603 ttk::MPIcomm_);
604
605 // re-order tempGlobalBounds
606 std::array<double, 6> globalBounds{
607 tempGlobalBounds[0], tempGlobalBounds[3], tempGlobalBounds[1],
608 tempGlobalBounds[4], tempGlobalBounds[2], tempGlobalBounds[5],
609 };
610
611 const std::array<ttk::SimplexId, 3> dimensions = {
612 static_cast<ttk::SimplexId>(
613 std::round((globalBounds[1] - globalBounds[0]) / this->spacing_[0]))
614 + 1,
615 static_cast<ttk::SimplexId>(
616 std::round((globalBounds[3] - globalBounds[2]) / this->spacing_[1]))
617 + 1,
618 static_cast<ttk::SimplexId>(
619 std::round((globalBounds[5] - globalBounds[4]) / this->spacing_[2]))
620 + 1,
621 };
622
623 this->localGridOffset_ = {
624 static_cast<SimplexId>(
625 std::round((this->origin_[0] - globalBounds[0]) / this->spacing_[0])),
626 static_cast<SimplexId>(
627 std::round((this->origin_[1] - globalBounds[2]) / this->spacing_[1])),
628 static_cast<SimplexId>(
629 std::round((this->origin_[2] - globalBounds[4]) / this->spacing_[2])),
630 };
631
632 this->metaGrid_ = std::make_shared<PeriodicNoPreconditions>();
633 this->metaGrid_->setInputGrid(globalBounds[0], globalBounds[1],
634 globalBounds[2], this->spacing_[0],
635 this->spacing_[1], this->spacing_[2],
636 dimensions[0], dimensions[1], dimensions[2]);
638
639int PeriodicImplicitTriangulation::preconditionDistributedCells() {
640 if(this->hasPreconditionedDistributedCells_) {
641 return 0;
642 }
643 if(!ttk::hasInitializedMPI()) {
644 return -1;
646 if(this->metaGrid_ == nullptr) {
647 return 0;
648 }
649 if(this->cellGhost_ == nullptr) {
650 if(ttk::isRunningWithMPI()) {
651 this->printErr("Missing cell ghost array!");
652 }
653 return -3;
654 }
655
656 Timer tm{};
657
658 // there are 6 tetrahedra per cubic cell (and 2 triangles per square)
659 const int nTetraPerCube{this->dimensionality_ == 3 ? 6 : 2};
660
661 // number of local cells (with ghost cells but without the additional periodic
662 // cells)
663 const auto nLocCells{(this->dimensions_[0] - 1) * (this->dimensions_[1] - 1)
664 * (this->dimensions_[2] - 1) * nTetraPerCube};
665
666 std::vector<unsigned char> fillCells(nLocCells / nTetraPerCube);
667
668 this->neighborCellBBoxes_.resize(ttk::MPIsize_);
669 auto &localBBox{this->neighborCellBBoxes_[ttk::MPIrank_]};
670 // "good" starting values?
671 localBBox = {
672 this->localGridOffset_[0] + this->dimensions_[0], this->localGridOffset_[0],
673 this->localGridOffset_[1] + this->dimensions_[1], this->localGridOffset_[1],
674 this->localGridOffset_[2] + this->dimensions_[2], this->localGridOffset_[2],
675 };
676 const auto &dims{this->metaGrid_->getGridDimensions()};
677
678 for(SimplexId lcid = 0; lcid < nLocCells; ++lcid) {
679 // only keep non-ghost cells
680 if(this->cellGhost_[lcid / nTetraPerCube] != 0) {
681 continue;
682 }
683 // local vertex coordinates
684 std::array<SimplexId, 3> p{};
685 if(this->dimensionality_ == 3) {
686 this->tetrahedronToPosition(lcid, p.data());
687 } else if(this->dimensionality_ == 2) {
688 this->triangleToPosition2d(lcid, p.data());
689 // compatibility with tetrahedronToPosition; fix a bounding box
690 // error in the first axis
691 p[0] /= 2;
692 }
693
694 // global vertex coordinates
695 p[0] += this->localGridOffset_[0];
696 p[1] += this->localGridOffset_[1];
697 p[2] += this->localGridOffset_[2];
698
699 if(p[0] < localBBox[0]) {
700 localBBox[0] = max(p[0], static_cast<ttk::SimplexId>(0));
701 }
702 if(p[0] > localBBox[1]) {
703 localBBox[1] = min(p[0], dims[0]);
704 }
705 if(p[1] < localBBox[2]) {
706 localBBox[2] = max(p[1], static_cast<ttk::SimplexId>(0));
707 }
708 if(p[1] > localBBox[3]) {
709 localBBox[3] = min(p[1], dims[1]);
710 }
711 if(p[2] < localBBox[4]) {
712 localBBox[4] = max(p[2], static_cast<ttk::SimplexId>(0));
713 }
714 if(p[2] > localBBox[5]) {
715 localBBox[5] = min(p[2], dims[2]);
716 }
717 }
718 localBBox[0] -= isBoundaryPeriodic[0];
719 if(dimensionality_ > 1) {
720 localBBox[2] -= isBoundaryPeriodic[2];
721 if(dimensionality_ > 2)
722 localBBox[4] -= isBoundaryPeriodic[4];
723 }
724
725 localBBox[1]++;
726 localBBox[3]++;
727 localBBox[5]++;
728
729 for(size_t i = 0; i < this->neighborRanks_.size(); ++i) {
730 const auto neigh{this->neighborRanks_[i]};
731 MPI_Sendrecv(this->neighborCellBBoxes_[ttk::MPIrank_].data(), 6,
732 ttk::getMPIType(SimplexId{}), neigh, ttk::MPIrank_,
733 this->neighborCellBBoxes_[neigh].data(), 6,
734 ttk::getMPIType(SimplexId{}), neigh, neigh, ttk::MPIcomm_,
735 MPI_STATUS_IGNORE);
736 }
737
738 this->hasPreconditionedDistributedCells_ = true;
739
740 return 0;
741}
742
743std::array<SimplexId, 3> PeriodicImplicitTriangulation::getVertGlobalCoords(
744 const SimplexId lvid) const {
745 // local vertex coordinates
746 std::array<SimplexId, 3> p{};
747 if(this->dimensionality_ == 3) {
748 this->vertexToPosition(lvid, p.data());
749 } else if(this->dimensionality_ == 2) {
750 this->vertexToPosition2d(lvid, p.data());
751 }
752 // global vertex coordinates
753 p[0] += this->localGridOffset_[0];
754 p[1] += this->localGridOffset_[1];
755 p[2] += this->localGridOffset_[2];
756
757 const auto &dims{this->metaGrid_->getGridDimensions()};
758
759 p[0] = (p[0] + dims[0]) % dims[0];
760 if(dimensionality_ > 1) {
761 p[1] = (p[1] + dims[1]) % dims[1];
762 if(dimensionality_ > 2)
763 p[2] = (p[2] + dims[2]) % dims[2];
764 }
765
766 return p;
767}
768
769std::array<SimplexId, 3> PeriodicImplicitTriangulation::getVertLocalCoords(
770 const SimplexId gvid) const {
771 // global vertex coordinates
772 std::array<SimplexId, 3> pGlobal{};
773 if(this->dimensionality_ == 3) {
774 this->metaGrid_->vertexToPosition(gvid, pGlobal.data());
775 } else if(this->dimensionality_ == 2) {
776 this->metaGrid_->vertexToPosition2d(gvid, pGlobal.data());
777 }
778 std::array<SimplexId, 3> p{pGlobal};
779 // local vertex coordinates
780 p[0] -= this->localGridOffset_[0];
781 p[1] -= this->localGridOffset_[1];
782 p[2] -= this->localGridOffset_[2];
783
784 const auto &dims{this->getGridDimensions()};
785
786 if(p[0] >= 0 && p[1] >= 0 && p[2] >= 0 && p[0] <= dims[0] - 1
787 && p[1] <= dims[1] - 1 && p[2] <= dims[2] - 1) {
788 return p;
789 }
790 for(int i = 0; i < 3; i++) {
791 if((p[i] < 0 || p[i] > dims[i] - 1) && pGlobal[i] == 0) {
792 p[i] = dims[i] - 1;
793 }
794 if((p[i] < 0 || p[i] > dims[i] - 1)
795 && pGlobal[i] == this->metaGrid_->dimensions_[i] - 1) {
796 p[i] = 0;
797 }
798 }
799
800 if(p[0] >= 0 && p[1] >= 0 && p[2] >= 0 && p[0] <= dims[0] - 1
801 && p[1] <= dims[1] - 1 && p[2] <= dims[2] - 1) {
802 if(this->vertexGhost_[p[0] + p[1] * dims[0] + p[2] * dims[0] * dims[1]]
803 != 0) {
804 return p;
805 }
806 }
807 return std::array<SimplexId, 3>{-1, -1, -1};
808}
809
810int ttk::PeriodicImplicitTriangulation::getCellRankInternal(
811 const SimplexId lcid) const {
812
813 const int nTetraPerCube{this->dimensionality_ == 3 ? 6 : 2};
814 const auto locCubeId{lcid / nTetraPerCube};
815
816 if(this->cellGhost_[locCubeId] == 0) {
817 return ttk::MPIrank_;
818 }
819
820#ifndef TTK_ENABLE_KAMIKAZE
821 if(this->neighborRanks_.empty()) {
822 this->printErr("Empty neighborsRanks_!");
823 return -1;
824 }
825#endif // TTK_ENABLE_KAMIKAZE
826
827 const auto nVertsCell{this->getCellVertexNumber(lcid)};
828 std::vector<bool> inRank(nVertsCell);
829 std::map<int, int> neighborOccurrences;
830 for(const auto neigh : this->neighborRanks_) {
831 std::fill(inRank.begin(), inRank.end(), false);
832 const auto &bbox{this->neighborCellBBoxes_[neigh]};
833 for(SimplexId i = 0; i < nVertsCell; ++i) {
834 SimplexId v{};
835 this->getCellVertex(lcid, i, v);
836 if(this->vertexGhost_[v] == 0) {
837 inRank[i] = true;
838 } else {
839 const auto p{this->getVertGlobalCoords(v)};
840 if(p[0] >= bbox[0] && p[0] <= bbox[1] && p[1] >= bbox[2]
841 && p[1] <= bbox[3] && p[2] >= bbox[4] && p[2] <= bbox[5]) {
842 inRank[i] = true;
843 }
844 }
845 }
846 if(std::all_of(
847 inRank.begin(), inRank.end(), [](const bool v) { return v; })) {
848 return neigh;
849 }
850 neighborOccurrences[neigh]
851 = std::accumulate(inRank.begin(), inRank.end(), 0);
852 }
853
854 auto pr = std::max_element(
855 std::begin(neighborOccurrences), std::end(neighborOccurrences),
856 [](const std::pair<int, int> &p1, const std::pair<int, int> &p2) {
857 return p1.second < p2.second;
858 });
859 return pr->first;
860}
861
862#endif // TTK_ENABLE_MPI
863
864template <typename Derived>
866 getVertexPoint)(const SimplexId &vertexId,
867 float &x,
868 float &y,
869 float &z) const {
870#ifndef TTK_ENABLE_KAMIKAZE
871 if(vertexId < 0 or vertexId >= vertexNumber_)
872 return -1;
873#endif
874
875 if(dimensionality_ == 3) {
876 const auto &p = this->underlying().getVertexCoords(vertexId);
877
878 x = origin_[0] + spacing_[0] * p[0];
879 y = origin_[1] + spacing_[1] * p[1];
880 z = origin_[2] + spacing_[2] * p[2];
881 } else if(dimensionality_ == 2) {
882 const auto &p = this->underlying().getVertexCoords(vertexId);
883
884 if(dimensions_[0] > 1 and dimensions_[1] > 1) {
885 x = origin_[0] + spacing_[0] * p[0];
886 y = origin_[1] + spacing_[1] * p[1];
887 z = origin_[2];
888 } else if(dimensions_[1] > 1 and dimensions_[2] > 1) {
889 x = origin_[0];
890 y = origin_[1] + spacing_[1] * p[0];
891 z = origin_[2] + spacing_[2] * p[1];
892 } else if(dimensions_[0] > 1 and dimensions_[2] > 1) {
893 x = origin_[0] + spacing_[0] * p[0];
894 y = origin_[1];
895 z = origin_[2] + spacing_[2] * p[1];
896 }
897 } else if(dimensionality_ == 1) {
898 if(dimensions_[0] > 1) {
899 x = origin_[0] + spacing_[0] * vertexId;
900 y = origin_[1];
901 z = origin_[2];
902 } else if(dimensions_[1] > 1) {
903 x = origin_[0];
904 y = origin_[1] + spacing_[1] * vertexId;
905 z = origin_[2];
906 } else if(dimensions_[2] > 1) {
907 x = origin_[0];
908 y = origin_[1];
909 z = origin_[2] + spacing_[2] * vertexId;
910 }
911 }
912
913 return 0;
914}
915
916template <typename Derived>
918 const SimplexId &edgeId,
919 const int &localVertexId,
920 SimplexId &vertexId) const {
921#ifndef TTK_ENABLE_KAMIKAZE
922 if(edgeId < 0 or edgeId >= edgeNumber_)
923 return -1;
924 if(localVertexId < 0 or localVertexId >= 2)
925 return -2;
926#endif
927
928 vertexId = -1;
929 const auto &p = this->underlying().getEdgeCoords(edgeId);
930 const SimplexId wrapXRight = (p[0] == nbvoxels_[0] ? -wrap_[0] : 0);
931 const SimplexId wrapYBottom = (p[1] == nbvoxels_[1] ? -wrap_[1] : 0);
932 const SimplexId wrapZFront = (p[2] == nbvoxels_[2] ? -wrap_[2] : 0);
933 const auto a = p[0] + this->underlying().getEdgeVertexAccelerated(edgeId);
934
935 switch(this->underlying().getEdgePosition(edgeId)) {
936 case EdgePosition::L_3D:
937 vertexId = a + (localVertexId == 0 ? 0 : (1 + wrapXRight));
938 break;
939 case EdgePosition::H_3D:
940 vertexId = a + (localVertexId == 0 ? 0 : (vshift_[0] + wrapYBottom));
941 break;
942 case EdgePosition::P_3D:
943 vertexId = a + (localVertexId == 0 ? 0 : (vshift_[1] + wrapZFront));
944 break;
945 case EdgePosition::D1_3D:
946 vertexId = a
947 + (localVertexId == 0 ? (1 + wrapXRight)
948 : (vshift_[0] + wrapYBottom));
949 break;
950 case EdgePosition::D2_3D:
951 vertexId = a
952 + (localVertexId == 0
953 ? 0
954 : (vshift_[0] + wrapYBottom + vshift_[1] + wrapZFront));
955 break;
956 case EdgePosition::D3_3D:
957 vertexId
958 = a
959 + (localVertexId == 0 ? (1 + wrapXRight) : (vshift_[1] + wrapZFront));
960 break;
961 case EdgePosition::D4_3D:
962 vertexId = a
963 + (localVertexId == 0
964 ? (1 + wrapXRight)
965 : (vshift_[0] + wrapYBottom + vshift_[1] + wrapZFront));
966 break;
967 case EdgePosition::L_2D:
968 vertexId = a + (localVertexId == 0 ? 0 : (1 + wrapXRight));
969 break;
970 case EdgePosition::H_2D:
971 vertexId = a + (localVertexId == 0 ? 0 : (vshift_[0] + wrapYBottom));
972 break;
973 case EdgePosition::D1_2D:
974 vertexId = a
975 + (localVertexId == 0 ? (1 + wrapXRight)
976 : (vshift_[0] + wrapYBottom));
977 break;
978 case EdgePosition::FIRST_EDGE_1D:
979 vertexId = localVertexId == 0 ? 0 : 1;
980 break;
981 case EdgePosition::LAST_EDGE_1D:
982 vertexId = localVertexId == 0 ? edgeId : 0;
983 break;
984 case EdgePosition::CENTER_1D:
985 vertexId = localVertexId == 0 ? edgeId : edgeId + 1;
986 break;
987 default:
988 break;
989 }
990
991 return 0;
992}
993
994const vector<std::array<SimplexId, 2>> *
995 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdges)() {
996
997 if(edgeList_.empty()) {
998 Timer t;
999
1000 edgeList_.resize(edgeNumber_);
1001 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1002 SimplexId id0, id1;
1003 getEdgeVertexInternal(i, 0, id0);
1004 getEdgeVertexInternal(i, 1, id1);
1005 edgeList_[i] = {id0, id1};
1006 }
1007
1008 printMsg(
1009 "Built " + to_string(edgeNumber_) + " edges.", 1, t.getElapsedTime(), 1);
1010 }
1011
1012 return &edgeList_;
1013}
1014
1015template <typename Derived>
1018 const SimplexId &edgeId) const {
1019#ifndef TTK_ENABLE_KAMIKAZE
1020 if(edgeId < 0 or edgeId >= edgeNumber_)
1021 return -1;
1022#endif
1023
1024 switch(this->underlying().getEdgePosition(edgeId)) {
1025 case EdgePosition::L_3D:
1026 case EdgePosition::H_3D:
1027 case EdgePosition::P_3D:
1028 case EdgePosition::D4_3D:
1029 return 6;
1030 case EdgePosition::D1_3D:
1031 case EdgePosition::D2_3D:
1032 case EdgePosition::D3_3D:
1033 return 4;
1034 case EdgePosition::L_2D:
1035 case EdgePosition::H_2D:
1036 case EdgePosition::D1_2D:
1037 return 2;
1038 default:
1039 return 0;
1040 }
1041}
1042
1043template <typename Derived>
1045 const SimplexId &edgeId,
1046 const int &localTriangleId,
1047 SimplexId &triangleId) const {
1048#ifndef TTK_ENABLE_KAMIKAZE
1049 if(localTriangleId < 0
1050 or localTriangleId >= getEdgeTriangleNumberInternal(edgeId))
1051 return -1;
1052#endif
1053
1054 triangleId = -1;
1055 const auto &p = this->underlying().getEdgeCoords(edgeId);
1056
1057 switch(this->underlying().getEdgePosition(edgeId)) {
1058 case EdgePosition::L_3D:
1059 triangleId = getEdgeTriangle3dL(p.data(), localTriangleId);
1060 break;
1061 case EdgePosition::H_3D:
1062 triangleId = getEdgeTriangle3dH(p.data(), localTriangleId);
1063 break;
1064 case EdgePosition::P_3D:
1065 triangleId = getEdgeTriangle3dP(p.data(), localTriangleId);
1066 break;
1067 case EdgePosition::D1_3D:
1068 triangleId = getEdgeTriangle3dD1(p.data(), localTriangleId);
1069 break;
1070 case EdgePosition::D2_3D:
1071 triangleId = getEdgeTriangle3dD2(p.data(), localTriangleId);
1072 break;
1073 case EdgePosition::D3_3D:
1074 triangleId = getEdgeTriangle3dD3(p.data(), localTriangleId);
1075 break;
1076 case EdgePosition::D4_3D:
1077 triangleId = getEdgeTriangle3dD4(p.data(), localTriangleId);
1078 break;
1079 case EdgePosition::L_2D:
1080 triangleId = getEdgeTriangle2dL(p.data(), localTriangleId);
1081 break;
1082 case EdgePosition::H_2D:
1083 triangleId = getEdgeTriangle2dH(p.data(), localTriangleId);
1084 break;
1085 case EdgePosition::D1_2D:
1086 triangleId = getEdgeTriangle2dD1(p.data(), localTriangleId);
1087 break;
1088 default:
1089 break;
1090 }
1091
1092 return 0;
1093}
1094
1095const vector<vector<SimplexId>> *
1097 if(edgeTriangleList_.empty()) {
1098 Timer t;
1099
1101 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1103 for(SimplexId j = 0; j < (SimplexId)edgeTriangleList_[i].size(); ++j)
1105 }
1106
1107 printMsg("Built " + to_string(edgeNumber_) + " edge triangles.", 1,
1108 t.getElapsedTime(), 1);
1109 }
1110
1111 return &edgeTriangleList_;
1112}
1113
1114SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1115 getEdgeLinkNumber)(const SimplexId &edgeId) const {
1116
1117 return getEdgeStarNumber(edgeId);
1118}
1119
1120template <typename Derived>
1122 getEdgeLink)(const SimplexId &edgeId,
1123 const int &localLinkId,
1124 SimplexId &linkId) const {
1125#ifndef TTK_ENABLE_KAMIKAZE
1126 if(localLinkId < 0 or localLinkId >= getEdgeLinkNumber(edgeId))
1127 return -1;
1128#endif
1129
1130 linkId = -1;
1131 const auto &p = this->underlying().getEdgeCoords(edgeId);
1132
1133 switch(this->underlying().getEdgePosition(edgeId)) {
1134 case EdgePosition::L_3D:
1135 linkId = getEdgeLinkL(p.data(), localLinkId);
1136 break;
1137 case EdgePosition::H_3D:
1138 linkId = getEdgeLinkH(p.data(), localLinkId);
1139 break;
1140 case EdgePosition::P_3D:
1141 linkId = getEdgeLinkP(p.data(), localLinkId);
1142 break;
1143 case EdgePosition::D1_3D:
1144 linkId = getEdgeLinkD1(p.data(), localLinkId);
1145 break;
1146 case EdgePosition::D2_3D:
1147 linkId = getEdgeLinkD2(p.data(), localLinkId);
1148 break;
1149 case EdgePosition::D3_3D:
1150 linkId = getEdgeLinkD3(p.data(), localLinkId);
1151 break;
1152 case EdgePosition::D4_3D:
1153 linkId = getEdgeLinkD4(p.data(), localLinkId);
1154 break;
1155 case EdgePosition::L_2D:
1156 linkId = getEdgeLink2dL(p.data(), localLinkId);
1157 break;
1158 case EdgePosition::H_2D:
1159 linkId = getEdgeLink2dH(p.data(), localLinkId);
1160 break;
1161 case EdgePosition::D1_2D:
1162 linkId = getEdgeLink2dD1(p.data(), localLinkId);
1163 break;
1164 default:
1165 break;
1166 }
1167
1168 return 0;
1169}
1170
1171const vector<vector<SimplexId>> *
1172 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdgeLinks)() {
1173
1174 if(edgeLinkList_.empty()) {
1175 Timer t;
1176
1177 edgeLinkList_.resize(edgeNumber_);
1178 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1179 edgeLinkList_[i].resize(getEdgeLinkNumber(i));
1180 for(SimplexId j = 0; j < (SimplexId)edgeLinkList_[i].size(); ++j)
1181 getEdgeLink(i, j, edgeLinkList_[i][j]);
1182 }
1183
1184 printMsg("Built " + to_string(edgeNumber_) + " edge links.", 1,
1185 t.getElapsedTime(), 1);
1186 }
1187
1188 return &edgeLinkList_;
1189}
1190
1191template <typename Derived>
1194 getEdgeStarNumber)(const SimplexId &edgeId) const {
1195#ifndef TTK_ENABLE_KAMIKAZE
1196 if(edgeId < 0 or edgeId >= edgeNumber_)
1197 return -1;
1198#endif
1199
1200 switch(this->underlying().getEdgePosition(edgeId)) {
1201 case EdgePosition::L_3D:
1202 case EdgePosition::H_3D:
1203 case EdgePosition::P_3D:
1204 case EdgePosition::D4_3D:
1205 return 6;
1206 case EdgePosition::D1_3D:
1207 case EdgePosition::D2_3D:
1208 case EdgePosition::D3_3D:
1209 return 4;
1210 case EdgePosition::L_2D:
1211 case EdgePosition::H_2D:
1212 case EdgePosition::D1_2D:
1213 return 2;
1214 default:
1215 return 0;
1216 }
1217
1218 return 0;
1219}
1220
1221template <typename Derived>
1223 getEdgeStar)(const SimplexId &edgeId,
1224 const int &localStarId,
1225 SimplexId &starId) const {
1226#ifndef TTK_ENABLE_KAMIKAZE
1227 if(localStarId < 0 or localStarId >= getEdgeStarNumber(edgeId))
1228 return -1;
1229#endif
1230
1231 starId = -1;
1232 const auto &p = this->underlying().getEdgeCoords(edgeId);
1233
1234 switch(this->underlying().getEdgePosition(edgeId)) {
1235 case EdgePosition::L_3D:
1236 starId = getEdgeStarL(p.data(), localStarId);
1237 break;
1238 case EdgePosition::H_3D:
1239 starId = getEdgeStarH(p.data(), localStarId);
1240 break;
1241 case EdgePosition::P_3D:
1242 starId = getEdgeStarP(p.data(), localStarId);
1243 break;
1244 case EdgePosition::D1_3D:
1245 starId = getEdgeStarD1(p.data(), localStarId);
1246 break;
1247 case EdgePosition::D2_3D:
1248 starId = getEdgeStarD2(p.data(), localStarId);
1249 break;
1250 case EdgePosition::D3_3D:
1251 starId = getEdgeStarD3(p.data(), localStarId);
1252 break;
1253 case EdgePosition::D4_3D:
1254 starId
1255 = p[2] * tetshift_[1] + p[1] * tetshift_[0] + p[0] * 6 + localStarId;
1256 break;
1257 case EdgePosition::L_2D:
1258 starId = getEdgeStar2dL(p.data(), localStarId);
1259 break;
1260 case EdgePosition::H_2D:
1261 starId = getEdgeStar2dH(p.data(), localStarId);
1262 break;
1263 case EdgePosition::D1_2D:
1264 starId = p[0] * 2 + p[1] * tshift_[0] + localStarId;
1265 break;
1266 default:
1267 break;
1268 }
1269
1270 return 0;
1271}
1272
1273const vector<vector<SimplexId>> *
1274 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdgeStars)() {
1275
1276 if(edgeStarList_.empty()) {
1277 Timer t;
1278
1279 edgeStarList_.resize(edgeNumber_);
1280 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1281 edgeStarList_[i].resize(getEdgeStarNumber(i));
1282 for(SimplexId j = 0; j < (SimplexId)edgeStarList_[i].size(); ++j)
1283 getEdgeStar(i, j, edgeStarList_[i][j]);
1284 }
1285
1286 printMsg("Built " + to_string(edgeNumber_) + " edge stars.", 1,
1287 t.getElapsedTime(), 1);
1288 }
1289
1290 return &edgeStarList_;
1291}
1292
1293template <typename Derived>
1295 const SimplexId &triangleId,
1296 const int &localVertexId,
1297 SimplexId &vertexId) const {
1298#ifndef TTK_ENABLE_KAMIKAZE
1299 if(triangleId < 0 or triangleId >= triangleNumber_)
1300 return -1;
1301 if(localVertexId < 0 or localVertexId >= 3)
1302 return -2;
1303#endif
1304
1305 vertexId = -1;
1306 const auto &p = this->underlying().getTriangleCoords(triangleId);
1307 const SimplexId wrapXRight = (p[0] / 2 == nbvoxels_[Di_]) ? -wrap_[0] : 0;
1308 const SimplexId wrapYBottom = (p[1] == nbvoxels_[Dj_]) ? -wrap_[1] : 0;
1309
1310 switch(this->underlying().getTrianglePosition(triangleId)) {
1311 case TrianglePosition::F_3D:
1312 vertexId = getTriangleVertexF(p.data(), localVertexId);
1313 break;
1314 case TrianglePosition::H_3D:
1315 vertexId = getTriangleVertexH(p.data(), localVertexId);
1316 break;
1317 case TrianglePosition::C_3D:
1318 vertexId = getTriangleVertexC(p.data(), localVertexId);
1319 break;
1320 case TrianglePosition::D1_3D:
1321 vertexId = getTriangleVertexD1(p.data(), localVertexId);
1322 break;
1323 case TrianglePosition::D2_3D:
1324 vertexId = getTriangleVertexD2(p.data(), localVertexId);
1325 break;
1326 case TrianglePosition::D3_3D:
1327 vertexId = getTriangleVertexD3(p.data(), localVertexId);
1328 break;
1329 case TrianglePosition::TOP_2D:
1330 if(localVertexId == 0) {
1331 vertexId = p[0] / 2 + p[1] * vshift_[0];
1332 } else if(localVertexId == 1) {
1333 vertexId = p[0] / 2 + p[1] * vshift_[0] + 1 + wrapXRight;
1334 } else if(localVertexId == 2) {
1335 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0] + wrapYBottom;
1336 }
1337 break;
1338 case TrianglePosition::BOTTOM_2D:
1339 if(localVertexId == 0) {
1340 vertexId = p[0] / 2 + p[1] * vshift_[0] + 1 + wrapXRight;
1341 } else if(localVertexId == 1) {
1342 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0] + 1 + wrapXRight
1343 + wrapYBottom;
1344 } else if(localVertexId == 2) {
1345 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0] + wrapYBottom;
1346 }
1347 break;
1348 default:
1349 break;
1350 }
1351
1352 return 0;
1353}
1354
1355template <typename Derived>
1357 const SimplexId &triangleId,
1358 const int &localEdgeId,
1359 SimplexId &edgeId) const {
1360#ifndef TTK_ENABLE_KAMIKAZE
1361 if(triangleId < 0 or triangleId >= triangleNumber_)
1362 return -1;
1363 if(localEdgeId < 0 or localEdgeId >= 3)
1364 return -2;
1365#endif
1366
1367 edgeId = -1;
1368 const auto &p = this->underlying().getTriangleCoords(triangleId);
1369 const SimplexId wrapXRight = (p[0] / 2 == nbvoxels_[Di_]) ? -wrap_[0] : 0;
1370 const SimplexId wrapYBottom = (p[1] == nbvoxels_[Dj_]) ? -wrap_[1] : 0;
1371 const SimplexId id = triangleId % 2;
1372
1373 switch(this->underlying().getTrianglePosition(triangleId)) {
1374 case TrianglePosition::F_3D:
1375 edgeId = (id == 1) ? getTriangleEdgeF_1(p.data(), localEdgeId)
1376 : getTriangleEdgeF_0(p.data(), localEdgeId);
1377 break;
1378 case TrianglePosition::H_3D:
1379 edgeId = (id == 1) ? getTriangleEdgeH_1(p.data(), localEdgeId)
1380 : getTriangleEdgeH_0(p.data(), localEdgeId);
1381 break;
1382 case TrianglePosition::C_3D:
1383 edgeId = (id == 1) ? getTriangleEdgeC_1(p.data(), localEdgeId)
1384 : getTriangleEdgeC_0(p.data(), localEdgeId);
1385 break;
1386 case TrianglePosition::D1_3D:
1387 edgeId = (id == 1) ? getTriangleEdgeD1_1(p.data(), localEdgeId)
1388 : getTriangleEdgeD1_0(p.data(), localEdgeId);
1389 break;
1390 case TrianglePosition::D2_3D:
1391 edgeId = (id == 1) ? getTriangleEdgeD2_1(p.data(), localEdgeId)
1392 : getTriangleEdgeD2_0(p.data(), localEdgeId);
1393 break;
1394 case TrianglePosition::D3_3D:
1395 edgeId = (id == 1) ? getTriangleEdgeD3_1(p.data(), localEdgeId)
1396 : getTriangleEdgeD3_0(p.data(), localEdgeId);
1397 break;
1398 case TrianglePosition::TOP_2D:
1399 if(localEdgeId == 0) {
1400 edgeId = p[0] / 2 + p[1] * eshift_[0];
1401 } else if(localEdgeId == 1) {
1402 edgeId = esetshift_[0] + p[0] / 2 + p[1] * eshift_[2];
1403 } else if(localEdgeId == 2) {
1404 edgeId = esetshift_[1] + p[0] / 2 + p[1] * eshift_[4];
1405 }
1406 break;
1407 case TrianglePosition::BOTTOM_2D:
1408 if(localEdgeId == 0) {
1409 edgeId = p[0] / 2 + (p[1] + 1) * eshift_[0] + wrapYBottom;
1410 } else if(localEdgeId == 1) {
1411 edgeId
1412 = esetshift_[0] + (p[0] + 1) / 2 + p[1] * eshift_[2] + wrapXRight;
1413 } else if(localEdgeId == 2) {
1414 edgeId = esetshift_[1] + p[0] / 2 + p[1] * eshift_[4];
1415 }
1416 break;
1417 default:
1418 break;
1419 }
1420
1421 return 0;
1422}
1423
1425 vector<vector<SimplexId>> &edges) const {
1426 edges.resize(triangleNumber_);
1427 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1428 edges[i].resize(3);
1429 for(int j = 0; j < 3; ++j)
1430 getTriangleEdgeInternal(i, j, edges[i][j]);
1431 }
1432 return 0;
1433}
1434
1435const vector<vector<SimplexId>> *
1437 if(triangleEdgeVector_.empty()) {
1438 Timer t;
1439
1441
1442 printMsg("Built " + to_string(triangleNumber_) + " triangle edges.", 1,
1443 t.getElapsedTime(), 1);
1444 }
1445
1446 return &triangleEdgeVector_;
1447}
1448
1449const vector<std::array<SimplexId, 3>> *
1450 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getTriangles)() {
1451
1452 if(triangleList_.empty()) {
1453 Timer t;
1454
1455 triangleList_.resize(triangleNumber_);
1456 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1457 for(int j = 0; j < 3; ++j)
1458 getTriangleVertexInternal(i, j, triangleList_[i][j]);
1459 }
1460
1461 printMsg("Built " + to_string(triangleNumber_) + " triangles.", 1,
1462 t.getElapsedTime(), 1);
1463 }
1464
1465 return &triangleList_;
1466}
1467
1468template <typename Derived>
1470 getTriangleLink)(const SimplexId &triangleId,
1471 const int &localLinkId,
1472 SimplexId &linkId) const {
1473#ifndef TTK_ENABLE_KAMIKAZE
1474 if(localLinkId < 0 or localLinkId >= getTriangleLinkNumber(triangleId))
1475 return -1;
1476#endif
1477
1478 linkId = -1;
1479 const auto &p = this->underlying().getTriangleCoords(triangleId);
1480
1481 switch(this->underlying().getTrianglePosition(triangleId)) {
1482 case TrianglePosition::F_3D:
1483 linkId = getTriangleLinkF(p.data(), localLinkId);
1484 break;
1485 case TrianglePosition::H_3D:
1486 linkId = getTriangleLinkH(p.data(), localLinkId);
1487 break;
1488 case TrianglePosition::C_3D:
1489 linkId = getTriangleLinkC(p.data(), localLinkId);
1490 break;
1491 case TrianglePosition::D1_3D:
1492 linkId = getTriangleLinkD1(p.data(), localLinkId);
1493 break;
1494 case TrianglePosition::D2_3D:
1495 linkId = getTriangleLinkD2(p.data(), localLinkId);
1496 break;
1497 case TrianglePosition::D3_3D:
1498 linkId = getTriangleLinkD3(p.data(), localLinkId);
1499 break;
1500 default:
1501 break;
1502 }
1503
1504 return 0;
1505}
1506
1507SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1508 getTriangleLinkNumber)(const SimplexId &triangleId) const {
1509
1510 return getTriangleStarNumber(triangleId);
1511}
1512
1513const vector<vector<SimplexId>> *
1514 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1515 getTriangleLinks)() {
1516
1517 if(triangleLinkList_.empty()) {
1518 Timer t;
1519
1520 triangleLinkList_.resize(triangleNumber_);
1521 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1522 triangleLinkList_[i].resize(getTriangleLinkNumber(i));
1523 for(SimplexId j = 0; j < (SimplexId)triangleLinkList_[i].size(); ++j)
1524 getTriangleLink(i, j, triangleLinkList_[i][j]);
1525 }
1526
1527 printMsg("Built " + to_string(triangleNumber_) + " triangle links.", 1,
1528 t.getElapsedTime(), 1);
1529 }
1530 return &triangleLinkList_;
1531}
1532
1533template <typename Derived>
1536 getTriangleStarNumber)(const SimplexId &triangleId) const {
1537#ifndef TTK_ENABLE_KAMIKAZE
1538 if(triangleId < 0 or triangleId >= triangleNumber_)
1539 return -1;
1540#else
1541 TTK_FORCE_USE(triangleId);
1542#endif
1543
1544 if(dimensionality_ == 3) {
1545 return 2;
1546 }
1547 return 0;
1548}
1549
1550template <typename Derived>
1552 getTriangleStar)(const SimplexId &triangleId,
1553 const int &localStarId,
1554 SimplexId &starId) const {
1555#ifndef TTK_ENABLE_KAMIKAZE
1556 if(localStarId < 0 or localStarId >= getTriangleStarNumber(triangleId))
1557 return -1;
1558#endif
1559
1560 starId = -1;
1561 const auto &p = this->underlying().getTriangleCoords(triangleId);
1562
1563 switch(this->underlying().getTrianglePosition(triangleId)) {
1564 case TrianglePosition::F_3D:
1565 starId = getTriangleStarF(p.data(), localStarId);
1566 break;
1567 case TrianglePosition::H_3D:
1568 starId = getTriangleStarH(p.data(), localStarId);
1569 break;
1570 case TrianglePosition::C_3D:
1571 starId = getTriangleStarC(p.data(), localStarId);
1572 break;
1573 case TrianglePosition::D1_3D:
1574 starId = getTriangleStarD1(p.data(), localStarId);
1575 break;
1576 case TrianglePosition::D2_3D:
1577 starId = getTriangleStarD2(p.data(), localStarId);
1578 break;
1579 case TrianglePosition::D3_3D:
1580 starId = getTriangleStarD3(p.data(), localStarId);
1581 break;
1582 default:
1583 break;
1584 }
1585
1586 return 0;
1587}
1588
1589const vector<vector<SimplexId>> *
1590 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1591 getTriangleStars)() {
1592
1593 if(triangleStarList_.empty()) {
1594 Timer t;
1595
1596 triangleStarList_.resize(triangleNumber_);
1597 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1598 triangleStarList_[i].resize(getTriangleStarNumber(i));
1599 for(SimplexId j = 0; j < (SimplexId)triangleStarList_[i].size(); ++j)
1600 getTriangleStar(i, j, triangleStarList_[i][j]);
1601 }
1602
1603 printMsg("Built " + to_string(triangleNumber_) + " triangle stars.", 1,
1604 t.getElapsedTime(), 1);
1605 }
1606 return &triangleStarList_;
1607}
1608
1610 const SimplexId &triangleId) const {
1611#ifndef TTK_ENABLE_KAMIKAZE
1612 if(triangleId < 0 or triangleId >= triangleNumber_)
1613 return -1;
1614#endif
1615
1616 TTK_FORCE_USE(triangleId);
1617 if(dimensionality_ == 2) {
1618 return 3;
1619 }
1620
1621 return 0;
1622}
1623
1624template <typename Derived>
1626 const SimplexId &triangleId,
1627 const int &localNeighborId,
1628 SimplexId &neighborId) const {
1629#ifndef TTK_ENABLE_KAMIKAZE
1630 if(localNeighborId < 0
1631 or localNeighborId >= getTriangleNeighborNumber(triangleId))
1632 return -1;
1633#endif
1634
1635 neighborId = -1;
1636 const auto &p = this->underlying().getTriangleCoords(triangleId);
1637
1638 switch(this->underlying().getTrianglePosition(triangleId)) {
1639 case TrianglePosition::BOTTOM_2D:
1640
1641 if(p[0] / 2 == nbvoxels_[Di_] and p[1] == nbvoxels_[Dj_]) {
1642 if(localNeighborId == 0) {
1643 neighborId = triangleId - 1;
1644 } else if(localNeighborId == 1) {
1645 neighborId = triangleId + 1 - wrap_[0] * 2;
1646 } else if(localNeighborId == 2) {
1647 neighborId = triangleId + tshift_[0] - 1 - wrap_[1] * 2;
1648 }
1649
1650 } else if(p[0] / 2 == nbvoxels_[Di_]) {
1651 if(localNeighborId == 0) {
1652 neighborId = triangleId - 1;
1653 } else if(localNeighborId == 1) {
1654 neighborId = triangleId + 1 - wrap_[0] * 2;
1655 } else if(localNeighborId == 2) {
1656 neighborId = triangleId + tshift_[0] - 1;
1657 }
1658
1659 } else if(p[1] == nbvoxels_[Dj_]) {
1660 if(localNeighborId == 0) {
1661 neighborId = triangleId - 1;
1662 } else if(localNeighborId == 1) {
1663 neighborId = triangleId + 1;
1664 } else if(localNeighborId == 2) {
1665 neighborId = triangleId + tshift_[0] - 1 - wrap_[1] * 2;
1666 }
1667
1668 } else {
1669 if(localNeighborId == 0) {
1670 neighborId = triangleId - 1;
1671 } else if(localNeighborId == 1) {
1672 neighborId = triangleId + 1;
1673 } else if(localNeighborId == 2) {
1674 neighborId = triangleId + tshift_[0] - 1;
1675 }
1676 }
1677 break;
1678
1679 case TrianglePosition::TOP_2D:
1680
1681 if(p[0] / 2 == 0 and p[1] == 0) {
1682 if(localNeighborId == 0) {
1683 neighborId = triangleId + 1;
1684 } else if(localNeighborId == 1) {
1685 neighborId = triangleId - 1 + wrap_[0] * 2;
1686 } else if(localNeighborId == 2) {
1687 neighborId = triangleId - tshift_[0] + 1 + wrap_[1] * 2;
1688 }
1689
1690 } else if(p[0] / 2 == 0) {
1691 if(localNeighborId == 0) {
1692 neighborId = triangleId + 1;
1693 } else if(localNeighborId == 1) {
1694 neighborId = triangleId - 1 + wrap_[0] * 2;
1695 } else if(localNeighborId == 2) {
1696 neighborId = triangleId - tshift_[0] + 1;
1697 }
1698
1699 } else if(p[1] == 0) {
1700 if(localNeighborId == 0) {
1701 neighborId = triangleId + 1;
1702 } else if(localNeighborId == 1) {
1703 neighborId = triangleId - 1;
1704 } else if(localNeighborId == 2) {
1705 neighborId = triangleId - tshift_[0] + 1 + wrap_[1] * 2;
1706 }
1707
1708 } else {
1709 if(localNeighborId == 0) {
1710 neighborId = triangleId + 1;
1711 } else if(localNeighborId == 1) {
1712 neighborId = triangleId - 1;
1713 } else if(localNeighborId == 2) {
1714 neighborId = triangleId - tshift_[0] + 1;
1715 }
1716 }
1717 break;
1718 default:
1719 break;
1720 }
1721
1722 return 0;
1723}
1724
1726 vector<vector<SimplexId>> &neighbors) {
1727 neighbors.resize(triangleNumber_);
1728 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1729 neighbors[i].resize(getTriangleNeighborNumber(i));
1730 for(SimplexId j = 0; j < (SimplexId)neighbors[i].size(); ++j)
1731 getTriangleNeighbor(i, j, neighbors[i][j]);
1732 }
1733 return 0;
1734}
1735
1736template <typename Derived>
1738 const SimplexId &tetId, const int &localVertexId, SimplexId &vertexId) const {
1739#ifndef TTK_ENABLE_KAMIKAZE
1740 if(tetId < 0 or tetId >= tetrahedronNumber_)
1741 return -1;
1742 if(localVertexId < 0 or localVertexId >= 4)
1743 return -2;
1744#endif
1745
1746 vertexId = -1;
1747
1748 if(dimensionality_ == 3) {
1749 const auto &p = this->underlying().getTetrahedronCoords(tetId);
1750 const SimplexId id = tetId % 6;
1751
1752 switch(id) {
1753 case 0:
1754 vertexId = getTetrahedronVertexABCG(p.data(), localVertexId);
1755 break;
1756 case 1:
1757 vertexId = getTetrahedronVertexBCDG(p.data(), localVertexId);
1758 break;
1759 case 2:
1760 vertexId = getTetrahedronVertexABEG(p.data(), localVertexId);
1761 break;
1762 case 3:
1763 vertexId = getTetrahedronVertexBEFG(p.data(), localVertexId);
1764 break;
1765 case 4:
1766 vertexId = getTetrahedronVertexBFGH(p.data(), localVertexId);
1767 break;
1768 case 5:
1769 vertexId = getTetrahedronVertexBDGH(p.data(), localVertexId);
1770 break;
1771 }
1772 }
1773 return 0;
1774}
1775
1776template <typename Derived>
1778 const SimplexId &tetId, const int &localEdgeId, SimplexId &edgeId) const {
1779#ifndef TTK_ENABLE_KAMIKAZE
1780 if(tetId < 0 or tetId >= tetrahedronNumber_)
1781 return -1;
1782 if(localEdgeId < 0 or localEdgeId >= 6)
1783 return -2;
1784#endif
1785
1786 edgeId = -1;
1787
1788 if(dimensionality_ == 3) {
1789 const auto &p = this->underlying().getTetrahedronCoords(tetId);
1790 const SimplexId id = tetId % 6;
1791
1792 switch(id) {
1793 case 0:
1794 edgeId = getTetrahedronEdgeABCG(p.data(), localEdgeId);
1795 break;
1796 case 1:
1797 edgeId = getTetrahedronEdgeBCDG(p.data(), localEdgeId);
1798 break;
1799 case 2:
1800 edgeId = getTetrahedronEdgeABEG(p.data(), localEdgeId);
1801 break;
1802 case 3:
1803 edgeId = getTetrahedronEdgeBEFG(p.data(), localEdgeId);
1804 break;
1805 case 4:
1806 edgeId = getTetrahedronEdgeBFGH(p.data(), localEdgeId);
1807 break;
1808 case 5:
1809 edgeId = getTetrahedronEdgeBDGH(p.data(), localEdgeId);
1810 break;
1811 }
1812 }
1813
1814 return 0;
1815}
1816
1818 vector<vector<SimplexId>> &edges) const {
1819 edges.resize(tetrahedronNumber_);
1820 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
1821 edges[i].resize(6);
1822 for(int j = 0; j < 6; ++j)
1823 getTetrahedronEdge(i, j, edges[i][j]);
1824 }
1825
1826 return 0;
1827}
1828
1829template <typename Derived>
1831 const SimplexId &tetId,
1832 const int &localTriangleId,
1833 SimplexId &triangleId) const {
1834#ifndef TTK_ENABLE_KAMIKAZE
1835 if(tetId < 0 or tetId >= tetrahedronNumber_)
1836 return -1;
1837 if(localTriangleId < 0 or localTriangleId >= 4)
1838 return -2;
1839#endif
1840
1841 triangleId = -1;
1842
1843 if(dimensionality_ == 3) {
1844 const auto &p = this->underlying().getTetrahedronCoords(tetId);
1845 const SimplexId id = tetId % 6;
1846
1847 switch(id) {
1848 case 0:
1849 triangleId = getTetrahedronTriangleABCG(p.data(), localTriangleId);
1850 break;
1851 case 1:
1852 triangleId = getTetrahedronTriangleBCDG(p.data(), localTriangleId);
1853 break;
1854 case 2:
1855 triangleId = getTetrahedronTriangleABEG(p.data(), localTriangleId);
1856 break;
1857 case 3:
1858 triangleId = getTetrahedronTriangleBEFG(p.data(), localTriangleId);
1859 break;
1860 case 4:
1861 triangleId = getTetrahedronTriangleBFGH(p.data(), localTriangleId);
1862 break;
1863 case 5:
1864 triangleId = getTetrahedronTriangleBDGH(p.data(), localTriangleId);
1865 break;
1866 }
1867 }
1868
1869 return 0;
1870}
1871
1873 vector<vector<SimplexId>> &triangles) const {
1874 triangles.resize(tetrahedronNumber_);
1875 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
1876 triangles[i].resize(4);
1877 for(int j = 0; j < 4; ++j)
1878 getTetrahedronTriangle(i, j, triangles[i][j]);
1879 }
1880
1881 return 0;
1882}
1883
1885 const SimplexId &tetId) const {
1886#ifndef TTK_ENABLE_KAMIKAZE
1887 if(tetId < 0 or tetId >= tetrahedronNumber_)
1888 return -1;
1889#endif
1890
1891 TTK_FORCE_USE(tetId);
1892 if(dimensionality_ == 3) {
1893 return 4;
1894 }
1895
1896 return 0;
1897}
1898
1899template <typename Derived>
1901 const SimplexId &tetId,
1902 const int &localNeighborId,
1903 SimplexId &neighborId) const {
1904#ifndef TTK_ENABLE_KAMIKAZE
1905 if(localNeighborId < 0
1906 or localNeighborId >= getTetrahedronNeighborNumber(tetId))
1907 return -1;
1908#endif
1909
1910 neighborId = -1;
1911
1912 if(dimensionality_ == 3) {
1913 const auto &p = this->underlying().getTetrahedronCoords(tetId);
1914 const SimplexId id = tetId % 6;
1915
1916 switch(id) {
1917 case 0:
1918 neighborId
1919 = getTetrahedronNeighborABCG(tetId, p.data(), localNeighborId);
1920 break;
1921 case 1:
1922 neighborId
1923 = getTetrahedronNeighborBCDG(tetId, p.data(), localNeighborId);
1924 break;
1925 case 2:
1926 neighborId
1927 = getTetrahedronNeighborABEG(tetId, p.data(), localNeighborId);
1928 break;
1929 case 3:
1930 neighborId
1931 = getTetrahedronNeighborBEFG(tetId, p.data(), localNeighborId);
1932 break;
1933 case 4:
1934 neighborId
1935 = getTetrahedronNeighborBFGH(tetId, p.data(), localNeighborId);
1936 break;
1937 case 5:
1938 neighborId
1939 = getTetrahedronNeighborBDGH(tetId, p.data(), localNeighborId);
1940 break;
1941 }
1942 }
1943
1944 return 0;
1945}
1946
1948 vector<vector<SimplexId>> &neighbors) {
1949 neighbors.resize(tetrahedronNumber_);
1950 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
1951 neighbors[i].resize(getTetrahedronNeighborNumber(i));
1952 for(SimplexId j = 0; j < (SimplexId)neighbors[i].size(); ++j)
1953 getTetrahedronNeighbor(i, j, neighbors[i][j]);
1954 }
1955
1956 return 0;
1957}
1958
1959SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1960 getCellVertexNumber)(const SimplexId &ttkNotUsed(cellId)) const {
1961
1962 return dimensionality_ + 1;
1963}
1964
1965int PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getCellVertex)(
1966 const SimplexId &cellId,
1967 const int &localVertexId,
1968 SimplexId &vertexId) const {
1969
1970 if(dimensionality_ == 3)
1971 getTetrahedronVertex(cellId, localVertexId, vertexId);
1972 else if(dimensionality_ == 2)
1973 getTriangleVertexInternal(cellId, localVertexId, vertexId);
1974 else if(dimensionality_ == 1)
1975 getEdgeVertexInternal(cellId, localVertexId, vertexId);
1976
1977 return 0;
1978}
1979
1981 const SimplexId &ttkNotUsed(cellId)) const {
1982 if(dimensionality_ == 3)
1983 return 6;
1984 else if(dimensionality_ == 2)
1985 return 3;
1986
1987 return 0;
1988}
1989
1991 const SimplexId &cellId, const int &localEdgeId, SimplexId &edgeId) const {
1992 if(dimensionality_ == 3)
1993 getTetrahedronEdge(cellId, localEdgeId, edgeId);
1994 else if(dimensionality_ == 2)
1995 getTriangleEdgeInternal(cellId, localEdgeId, edgeId);
1996 else if(dimensionality_ == 1)
1997 getCellNeighbor(cellId, localEdgeId, edgeId);
1998
1999 return 0;
2000}
2001
2002const vector<vector<SimplexId>> *
2004 if(cellEdgeVector_.empty()) {
2005 Timer t;
2006
2007 if(dimensionality_ == 3)
2009 else if(dimensionality_ == 2)
2011
2012 printMsg("Built " + to_string(cellNumber_) + " cell edges.", 1,
2013 t.getElapsedTime(), 1);
2014 }
2015
2016 return &cellEdgeVector_;
2017}
2018
2020 const SimplexId &cellId,
2021 const int &localTriangleId,
2022 SimplexId &triangleId) const {
2023 if(dimensionality_ == 3)
2024 getTetrahedronTriangle(cellId, localTriangleId, triangleId);
2025
2026 return 0;
2027}
2028
2029const vector<vector<SimplexId>> *
2031 if(cellTriangleVector_.empty()) {
2032 Timer t;
2033
2034 if(dimensionality_ == 3)
2036
2037 printMsg("Built " + to_string(cellNumber_) + " cell triangles.", 1,
2038 t.getElapsedTime(), 1);
2039 }
2040
2041 return &cellTriangleVector_;
2042}
2043
2044SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
2045 getCellNeighborNumber)(const SimplexId &cellId) const {
2046
2047 if(dimensionality_ == 3)
2048 return getTetrahedronNeighborNumber(cellId);
2049 else if(dimensionality_ == 2)
2050 return getTriangleNeighborNumber(cellId);
2051 else if(dimensionality_ == 1) {
2052 printErr("getCellNeighborNumber() not implemented in 1D! (TODO)");
2053 return -1;
2054 }
2055
2056 return 0;
2057}
2058
2059int PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getCellNeighbor)(
2060 const SimplexId &cellId,
2061 const int &localNeighborId,
2062 SimplexId &neighborId) const {
2063
2064 if(dimensionality_ == 3)
2065 getTetrahedronNeighbor(cellId, localNeighborId, neighborId);
2066 else if(dimensionality_ == 2)
2067 getTriangleNeighbor(cellId, localNeighborId, neighborId);
2068 else if(dimensionality_ == 1) {
2069 printErr("getCellNeighbor() not implemented in 1D! (TODO)");
2070 return -1;
2071 }
2072
2073 return 0;
2074}
2075
2076const vector<vector<SimplexId>> *
2077 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
2078 getCellNeighbors)() {
2079
2080 if(cellNeighborList_.empty()) {
2081 Timer t;
2082
2083 if(dimensionality_ == 3)
2084 getTetrahedronNeighbors(cellNeighborList_);
2085 else if(dimensionality_ == 2)
2086 getTriangleNeighbors(cellNeighborList_);
2087 else if(dimensionality_ == 1) {
2088 printErr("getCellNeighbors() not implemented in 1D! (TODO)");
2089 return nullptr;
2090 }
2091
2092 printMsg("Built " + to_string(cellNumber_) + " cell neighbors.", 1,
2093 t.getElapsedTime(), 1);
2094 }
2095
2096 return &cellNeighborList_;
2097}
2098
2099// explicit instantiations
#define TTK_FORCE_USE(x)
Force the compiler to use the function/method parameter.
Definition: BaseClass.h:57
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition: BaseClass.h:47
bool ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() isTriangleOnBoundary(const SimplexId &triangleId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getEdgeStar(const SimplexId &edgeId, const int &localStarId, SimplexId &starId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellNeighbors()
SimplexId ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getTriangleStarNumber(const SimplexId &triangleId) const
int ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellNeighbor(const SimplexId &cellId, const int &localNeighborId, SimplexId &neighborId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexStar(const SimplexId &vertexId, const int &localStarId, SimplexId &starId) const
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getTriangleLinkNumber(const SimplexId &triangleId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getEdgeLink(const SimplexId &edgeId, const int &localLinkId, SimplexId &linkId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getTriangleLink(const SimplexId &triangleId, const int &localLinkId, SimplexId &linkId) const
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellVertexNumber(const SimplexId &) const
SimplexId ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getEdgeStarNumber(const SimplexId &edgeId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexNeighbor(const SimplexId &vertexId, const int &localNeighborId, SimplexId &neighborId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getTriangleLinks()
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getTriangleStars()
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexLinkNumber(const SimplexId &vertexId) const
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellNeighborNumber(const SimplexId &cellId) const
SimplexId ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexStarNumber(const SimplexId &vertexId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexLinks()
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getEdgeStars()
bool ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() isEdgeOnBoundary(const SimplexId &edgeId) const
int ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellVertex(const SimplexId &cellId, const int &localVertexId, SimplexId &vertexId) const
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getEdgeLinkNumber(const SimplexId &edgeId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexNeighbors()
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getTriangleStar(const SimplexId &triangleId, const int &localStarId, SimplexId &starId) const
const vector< std::array< SimplexId, 3 > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getTriangles()
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexStars()
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexPoint(const SimplexId &vertexId, float &x, float &y, float &z) const
const vector< std::array< SimplexId, 2 > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getEdges()
bool ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() isVertexOnBoundary(const SimplexId &vertexId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexLink(const SimplexId &vertexId, const int &localLinkId, SimplexId &linkId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getEdgeLinks()
SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexNeighborNumber(const SimplexId &vertexId) const
virtual int getVertexTriangleInternal(const SimplexId &ttkNotUsed(vertexId), const int &ttkNotUsed(localTriangleId), SimplexId &ttkNotUsed(triangleId)) const
std::vector< std::vector< SimplexId > > vertexEdgeList_
std::vector< std::vector< SimplexId > > triangleEdgeVector_
virtual int getTriangleEdgeInternal(const SimplexId &ttkNotUsed(triangleId), const int &ttkNotUsed(localEdgeId), SimplexId &ttkNotUsed(edgeId)) const
virtual SimplexId getEdgeTriangleNumberInternal(const SimplexId &ttkNotUsed(edgeId)) const
virtual int getEdgeTriangleInternal(const SimplexId &ttkNotUsed(edgeId), const int &ttkNotUsed(localTriangleId), SimplexId &ttkNotUsed(triangleId)) const
virtual int getVertexEdgeInternal(const SimplexId &ttkNotUsed(vertexId), const int &ttkNotUsed(localEdgeId), SimplexId &ttkNotUsed(edgeId)) const
std::vector< std::vector< SimplexId > > vertexTriangleList_
std::vector< std::vector< SimplexId > > cellEdgeVector_
std::vector< std::vector< SimplexId > > cellTriangleVector_
std::vector< std::vector< SimplexId > > edgeTriangleList_
void setDebugMsgPrefix(const std::string &prefix)
Definition: Debug.h:364
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
Definition: Debug.h:118
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition: Debug.h:149
int getTetrahedronVertex(const SimplexId &tetId, const int &localVertexId, SimplexId &vertexId) const override
int getTetrahedronTriangle(const SimplexId &tetId, const int &id, SimplexId &triangleId) const override
int getTriangleVertexInternal(const SimplexId &triangleId, const int &localVertexId, SimplexId &vertexId) const override
int getEdgeVertexInternal(const SimplexId &edgeId, const int &localVertexId, SimplexId &vertexId) const override
int getVertexTriangleInternal(const SimplexId &vertexId, const int &id, SimplexId &triangleId) const override
int getTriangleEdgeInternal(const SimplexId &triangleId, const int &id, SimplexId &edgeId) const override
int getTetrahedronNeighbor(const SimplexId &tetId, const int &localNeighborId, SimplexId &neighborId) const override
int getVertexEdgeInternal(const SimplexId &vertexId, const int &id, SimplexId &edgeId) const override
SimplexId getEdgeTriangleNumberInternal(const SimplexId &edgeId) const override
int getEdgeTriangleInternal(const SimplexId &edgeId, const int &id, SimplexId &triangleId) const override
int getTetrahedronEdge(const SimplexId &tetId, const int &id, SimplexId &edgeId) const override
int getTriangleNeighbor(const SimplexId &triangleId, const int &localNeighborId, SimplexId &neighborId) const override
int getTriangleNeighbors(std::vector< std::vector< SimplexId > > &neighbors)
virtual int getTetrahedronNeighbor(const SimplexId &tetId, const int &localNeighborId, SimplexId &neighborId) const =0
int getCellTriangleInternal(const SimplexId &cellId, const int &id, SimplexId &triangleId) const override
int setInputGrid(const float &xOrigin, const float &yOrigin, const float &zOrigin, const float &xSpacing, const float &ySpacing, const float &zSpacing, const SimplexId &xDim, const SimplexId &yDim, const SimplexId &zDim) override
const std::vector< std::vector< SimplexId > > * getTriangleEdgesInternal() override
int getTetrahedronNeighbors(std::vector< std::vector< SimplexId > > &neighbors)
SimplexId getVertexEdgeNumberInternal(const SimplexId &vertexId) const override
SimplexId getCellEdgeNumberInternal(const SimplexId &cellId) const override
int getTetrahedronEdges(std::vector< std::vector< SimplexId > > &edges) const
SimplexId getTriangleNeighborNumber(const SimplexId &triangleId) const
const std::array< ttk::SimplexId, 3 > & getGridDimensions() const override
const std::vector< std::vector< SimplexId > > * getEdgeTrianglesInternal() override
virtual int getTriangleNeighbor(const SimplexId &triangleId, const int &localNeighborId, SimplexId &neighborId) const =0
bool isPowerOfTwo(unsigned long long int v, unsigned long long int &r)
virtual int getTetrahedronEdge(const SimplexId &tetId, const int &id, SimplexId &edgeId) const =0
virtual int getTetrahedronTriangle(const SimplexId &tetId, const int &id, SimplexId &triangleId) const =0
const std::vector< std::vector< SimplexId > > * getVertexEdgesInternal() override
SimplexId getVertexTriangleNumberInternal(const SimplexId &vertexId) const override
int getTetrahedronTriangles(std::vector< std::vector< SimplexId > > &triangles) const
const std::vector< std::vector< SimplexId > > * getCellEdgesInternal() override
int getCellEdgeInternal(const SimplexId &cellId, const int &id, SimplexId &edgeId) const override
SimplexId getTetrahedronNeighborNumber(const SimplexId &tetId) const
SimplexId TTK_TRIANGULATION_INTERNAL() getVertexNeighborNumber(const SimplexId &vertexId) const override
int TTK_TRIANGULATION_INTERNAL() getCellNeighbor(const SimplexId &cellId, const int &localNeighborId, SimplexId &neighborId) const override
const std::vector< std::vector< SimplexId > > * getCellTrianglesInternal() override
const std::vector< std::vector< SimplexId > > * getVertexTrianglesInternal() override
Periodic implicit Triangulation class without preconditioning.
Periodic implicit Triangulation class with preconditioning.
virtual void tetrahedronToPosition(const SimplexId tetrahedron, SimplexId p[3]) const =0
virtual void vertexToPosition(const SimplexId vertex, SimplexId p[3]) const =0
virtual void triangleToPosition2d(const SimplexId triangle, SimplexId p[2]) const =0
std::array< SimplexId, 3 > dimensions_
virtual void vertexToPosition2d(const SimplexId vertex, SimplexId p[2]) const =0
double getElapsedTime()
Definition: Timer.h:15
The Topology ToolKit.
COMMON_EXPORTS int MPIsize_
Definition: BaseClass.cpp:10
COMMON_EXPORTS int MPIrank_
Definition: BaseClass.cpp:9
int SimplexId
Identifier type for simplices of any dimension.
Definition: DataTypes.h:22
printMsg(debug::output::GREEN+"                           "+debug::output::ENDCOLOR+debug::output::GREEN+"▒"+debug::output::ENDCOLOR+debug::output::GREEN+"▒▒▒▒▒▒▒▒▒▒▒▒▒░"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)