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