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 const isDi = isPowerOfTwo(dimensions_[Di_], msb[Di_]);
204 bool const isDj = isPowerOfTwo(dimensions_[Dj_], msb[Dj_]);
205 bool const 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
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 ttk::SimplexId localBBox_x_min{this->localGridOffset_[0]
672 + this->dimensions_[0]},
673 localBBox_y_min{this->localGridOffset_[1] + this->dimensions_[1]},
674 localBBox_z_min{this->localGridOffset_[2] + this->dimensions_[2]};
675 ttk::SimplexId localBBox_x_max{this->localGridOffset_[0]},
676 localBBox_y_max{this->localGridOffset_[1]},
677 localBBox_z_max{this->localGridOffset_[2]};
678 const auto &dims{this->metaGrid_->getGridDimensions()};
679#ifdef TTK_ENABLE_OPENMP
680#pragma omp parallel for reduction( \
681 min \
682 : localBBox_x_min, localBBox_y_min, localBBox_z_min) \
683 reduction(max \
684 : localBBox_x_max, localBBox_y_max, localBBox_z_max)
685#endif
686 for(SimplexId lcid = 0; lcid < nLocCells; ++lcid) {
687 // only keep non-ghost cells
688 if(this->cellGhost_[lcid / nTetraPerCube] != 0) {
689 continue;
690 }
691 // local vertex coordinates
692 std::array<SimplexId, 3> p{};
693 if(this->dimensionality_ == 3) {
694 this->tetrahedronToPosition(lcid, p.data());
695 } else if(this->dimensionality_ == 2) {
696 this->triangleToPosition2d(lcid, p.data());
697 // compatibility with tetrahedronToPosition; fix a bounding box
698 // error in the first axis
699 p[0] /= 2;
700 }
701
702 // global vertex coordinates
703 p[0] += this->localGridOffset_[0];
704 p[1] += this->localGridOffset_[1];
705 p[2] += this->localGridOffset_[2];
706
707 if(p[0] < localBBox_x_min) {
708 localBBox_x_min = max(p[0], static_cast<ttk::SimplexId>(0));
709 }
710 if(p[0] > localBBox_x_max) {
711 localBBox_x_max = min(p[0], dims[0]);
712 }
713 if(p[1] < localBBox_y_min) {
714 localBBox_y_min = max(p[1], static_cast<ttk::SimplexId>(0));
715 }
716 if(p[1] > localBBox_y_max) {
717 localBBox_y_max = min(p[1], dims[1]);
718 }
719 if(p[2] < localBBox_z_min) {
720 localBBox_z_min = max(p[2], static_cast<ttk::SimplexId>(0));
721 }
722 if(p[2] > localBBox_z_max) {
723 localBBox_z_max = min(p[2], dims[2]);
724 }
725 }
726 localBBox_x_min -= isBoundaryPeriodic[0];
727 if(dimensionality_ > 1) {
728 localBBox_y_min -= isBoundaryPeriodic[2];
729 if(dimensionality_ > 2)
730 localBBox_z_min -= isBoundaryPeriodic[4];
731 }
732
733 localBBox_x_max++;
734 localBBox_y_max++;
735 localBBox_z_max++;
736
737 localBBox = {
738 localBBox_x_min, localBBox_x_max, localBBox_y_min,
739 localBBox_y_max, localBBox_z_min, localBBox_z_max,
740 };
741
742 for(size_t i = 0; i < this->neighborRanks_.size(); ++i) {
743 const auto neigh{this->neighborRanks_[i]};
744 MPI_Sendrecv(this->neighborCellBBoxes_[ttk::MPIrank_].data(), 6,
745 ttk::getMPIType(SimplexId{}), neigh, ttk::MPIrank_,
746 this->neighborCellBBoxes_[neigh].data(), 6,
747 ttk::getMPIType(SimplexId{}), neigh, neigh, ttk::MPIcomm_,
748 MPI_STATUS_IGNORE);
749 }
750
751 this->hasPreconditionedDistributedCells_ = true;
752
753 return 0;
754}
755
756std::array<SimplexId, 3> PeriodicImplicitTriangulation::getVertGlobalCoords(
757 const SimplexId lvid) const {
758 // local vertex coordinates
759 std::array<SimplexId, 3> p{};
760 if(this->dimensionality_ == 3) {
761 this->vertexToPosition(lvid, p.data());
762 } else if(this->dimensionality_ == 2) {
763 this->vertexToPosition2d(lvid, p.data());
764 }
765 // global vertex coordinates
766 p[0] += this->localGridOffset_[0];
767 p[1] += this->localGridOffset_[1];
768 p[2] += this->localGridOffset_[2];
769
770 const auto &dims{this->metaGrid_->getGridDimensions()};
771
772 p[0] = (p[0] + dims[0]) % dims[0];
773 if(dimensionality_ > 1) {
774 p[1] = (p[1] + dims[1]) % dims[1];
775 if(dimensionality_ > 2)
776 p[2] = (p[2] + dims[2]) % dims[2];
777 }
778
779 return p;
780}
781
782std::array<SimplexId, 3> PeriodicImplicitTriangulation::getVertLocalCoords(
783 const SimplexId gvid) const {
784 // global vertex coordinates
785 std::array<SimplexId, 3> pGlobal{};
786 if(this->dimensionality_ == 3) {
787 this->metaGrid_->vertexToPosition(gvid, pGlobal.data());
788 } else if(this->dimensionality_ == 2) {
789 this->metaGrid_->vertexToPosition2d(gvid, pGlobal.data());
790 }
791 std::array<SimplexId, 3> p{pGlobal};
792 // local vertex coordinates
793 p[0] -= this->localGridOffset_[0];
794 p[1] -= this->localGridOffset_[1];
795 p[2] -= this->localGridOffset_[2];
796
797 const auto &dims{this->getGridDimensions()};
798
799 if(p[0] >= 0 && p[1] >= 0 && p[2] >= 0 && p[0] <= dims[0] - 1
800 && p[1] <= dims[1] - 1 && p[2] <= dims[2] - 1) {
801 return p;
802 }
803 for(int i = 0; i < 3; i++) {
804 if((p[i] < 0 || p[i] > dims[i] - 1) && pGlobal[i] == 0) {
805 p[i] = dims[i] - 1;
806 }
807 if((p[i] < 0 || p[i] > dims[i] - 1)
808 && pGlobal[i] == this->metaGrid_->dimensions_[i] - 1) {
809 p[i] = 0;
810 }
811 }
812
813 if(p[0] >= 0 && p[1] >= 0 && p[2] >= 0 && p[0] <= dims[0] - 1
814 && p[1] <= dims[1] - 1 && p[2] <= dims[2] - 1) {
815 if(this->vertexGhost_[p[0] + p[1] * dims[0] + p[2] * dims[0] * dims[1]]
816 != 0) {
817 return p;
818 }
819 }
820 return std::array<SimplexId, 3>{-1, -1, -1};
821}
822
823int ttk::PeriodicImplicitTriangulation::getCellRankInternal(
824 const SimplexId lcid) const {
825
826 const int nTetraPerCube{this->dimensionality_ == 3 ? 6 : 2};
827 const auto locCubeId{lcid / nTetraPerCube};
828
829 if(this->cellGhost_[locCubeId] == 0) {
830 return ttk::MPIrank_;
831 }
832
833#ifndef TTK_ENABLE_KAMIKAZE
834 if(this->neighborRanks_.empty()) {
835 this->printErr("Empty neighborsRanks_!");
836 return -1;
837 }
838#endif // TTK_ENABLE_KAMIKAZE
839
840 const auto nVertsCell{this->getCellVertexNumber(lcid)};
841 std::vector<bool> inRank(nVertsCell);
842 std::map<int, int> neighborOccurrences;
843 for(const auto neigh : this->neighborRanks_) {
844 std::fill(inRank.begin(), inRank.end(), false);
845 const auto &bbox{this->neighborCellBBoxes_[neigh]};
846 for(SimplexId i = 0; i < nVertsCell; ++i) {
847 SimplexId v{};
848 this->getCellVertex(lcid, i, v);
849 if(this->vertexGhost_[v] == 0) {
850 inRank[i] = true;
851 } else {
852 const auto p{this->getVertGlobalCoords(v)};
853 if(p[0] >= bbox[0] && p[0] <= bbox[1] && p[1] >= bbox[2]
854 && p[1] <= bbox[3] && p[2] >= bbox[4] && p[2] <= bbox[5]) {
855 inRank[i] = true;
856 }
857 }
858 }
859 if(std::all_of(
860 inRank.begin(), inRank.end(), [](const bool v) { return v; })) {
861 return neigh;
862 }
863 neighborOccurrences[neigh]
864 = std::accumulate(inRank.begin(), inRank.end(), 0);
865 }
866
867 auto pr = std::max_element(
868 std::begin(neighborOccurrences), std::end(neighborOccurrences),
869 [](const std::pair<int, int> &p1, const std::pair<int, int> &p2) {
870 return p1.second < p2.second;
871 });
872 return pr->first;
873}
874
875#endif // TTK_ENABLE_MPI
876
877template <typename Derived>
879 getVertexPoint)(const SimplexId &vertexId,
880 float &x,
881 float &y,
882 float &z) const {
883#ifndef TTK_ENABLE_KAMIKAZE
884 if(vertexId < 0 or vertexId >= vertexNumber_)
885 return -1;
886#endif
887
888 if(dimensionality_ == 3) {
889 const auto &p = this->underlying().getVertexCoords(vertexId);
890
891 x = origin_[0] + spacing_[0] * p[0];
892 y = origin_[1] + spacing_[1] * p[1];
893 z = origin_[2] + spacing_[2] * p[2];
894 } else if(dimensionality_ == 2) {
895 const auto &p = this->underlying().getVertexCoords(vertexId);
896
897 if(dimensions_[0] > 1 and dimensions_[1] > 1) {
898 x = origin_[0] + spacing_[0] * p[0];
899 y = origin_[1] + spacing_[1] * p[1];
900 z = origin_[2];
901 } else if(dimensions_[1] > 1 and dimensions_[2] > 1) {
902 x = origin_[0];
903 y = origin_[1] + spacing_[1] * p[0];
904 z = origin_[2] + spacing_[2] * p[1];
905 } else if(dimensions_[0] > 1 and dimensions_[2] > 1) {
906 x = origin_[0] + spacing_[0] * p[0];
907 y = origin_[1];
908 z = origin_[2] + spacing_[2] * p[1];
909 }
910 } else if(dimensionality_ == 1) {
911 if(dimensions_[0] > 1) {
912 x = origin_[0] + spacing_[0] * vertexId;
913 y = origin_[1];
914 z = origin_[2];
915 } else if(dimensions_[1] > 1) {
916 x = origin_[0];
917 y = origin_[1] + spacing_[1] * vertexId;
918 z = origin_[2];
919 } else if(dimensions_[2] > 1) {
920 x = origin_[0];
921 y = origin_[1];
922 z = origin_[2] + spacing_[2] * vertexId;
923 }
924 }
925
926 return 0;
927}
928
929template <typename Derived>
931 const SimplexId &edgeId,
932 const int &localVertexId,
933 SimplexId &vertexId) const {
934#ifndef TTK_ENABLE_KAMIKAZE
935 if(edgeId < 0 or edgeId >= edgeNumber_)
936 return -1;
937 if(localVertexId < 0 or localVertexId >= 2)
938 return -2;
939#endif
940
941 vertexId = -1;
942 const auto &p = this->underlying().getEdgeCoords(edgeId);
943 const SimplexId wrapXRight = (p[0] == nbvoxels_[0] ? -wrap_[0] : 0);
944 const SimplexId wrapYBottom = (p[1] == nbvoxels_[1] ? -wrap_[1] : 0);
945 const SimplexId wrapZFront = (p[2] == nbvoxels_[2] ? -wrap_[2] : 0);
946 const auto a = p[0] + this->underlying().getEdgeVertexAccelerated(edgeId);
947
948 switch(this->underlying().getEdgePosition(edgeId)) {
949 case EdgePosition::L_3D:
950 vertexId = a + (localVertexId == 0 ? 0 : (1 + wrapXRight));
951 break;
952 case EdgePosition::H_3D:
953 vertexId = a + (localVertexId == 0 ? 0 : (vshift_[0] + wrapYBottom));
954 break;
955 case EdgePosition::P_3D:
956 vertexId = a + (localVertexId == 0 ? 0 : (vshift_[1] + wrapZFront));
957 break;
958 case EdgePosition::D1_3D:
959 vertexId = a
960 + (localVertexId == 0 ? (1 + wrapXRight)
961 : (vshift_[0] + wrapYBottom));
962 break;
963 case EdgePosition::D2_3D:
964 vertexId = a
965 + (localVertexId == 0
966 ? 0
967 : (vshift_[0] + wrapYBottom + vshift_[1] + wrapZFront));
968 break;
969 case EdgePosition::D3_3D:
970 vertexId
971 = a
972 + (localVertexId == 0 ? (1 + wrapXRight) : (vshift_[1] + wrapZFront));
973 break;
974 case EdgePosition::D4_3D:
975 vertexId = a
976 + (localVertexId == 0
977 ? (1 + wrapXRight)
978 : (vshift_[0] + wrapYBottom + vshift_[1] + wrapZFront));
979 break;
980 case EdgePosition::L_2D:
981 vertexId = a + (localVertexId == 0 ? 0 : (1 + wrapXRight));
982 break;
983 case EdgePosition::H_2D:
984 vertexId = a + (localVertexId == 0 ? 0 : (vshift_[0] + wrapYBottom));
985 break;
986 case EdgePosition::D1_2D:
987 vertexId = a
988 + (localVertexId == 0 ? (1 + wrapXRight)
989 : (vshift_[0] + wrapYBottom));
990 break;
991 case EdgePosition::FIRST_EDGE_1D:
992 vertexId = localVertexId == 0 ? 0 : 1;
993 break;
994 case EdgePosition::LAST_EDGE_1D:
995 vertexId = localVertexId == 0 ? edgeId : 0;
996 break;
997 case EdgePosition::CENTER_1D:
998 vertexId = localVertexId == 0 ? edgeId : edgeId + 1;
999 break;
1000 default:
1001 break;
1002 }
1003
1004 return 0;
1005}
1006
1007const vector<std::array<SimplexId, 2>> *
1008 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdges)() {
1009
1010 if(edgeList_.empty()) {
1011 Timer t;
1012
1013 edgeList_.resize(edgeNumber_);
1014 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1015 SimplexId id0, id1;
1016 getEdgeVertexInternal(i, 0, id0);
1017 getEdgeVertexInternal(i, 1, id1);
1018 edgeList_[i] = {id0, id1};
1019 }
1020
1021 printMsg(
1022 "Built " + to_string(edgeNumber_) + " edges.", 1, t.getElapsedTime(), 1);
1023 }
1024
1025 return &edgeList_;
1026}
1027
1028template <typename Derived>
1031 const SimplexId &edgeId) const {
1032#ifndef TTK_ENABLE_KAMIKAZE
1033 if(edgeId < 0 or edgeId >= edgeNumber_)
1034 return -1;
1035#endif
1036
1037 switch(this->underlying().getEdgePosition(edgeId)) {
1038 case EdgePosition::L_3D:
1039 case EdgePosition::H_3D:
1040 case EdgePosition::P_3D:
1041 case EdgePosition::D4_3D:
1042 return 6;
1043 case EdgePosition::D1_3D:
1044 case EdgePosition::D2_3D:
1045 case EdgePosition::D3_3D:
1046 return 4;
1047 case EdgePosition::L_2D:
1048 case EdgePosition::H_2D:
1049 case EdgePosition::D1_2D:
1050 return 2;
1051 default:
1052 return 0;
1053 }
1054}
1055
1056template <typename Derived>
1058 const SimplexId &edgeId,
1059 const int &localTriangleId,
1060 SimplexId &triangleId) const {
1061#ifndef TTK_ENABLE_KAMIKAZE
1062 if(localTriangleId < 0
1063 or localTriangleId >= getEdgeTriangleNumberInternal(edgeId))
1064 return -1;
1065#endif
1066
1067 triangleId = -1;
1068 const auto &p = this->underlying().getEdgeCoords(edgeId);
1069
1070 switch(this->underlying().getEdgePosition(edgeId)) {
1071 case EdgePosition::L_3D:
1072 triangleId = getEdgeTriangle3dL(p.data(), localTriangleId);
1073 break;
1074 case EdgePosition::H_3D:
1075 triangleId = getEdgeTriangle3dH(p.data(), localTriangleId);
1076 break;
1077 case EdgePosition::P_3D:
1078 triangleId = getEdgeTriangle3dP(p.data(), localTriangleId);
1079 break;
1080 case EdgePosition::D1_3D:
1081 triangleId = getEdgeTriangle3dD1(p.data(), localTriangleId);
1082 break;
1083 case EdgePosition::D2_3D:
1084 triangleId = getEdgeTriangle3dD2(p.data(), localTriangleId);
1085 break;
1086 case EdgePosition::D3_3D:
1087 triangleId = getEdgeTriangle3dD3(p.data(), localTriangleId);
1088 break;
1089 case EdgePosition::D4_3D:
1090 triangleId = getEdgeTriangle3dD4(p.data(), localTriangleId);
1091 break;
1092 case EdgePosition::L_2D:
1093 triangleId = getEdgeTriangle2dL(p.data(), localTriangleId);
1094 break;
1095 case EdgePosition::H_2D:
1096 triangleId = getEdgeTriangle2dH(p.data(), localTriangleId);
1097 break;
1098 case EdgePosition::D1_2D:
1099 triangleId = getEdgeTriangle2dD1(p.data(), localTriangleId);
1100 break;
1101 default:
1102 break;
1103 }
1104
1105 return 0;
1106}
1107
1108const vector<vector<SimplexId>> *
1110 if(edgeTriangleList_.empty()) {
1111 Timer t;
1112
1114 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1116 for(SimplexId j = 0; j < (SimplexId)edgeTriangleList_[i].size(); ++j)
1118 }
1119
1120 printMsg("Built " + to_string(edgeNumber_) + " edge triangles.", 1,
1121 t.getElapsedTime(), 1);
1122 }
1123
1124 return &edgeTriangleList_;
1125}
1126
1127SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1128 getEdgeLinkNumber)(const SimplexId &edgeId) const {
1129
1130 return getEdgeStarNumber(edgeId);
1131}
1132
1133template <typename Derived>
1135 getEdgeLink)(const SimplexId &edgeId,
1136 const int &localLinkId,
1137 SimplexId &linkId) const {
1138#ifndef TTK_ENABLE_KAMIKAZE
1139 if(localLinkId < 0 or localLinkId >= getEdgeLinkNumber(edgeId))
1140 return -1;
1141#endif
1142
1143 linkId = -1;
1144 const auto &p = this->underlying().getEdgeCoords(edgeId);
1145
1146 switch(this->underlying().getEdgePosition(edgeId)) {
1147 case EdgePosition::L_3D:
1148 linkId = getEdgeLinkL(p.data(), localLinkId);
1149 break;
1150 case EdgePosition::H_3D:
1151 linkId = getEdgeLinkH(p.data(), localLinkId);
1152 break;
1153 case EdgePosition::P_3D:
1154 linkId = getEdgeLinkP(p.data(), localLinkId);
1155 break;
1156 case EdgePosition::D1_3D:
1157 linkId = getEdgeLinkD1(p.data(), localLinkId);
1158 break;
1159 case EdgePosition::D2_3D:
1160 linkId = getEdgeLinkD2(p.data(), localLinkId);
1161 break;
1162 case EdgePosition::D3_3D:
1163 linkId = getEdgeLinkD3(p.data(), localLinkId);
1164 break;
1165 case EdgePosition::D4_3D:
1166 linkId = getEdgeLinkD4(p.data(), localLinkId);
1167 break;
1168 case EdgePosition::L_2D:
1169 linkId = getEdgeLink2dL(p.data(), localLinkId);
1170 break;
1171 case EdgePosition::H_2D:
1172 linkId = getEdgeLink2dH(p.data(), localLinkId);
1173 break;
1174 case EdgePosition::D1_2D:
1175 linkId = getEdgeLink2dD1(p.data(), localLinkId);
1176 break;
1177 default:
1178 break;
1179 }
1180
1181 return 0;
1182}
1183
1184const vector<vector<SimplexId>> *
1185 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdgeLinks)() {
1186
1187 if(edgeLinkList_.empty()) {
1188 Timer t;
1189
1190 edgeLinkList_.resize(edgeNumber_);
1191 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1192 edgeLinkList_[i].resize(getEdgeLinkNumber(i));
1193 for(SimplexId j = 0; j < (SimplexId)edgeLinkList_[i].size(); ++j)
1194 getEdgeLink(i, j, edgeLinkList_[i][j]);
1195 }
1196
1197 printMsg("Built " + to_string(edgeNumber_) + " edge links.", 1,
1198 t.getElapsedTime(), 1);
1199 }
1200
1201 return &edgeLinkList_;
1202}
1203
1204template <typename Derived>
1207 getEdgeStarNumber)(const SimplexId &edgeId) const {
1208#ifndef TTK_ENABLE_KAMIKAZE
1209 if(edgeId < 0 or edgeId >= edgeNumber_)
1210 return -1;
1211#endif
1212
1213 switch(this->underlying().getEdgePosition(edgeId)) {
1214 case EdgePosition::L_3D:
1215 case EdgePosition::H_3D:
1216 case EdgePosition::P_3D:
1217 case EdgePosition::D4_3D:
1218 return 6;
1219 case EdgePosition::D1_3D:
1220 case EdgePosition::D2_3D:
1221 case EdgePosition::D3_3D:
1222 return 4;
1223 case EdgePosition::L_2D:
1224 case EdgePosition::H_2D:
1225 case EdgePosition::D1_2D:
1226 return 2;
1227 default:
1228 return 0;
1229 }
1230
1231 return 0;
1232}
1233
1234template <typename Derived>
1236 getEdgeStar)(const SimplexId &edgeId,
1237 const int &localStarId,
1238 SimplexId &starId) const {
1239#ifndef TTK_ENABLE_KAMIKAZE
1240 if(localStarId < 0 or localStarId >= getEdgeStarNumber(edgeId))
1241 return -1;
1242#endif
1243
1244 starId = -1;
1245 const auto &p = this->underlying().getEdgeCoords(edgeId);
1246
1247 switch(this->underlying().getEdgePosition(edgeId)) {
1248 case EdgePosition::L_3D:
1249 starId = getEdgeStarL(p.data(), localStarId);
1250 break;
1251 case EdgePosition::H_3D:
1252 starId = getEdgeStarH(p.data(), localStarId);
1253 break;
1254 case EdgePosition::P_3D:
1255 starId = getEdgeStarP(p.data(), localStarId);
1256 break;
1257 case EdgePosition::D1_3D:
1258 starId = getEdgeStarD1(p.data(), localStarId);
1259 break;
1260 case EdgePosition::D2_3D:
1261 starId = getEdgeStarD2(p.data(), localStarId);
1262 break;
1263 case EdgePosition::D3_3D:
1264 starId = getEdgeStarD3(p.data(), localStarId);
1265 break;
1266 case EdgePosition::D4_3D:
1267 starId
1268 = p[2] * tetshift_[1] + p[1] * tetshift_[0] + p[0] * 6 + localStarId;
1269 break;
1270 case EdgePosition::L_2D:
1271 starId = getEdgeStar2dL(p.data(), localStarId);
1272 break;
1273 case EdgePosition::H_2D:
1274 starId = getEdgeStar2dH(p.data(), localStarId);
1275 break;
1276 case EdgePosition::D1_2D:
1277 starId = p[0] * 2 + p[1] * tshift_[0] + localStarId;
1278 break;
1279 default:
1280 break;
1281 }
1282
1283 return 0;
1284}
1285
1286const vector<vector<SimplexId>> *
1287 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdgeStars)() {
1288
1289 if(edgeStarList_.empty()) {
1290 Timer t;
1291
1292 edgeStarList_.resize(edgeNumber_);
1293 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1294 edgeStarList_[i].resize(getEdgeStarNumber(i));
1295 for(SimplexId j = 0; j < (SimplexId)edgeStarList_[i].size(); ++j)
1296 getEdgeStar(i, j, edgeStarList_[i][j]);
1297 }
1298
1299 printMsg("Built " + to_string(edgeNumber_) + " edge stars.", 1,
1300 t.getElapsedTime(), 1);
1301 }
1302
1303 return &edgeStarList_;
1304}
1305
1306template <typename Derived>
1308 const SimplexId &triangleId,
1309 const int &localVertexId,
1310 SimplexId &vertexId) const {
1311#ifndef TTK_ENABLE_KAMIKAZE
1312 if(triangleId < 0 or triangleId >= triangleNumber_)
1313 return -1;
1314 if(localVertexId < 0 or localVertexId >= 3)
1315 return -2;
1316#endif
1317
1318 vertexId = -1;
1319 const auto &p = this->underlying().getTriangleCoords(triangleId);
1320 const SimplexId wrapXRight = (p[0] / 2 == nbvoxels_[Di_]) ? -wrap_[0] : 0;
1321 const SimplexId wrapYBottom = (p[1] == nbvoxels_[Dj_]) ? -wrap_[1] : 0;
1322
1323 switch(this->underlying().getTrianglePosition(triangleId)) {
1324 case TrianglePosition::F_3D:
1325 vertexId = getTriangleVertexF(p.data(), localVertexId);
1326 break;
1327 case TrianglePosition::H_3D:
1328 vertexId = getTriangleVertexH(p.data(), localVertexId);
1329 break;
1330 case TrianglePosition::C_3D:
1331 vertexId = getTriangleVertexC(p.data(), localVertexId);
1332 break;
1333 case TrianglePosition::D1_3D:
1334 vertexId = getTriangleVertexD1(p.data(), localVertexId);
1335 break;
1336 case TrianglePosition::D2_3D:
1337 vertexId = getTriangleVertexD2(p.data(), localVertexId);
1338 break;
1339 case TrianglePosition::D3_3D:
1340 vertexId = getTriangleVertexD3(p.data(), localVertexId);
1341 break;
1342 case TrianglePosition::TOP_2D:
1343 if(localVertexId == 0) {
1344 vertexId = p[0] / 2 + p[1] * vshift_[0];
1345 } else if(localVertexId == 1) {
1346 vertexId = p[0] / 2 + p[1] * vshift_[0] + 1 + wrapXRight;
1347 } else if(localVertexId == 2) {
1348 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0] + wrapYBottom;
1349 }
1350 break;
1351 case TrianglePosition::BOTTOM_2D:
1352 if(localVertexId == 0) {
1353 vertexId = p[0] / 2 + p[1] * vshift_[0] + 1 + wrapXRight;
1354 } else if(localVertexId == 1) {
1355 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0] + 1 + wrapXRight
1356 + wrapYBottom;
1357 } else if(localVertexId == 2) {
1358 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0] + wrapYBottom;
1359 }
1360 break;
1361 default:
1362 break;
1363 }
1364
1365 return 0;
1366}
1367
1368template <typename Derived>
1370 const SimplexId &triangleId,
1371 const int &localEdgeId,
1372 SimplexId &edgeId) const {
1373#ifndef TTK_ENABLE_KAMIKAZE
1374 if(triangleId < 0 or triangleId >= triangleNumber_)
1375 return -1;
1376 if(localEdgeId < 0 or localEdgeId >= 3)
1377 return -2;
1378#endif
1379
1380 edgeId = -1;
1381 const auto &p = this->underlying().getTriangleCoords(triangleId);
1382 const SimplexId wrapXRight = (p[0] / 2 == nbvoxels_[Di_]) ? -wrap_[0] : 0;
1383 const SimplexId wrapYBottom = (p[1] == nbvoxels_[Dj_]) ? -wrap_[1] : 0;
1384 const SimplexId id = triangleId % 2;
1385
1386 switch(this->underlying().getTrianglePosition(triangleId)) {
1387 case TrianglePosition::F_3D:
1388 edgeId = (id == 1) ? getTriangleEdgeF_1(p.data(), localEdgeId)
1389 : getTriangleEdgeF_0(p.data(), localEdgeId);
1390 break;
1391 case TrianglePosition::H_3D:
1392 edgeId = (id == 1) ? getTriangleEdgeH_1(p.data(), localEdgeId)
1393 : getTriangleEdgeH_0(p.data(), localEdgeId);
1394 break;
1395 case TrianglePosition::C_3D:
1396 edgeId = (id == 1) ? getTriangleEdgeC_1(p.data(), localEdgeId)
1397 : getTriangleEdgeC_0(p.data(), localEdgeId);
1398 break;
1399 case TrianglePosition::D1_3D:
1400 edgeId = (id == 1) ? getTriangleEdgeD1_1(p.data(), localEdgeId)
1401 : getTriangleEdgeD1_0(p.data(), localEdgeId);
1402 break;
1403 case TrianglePosition::D2_3D:
1404 edgeId = (id == 1) ? getTriangleEdgeD2_1(p.data(), localEdgeId)
1405 : getTriangleEdgeD2_0(p.data(), localEdgeId);
1406 break;
1407 case TrianglePosition::D3_3D:
1408 edgeId = (id == 1) ? getTriangleEdgeD3_1(p.data(), localEdgeId)
1409 : getTriangleEdgeD3_0(p.data(), localEdgeId);
1410 break;
1411 case TrianglePosition::TOP_2D:
1412 if(localEdgeId == 0) {
1413 edgeId = p[0] / 2 + p[1] * eshift_[0];
1414 } else if(localEdgeId == 1) {
1415 edgeId = esetshift_[0] + p[0] / 2 + p[1] * eshift_[2];
1416 } else if(localEdgeId == 2) {
1417 edgeId = esetshift_[1] + p[0] / 2 + p[1] * eshift_[4];
1418 }
1419 break;
1420 case TrianglePosition::BOTTOM_2D:
1421 if(localEdgeId == 0) {
1422 edgeId = p[0] / 2 + (p[1] + 1) * eshift_[0] + wrapYBottom;
1423 } else if(localEdgeId == 1) {
1424 edgeId
1425 = esetshift_[0] + (p[0] + 1) / 2 + p[1] * eshift_[2] + wrapXRight;
1426 } else if(localEdgeId == 2) {
1427 edgeId = esetshift_[1] + p[0] / 2 + p[1] * eshift_[4];
1428 }
1429 break;
1430 default:
1431 break;
1432 }
1433
1434 return 0;
1435}
1436
1438 vector<vector<SimplexId>> &edges) const {
1439 edges.resize(triangleNumber_);
1440 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1441 edges[i].resize(3);
1442 for(int j = 0; j < 3; ++j)
1443 getTriangleEdgeInternal(i, j, edges[i][j]);
1444 }
1445 return 0;
1446}
1447
1448const vector<vector<SimplexId>> *
1450 if(triangleEdgeVector_.empty()) {
1451 Timer t;
1452
1454
1455 printMsg("Built " + to_string(triangleNumber_) + " triangle edges.", 1,
1456 t.getElapsedTime(), 1);
1457 }
1458
1459 return &triangleEdgeVector_;
1460}
1461
1462const vector<std::array<SimplexId, 3>> *
1463 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getTriangles)() {
1464
1465 if(triangleList_.empty()) {
1466 Timer t;
1467
1468 triangleList_.resize(triangleNumber_);
1469 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1470 for(int j = 0; j < 3; ++j)
1471 getTriangleVertexInternal(i, j, triangleList_[i][j]);
1472 }
1473
1474 printMsg("Built " + to_string(triangleNumber_) + " triangles.", 1,
1475 t.getElapsedTime(), 1);
1476 }
1477
1478 return &triangleList_;
1479}
1480
1481template <typename Derived>
1483 getTriangleLink)(const SimplexId &triangleId,
1484 const int &localLinkId,
1485 SimplexId &linkId) const {
1486#ifndef TTK_ENABLE_KAMIKAZE
1487 if(localLinkId < 0 or localLinkId >= getTriangleLinkNumber(triangleId))
1488 return -1;
1489#endif
1490
1491 linkId = -1;
1492 const auto &p = this->underlying().getTriangleCoords(triangleId);
1493
1494 switch(this->underlying().getTrianglePosition(triangleId)) {
1495 case TrianglePosition::F_3D:
1496 linkId = getTriangleLinkF(p.data(), localLinkId);
1497 break;
1498 case TrianglePosition::H_3D:
1499 linkId = getTriangleLinkH(p.data(), localLinkId);
1500 break;
1501 case TrianglePosition::C_3D:
1502 linkId = getTriangleLinkC(p.data(), localLinkId);
1503 break;
1504 case TrianglePosition::D1_3D:
1505 linkId = getTriangleLinkD1(p.data(), localLinkId);
1506 break;
1507 case TrianglePosition::D2_3D:
1508 linkId = getTriangleLinkD2(p.data(), localLinkId);
1509 break;
1510 case TrianglePosition::D3_3D:
1511 linkId = getTriangleLinkD3(p.data(), localLinkId);
1512 break;
1513 default:
1514 break;
1515 }
1516
1517 return 0;
1518}
1519
1520SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1521 getTriangleLinkNumber)(const SimplexId &triangleId) const {
1522
1523 return getTriangleStarNumber(triangleId);
1524}
1525
1526const vector<vector<SimplexId>> *
1527 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1528 getTriangleLinks)() {
1529
1530 if(triangleLinkList_.empty()) {
1531 Timer t;
1532
1533 triangleLinkList_.resize(triangleNumber_);
1534 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1535 triangleLinkList_[i].resize(getTriangleLinkNumber(i));
1536 for(SimplexId j = 0; j < (SimplexId)triangleLinkList_[i].size(); ++j)
1537 getTriangleLink(i, j, triangleLinkList_[i][j]);
1538 }
1539
1540 printMsg("Built " + to_string(triangleNumber_) + " triangle links.", 1,
1541 t.getElapsedTime(), 1);
1542 }
1543 return &triangleLinkList_;
1544}
1545
1546template <typename Derived>
1549 getTriangleStarNumber)(const SimplexId &triangleId) const {
1550#ifndef TTK_ENABLE_KAMIKAZE
1551 if(triangleId < 0 or triangleId >= triangleNumber_)
1552 return -1;
1553#else
1554 TTK_FORCE_USE(triangleId);
1555#endif
1556
1557 if(dimensionality_ == 3) {
1558 return 2;
1559 }
1560 return 0;
1561}
1562
1563template <typename Derived>
1565 getTriangleStar)(const SimplexId &triangleId,
1566 const int &localStarId,
1567 SimplexId &starId) const {
1568#ifndef TTK_ENABLE_KAMIKAZE
1569 if(localStarId < 0 or localStarId >= getTriangleStarNumber(triangleId))
1570 return -1;
1571#endif
1572
1573 starId = -1;
1574 const auto &p = this->underlying().getTriangleCoords(triangleId);
1575
1576 switch(this->underlying().getTrianglePosition(triangleId)) {
1577 case TrianglePosition::F_3D:
1578 starId = getTriangleStarF(p.data(), localStarId);
1579 break;
1580 case TrianglePosition::H_3D:
1581 starId = getTriangleStarH(p.data(), localStarId);
1582 break;
1583 case TrianglePosition::C_3D:
1584 starId = getTriangleStarC(p.data(), localStarId);
1585 break;
1586 case TrianglePosition::D1_3D:
1587 starId = getTriangleStarD1(p.data(), localStarId);
1588 break;
1589 case TrianglePosition::D2_3D:
1590 starId = getTriangleStarD2(p.data(), localStarId);
1591 break;
1592 case TrianglePosition::D3_3D:
1593 starId = getTriangleStarD3(p.data(), localStarId);
1594 break;
1595 default:
1596 break;
1597 }
1598
1599 return 0;
1600}
1601
1602const vector<vector<SimplexId>> *
1603 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1604 getTriangleStars)() {
1605
1606 if(triangleStarList_.empty()) {
1607 Timer t;
1608
1609 triangleStarList_.resize(triangleNumber_);
1610 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1611 triangleStarList_[i].resize(getTriangleStarNumber(i));
1612 for(SimplexId j = 0; j < (SimplexId)triangleStarList_[i].size(); ++j)
1613 getTriangleStar(i, j, triangleStarList_[i][j]);
1614 }
1615
1616 printMsg("Built " + to_string(triangleNumber_) + " triangle stars.", 1,
1617 t.getElapsedTime(), 1);
1618 }
1619 return &triangleStarList_;
1620}
1621
1623 const SimplexId &triangleId) const {
1624#ifndef TTK_ENABLE_KAMIKAZE
1625 if(triangleId < 0 or triangleId >= triangleNumber_)
1626 return -1;
1627#endif
1628
1629 TTK_FORCE_USE(triangleId);
1630 if(dimensionality_ == 2) {
1631 return 3;
1632 }
1633
1634 return 0;
1635}
1636
1637template <typename Derived>
1639 const SimplexId &triangleId,
1640 const int &localNeighborId,
1641 SimplexId &neighborId) const {
1642#ifndef TTK_ENABLE_KAMIKAZE
1643 if(localNeighborId < 0
1644 or localNeighborId >= getTriangleNeighborNumber(triangleId))
1645 return -1;
1646#endif
1647
1648 neighborId = -1;
1649 const auto &p = this->underlying().getTriangleCoords(triangleId);
1650
1651 switch(this->underlying().getTrianglePosition(triangleId)) {
1652 case TrianglePosition::BOTTOM_2D:
1653
1654 if(p[0] / 2 == nbvoxels_[Di_] and p[1] == nbvoxels_[Dj_]) {
1655 if(localNeighborId == 0) {
1656 neighborId = triangleId - 1;
1657 } else if(localNeighborId == 1) {
1658 neighborId = triangleId + 1 - wrap_[0] * 2;
1659 } else if(localNeighborId == 2) {
1660 neighborId = triangleId + tshift_[0] - 1 - wrap_[1] * 2;
1661 }
1662
1663 } else if(p[0] / 2 == nbvoxels_[Di_]) {
1664 if(localNeighborId == 0) {
1665 neighborId = triangleId - 1;
1666 } else if(localNeighborId == 1) {
1667 neighborId = triangleId + 1 - wrap_[0] * 2;
1668 } else if(localNeighborId == 2) {
1669 neighborId = triangleId + tshift_[0] - 1;
1670 }
1671
1672 } else if(p[1] == nbvoxels_[Dj_]) {
1673 if(localNeighborId == 0) {
1674 neighborId = triangleId - 1;
1675 } else if(localNeighborId == 1) {
1676 neighborId = triangleId + 1;
1677 } else if(localNeighborId == 2) {
1678 neighborId = triangleId + tshift_[0] - 1 - wrap_[1] * 2;
1679 }
1680
1681 } else {
1682 if(localNeighborId == 0) {
1683 neighborId = triangleId - 1;
1684 } else if(localNeighborId == 1) {
1685 neighborId = triangleId + 1;
1686 } else if(localNeighborId == 2) {
1687 neighborId = triangleId + tshift_[0] - 1;
1688 }
1689 }
1690 break;
1691
1692 case TrianglePosition::TOP_2D:
1693
1694 if(p[0] / 2 == 0 and p[1] == 0) {
1695 if(localNeighborId == 0) {
1696 neighborId = triangleId + 1;
1697 } else if(localNeighborId == 1) {
1698 neighborId = triangleId - 1 + wrap_[0] * 2;
1699 } else if(localNeighborId == 2) {
1700 neighborId = triangleId - tshift_[0] + 1 + wrap_[1] * 2;
1701 }
1702
1703 } else if(p[0] / 2 == 0) {
1704 if(localNeighborId == 0) {
1705 neighborId = triangleId + 1;
1706 } else if(localNeighborId == 1) {
1707 neighborId = triangleId - 1 + wrap_[0] * 2;
1708 } else if(localNeighborId == 2) {
1709 neighborId = triangleId - tshift_[0] + 1;
1710 }
1711
1712 } else if(p[1] == 0) {
1713 if(localNeighborId == 0) {
1714 neighborId = triangleId + 1;
1715 } else if(localNeighborId == 1) {
1716 neighborId = triangleId - 1;
1717 } else if(localNeighborId == 2) {
1718 neighborId = triangleId - tshift_[0] + 1 + wrap_[1] * 2;
1719 }
1720
1721 } else {
1722 if(localNeighborId == 0) {
1723 neighborId = triangleId + 1;
1724 } else if(localNeighborId == 1) {
1725 neighborId = triangleId - 1;
1726 } else if(localNeighborId == 2) {
1727 neighborId = triangleId - tshift_[0] + 1;
1728 }
1729 }
1730 break;
1731 default:
1732 break;
1733 }
1734
1735 return 0;
1736}
1737
1739 vector<vector<SimplexId>> &neighbors) {
1740 neighbors.resize(triangleNumber_);
1741 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1742 neighbors[i].resize(getTriangleNeighborNumber(i));
1743 for(SimplexId j = 0; j < (SimplexId)neighbors[i].size(); ++j)
1744 getTriangleNeighbor(i, j, neighbors[i][j]);
1745 }
1746 return 0;
1747}
1748
1749template <typename Derived>
1751 const SimplexId &tetId, const int &localVertexId, SimplexId &vertexId) const {
1752#ifndef TTK_ENABLE_KAMIKAZE
1753 if(tetId < 0 or tetId >= tetrahedronNumber_)
1754 return -1;
1755 if(localVertexId < 0 or localVertexId >= 4)
1756 return -2;
1757#endif
1758
1759 vertexId = -1;
1760
1761 if(dimensionality_ == 3) {
1762 const auto &p = this->underlying().getTetrahedronCoords(tetId);
1763 const SimplexId id = tetId % 6;
1764
1765 switch(id) {
1766 case 0:
1767 vertexId = getTetrahedronVertexABCG(p.data(), localVertexId);
1768 break;
1769 case 1:
1770 vertexId = getTetrahedronVertexBCDG(p.data(), localVertexId);
1771 break;
1772 case 2:
1773 vertexId = getTetrahedronVertexABEG(p.data(), localVertexId);
1774 break;
1775 case 3:
1776 vertexId = getTetrahedronVertexBEFG(p.data(), localVertexId);
1777 break;
1778 case 4:
1779 vertexId = getTetrahedronVertexBFGH(p.data(), localVertexId);
1780 break;
1781 case 5:
1782 vertexId = getTetrahedronVertexBDGH(p.data(), localVertexId);
1783 break;
1784 }
1785 }
1786 return 0;
1787}
1788
1789template <typename Derived>
1791 const SimplexId &tetId, const int &localEdgeId, SimplexId &edgeId) const {
1792#ifndef TTK_ENABLE_KAMIKAZE
1793 if(tetId < 0 or tetId >= tetrahedronNumber_)
1794 return -1;
1795 if(localEdgeId < 0 or localEdgeId >= 6)
1796 return -2;
1797#endif
1798
1799 edgeId = -1;
1800
1801 if(dimensionality_ == 3) {
1802 const auto &p = this->underlying().getTetrahedronCoords(tetId);
1803 const SimplexId id = tetId % 6;
1804
1805 switch(id) {
1806 case 0:
1807 edgeId = getTetrahedronEdgeABCG(p.data(), localEdgeId);
1808 break;
1809 case 1:
1810 edgeId = getTetrahedronEdgeBCDG(p.data(), localEdgeId);
1811 break;
1812 case 2:
1813 edgeId = getTetrahedronEdgeABEG(p.data(), localEdgeId);
1814 break;
1815 case 3:
1816 edgeId = getTetrahedronEdgeBEFG(p.data(), localEdgeId);
1817 break;
1818 case 4:
1819 edgeId = getTetrahedronEdgeBFGH(p.data(), localEdgeId);
1820 break;
1821 case 5:
1822 edgeId = getTetrahedronEdgeBDGH(p.data(), localEdgeId);
1823 break;
1824 }
1825 }
1826
1827 return 0;
1828}
1829
1831 vector<vector<SimplexId>> &edges) const {
1832 edges.resize(tetrahedronNumber_);
1833 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
1834 edges[i].resize(6);
1835 for(int j = 0; j < 6; ++j)
1836 getTetrahedronEdge(i, j, edges[i][j]);
1837 }
1838
1839 return 0;
1840}
1841
1842template <typename Derived>
1844 const SimplexId &tetId,
1845 const int &localTriangleId,
1846 SimplexId &triangleId) const {
1847#ifndef TTK_ENABLE_KAMIKAZE
1848 if(tetId < 0 or tetId >= tetrahedronNumber_)
1849 return -1;
1850 if(localTriangleId < 0 or localTriangleId >= 4)
1851 return -2;
1852#endif
1853
1854 triangleId = -1;
1855
1856 if(dimensionality_ == 3) {
1857 const auto &p = this->underlying().getTetrahedronCoords(tetId);
1858 const SimplexId id = tetId % 6;
1859
1860 switch(id) {
1861 case 0:
1862 triangleId = getTetrahedronTriangleABCG(p.data(), localTriangleId);
1863 break;
1864 case 1:
1865 triangleId = getTetrahedronTriangleBCDG(p.data(), localTriangleId);
1866 break;
1867 case 2:
1868 triangleId = getTetrahedronTriangleABEG(p.data(), localTriangleId);
1869 break;
1870 case 3:
1871 triangleId = getTetrahedronTriangleBEFG(p.data(), localTriangleId);
1872 break;
1873 case 4:
1874 triangleId = getTetrahedronTriangleBFGH(p.data(), localTriangleId);
1875 break;
1876 case 5:
1877 triangleId = getTetrahedronTriangleBDGH(p.data(), localTriangleId);
1878 break;
1879 }
1880 }
1881
1882 return 0;
1883}
1884
1886 vector<vector<SimplexId>> &triangles) const {
1887 triangles.resize(tetrahedronNumber_);
1888 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
1889 triangles[i].resize(4);
1890 for(int j = 0; j < 4; ++j)
1891 getTetrahedronTriangle(i, j, triangles[i][j]);
1892 }
1893
1894 return 0;
1895}
1896
1898 const SimplexId &tetId) const {
1899#ifndef TTK_ENABLE_KAMIKAZE
1900 if(tetId < 0 or tetId >= tetrahedronNumber_)
1901 return -1;
1902#endif
1903
1904 TTK_FORCE_USE(tetId);
1905 if(dimensionality_ == 3) {
1906 return 4;
1907 }
1908
1909 return 0;
1910}
1911
1912template <typename Derived>
1914 const SimplexId &tetId,
1915 const int &localNeighborId,
1916 SimplexId &neighborId) const {
1917#ifndef TTK_ENABLE_KAMIKAZE
1918 if(localNeighborId < 0
1919 or localNeighborId >= getTetrahedronNeighborNumber(tetId))
1920 return -1;
1921#endif
1922
1923 neighborId = -1;
1924
1925 if(dimensionality_ == 3) {
1926 const auto &p = this->underlying().getTetrahedronCoords(tetId);
1927 const SimplexId id = tetId % 6;
1928
1929 switch(id) {
1930 case 0:
1931 neighborId
1932 = getTetrahedronNeighborABCG(tetId, p.data(), localNeighborId);
1933 break;
1934 case 1:
1935 neighborId
1936 = getTetrahedronNeighborBCDG(tetId, p.data(), localNeighborId);
1937 break;
1938 case 2:
1939 neighborId
1940 = getTetrahedronNeighborABEG(tetId, p.data(), localNeighborId);
1941 break;
1942 case 3:
1943 neighborId
1944 = getTetrahedronNeighborBEFG(tetId, p.data(), localNeighborId);
1945 break;
1946 case 4:
1947 neighborId
1948 = getTetrahedronNeighborBFGH(tetId, p.data(), localNeighborId);
1949 break;
1950 case 5:
1951 neighborId
1952 = getTetrahedronNeighborBDGH(tetId, p.data(), localNeighborId);
1953 break;
1954 }
1955 }
1956
1957 return 0;
1958}
1959
1961 vector<vector<SimplexId>> &neighbors) {
1962 neighbors.resize(tetrahedronNumber_);
1963 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
1964 neighbors[i].resize(getTetrahedronNeighborNumber(i));
1965 for(SimplexId j = 0; j < (SimplexId)neighbors[i].size(); ++j)
1966 getTetrahedronNeighbor(i, j, neighbors[i][j]);
1967 }
1968
1969 return 0;
1970}
1971
1972SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
1973 getCellVertexNumber)(const SimplexId &ttkNotUsed(cellId)) const {
1974
1975 return dimensionality_ + 1;
1976}
1977
1978int PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getCellVertex)(
1979 const SimplexId &cellId,
1980 const int &localVertexId,
1981 SimplexId &vertexId) const {
1982
1983 if(dimensionality_ == 3)
1984 getTetrahedronVertex(cellId, localVertexId, vertexId);
1985 else if(dimensionality_ == 2)
1986 getTriangleVertexInternal(cellId, localVertexId, vertexId);
1987 else if(dimensionality_ == 1)
1988 getEdgeVertexInternal(cellId, localVertexId, vertexId);
1989
1990 return 0;
1991}
1992
1994 const SimplexId &ttkNotUsed(cellId)) const {
1995 if(dimensionality_ == 3)
1996 return 6;
1997 else if(dimensionality_ == 2)
1998 return 3;
1999
2000 return 0;
2001}
2002
2004 const SimplexId &cellId, const int &localEdgeId, SimplexId &edgeId) const {
2005 if(dimensionality_ == 3)
2006 getTetrahedronEdge(cellId, localEdgeId, edgeId);
2007 else if(dimensionality_ == 2)
2008 getTriangleEdgeInternal(cellId, localEdgeId, edgeId);
2009 else if(dimensionality_ == 1)
2010 getCellNeighbor(cellId, localEdgeId, edgeId);
2011
2012 return 0;
2013}
2014
2015const vector<vector<SimplexId>> *
2017 if(cellEdgeVector_.empty()) {
2018 Timer t;
2019
2020 if(dimensionality_ == 3)
2022 else if(dimensionality_ == 2)
2024
2025 printMsg("Built " + to_string(cellNumber_) + " cell edges.", 1,
2026 t.getElapsedTime(), 1);
2027 }
2028
2029 return &cellEdgeVector_;
2030}
2031
2033 const SimplexId &cellId,
2034 const int &localTriangleId,
2035 SimplexId &triangleId) const {
2036 if(dimensionality_ == 3)
2037 getTetrahedronTriangle(cellId, localTriangleId, triangleId);
2038
2039 return 0;
2040}
2041
2042const vector<vector<SimplexId>> *
2044 if(cellTriangleVector_.empty()) {
2045 Timer t;
2046
2047 if(dimensionality_ == 3)
2049
2050 printMsg("Built " + to_string(cellNumber_) + " cell triangles.", 1,
2051 t.getElapsedTime(), 1);
2052 }
2053
2054 return &cellTriangleVector_;
2055}
2056
2057SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
2058 getCellNeighborNumber)(const SimplexId &cellId) const {
2059
2060 if(dimensionality_ == 3)
2061 return getTetrahedronNeighborNumber(cellId);
2062 else if(dimensionality_ == 2)
2063 return getTriangleNeighborNumber(cellId);
2064 else if(dimensionality_ == 1) {
2065 printErr("getCellNeighborNumber() not implemented in 1D! (TODO)");
2066 return -1;
2067 }
2068
2069 return 0;
2070}
2071
2072int PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getCellNeighbor)(
2073 const SimplexId &cellId,
2074 const int &localNeighborId,
2075 SimplexId &neighborId) const {
2076
2077 if(dimensionality_ == 3)
2078 getTetrahedronNeighbor(cellId, localNeighborId, neighborId);
2079 else if(dimensionality_ == 2)
2080 getTriangleNeighbor(cellId, localNeighborId, neighborId);
2081 else if(dimensionality_ == 1) {
2082 printErr("getCellNeighbor() not implemented in 1D! (TODO)");
2083 return -1;
2084 }
2085
2086 return 0;
2087}
2088
2089const vector<vector<SimplexId>> *
2090 PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
2091 getCellNeighbors)() {
2092
2093 if(cellNeighborList_.empty()) {
2094 Timer t;
2095
2096 if(dimensionality_ == 3)
2097 getTetrahedronNeighbors(cellNeighborList_);
2098 else if(dimensionality_ == 2)
2099 getTriangleNeighbors(cellNeighborList_);
2100 else if(dimensionality_ == 1) {
2101 printErr("getCellNeighbors() not implemented in 1D! (TODO)");
2102 return nullptr;
2103 }
2104
2105 printMsg("Built " + to_string(cellNumber_) + " cell neighbors.", 1,
2106 t.getElapsedTime(), 1);
2107 }
2108
2109 return &cellNeighborList_;
2110}
2111
2112// 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
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
int PeriodicImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexNeighbor(const SimplexId &vertexId, const int &localNeighborId, SimplexId &neighborId) 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 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
std::string to_string(__int128)
Definition ripserpy.cpp:99
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::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)