TTK
Loading...
Searching...
No Matches
FTRGraphPrivate_Template.h
Go to the documentation of this file.
1#pragma once
2
3// local includes
4#include "FTRGraph.h"
5#include "FTRGraph_Template.h"
6#include "FTRTasks.h"
7
8// c++ includes
9#include <unordered_map>
10
11// trick to print a full line in an atomic operation, avoid mixed up redulsts in
12// parallel
13#ifndef NDEBUG
14// #define PRINT(msg) {std::stringstream s; s << msg << std::endl; std::cout <<
15// s.str();}
16#define PRINT(msg)
17#else
18#define PRINT(msg)
19#endif
20
21template <typename ScalarType, typename triangulationType>
23 const idVertex seed, Propagation *localProp, idSuperArc currentArc) {
24
25 TTK_FORCE_USE(seed);
26 PRINT(seed << " :: " << localProp->getNbArcs());
27 if(!localProp->getNbArcs()) {
28 PRINT(seed << " Stop direct");
29#ifdef TTK_ENABLE_FTR_TASK_STATS
30 {
31 // This only when tasks grows exclusively from min
32 // This propagation is dying here
33 idVertex curProp;
34 float curTime;
35#pragma omp atomic capture seq_cst
36 {
37 curProp = nbProp_;
38 --nbProp_;
39 }
40#pragma omp critical(stats)
41 { curTime = sweepStart_.getElapsedTime(); }
42 propTimes_[curProp - 1] = curTime;
43 }
44#endif
45 return;
46 }
47
48 // topology
49 bool isJoinLast = false;
50 bool isJoin = false, isSplit = false;
51
52 // containers
53 // vitsit
54 Star star;
55 Comp comp;
56
57 while(!isJoin && !isSplit && !localProp->empty()) {
58 localProp->nextVertex();
59 const idVertex curVert = localProp->getCurVertex();
60 idSuperArc mergeIn = nullSuperArc;
61
62 if(localProp->getNbArcs() == 0) {
63#ifdef TTK_ENABLE_FTR_TASK_STATS
64 {
65 // This only when tasks grows exclusively from min
66 // This propagation is dying here
67 idVertex curProp;
68 float curTime;
69#pragma omp atomic capture seq_cst
70 {
71 curProp = nbProp_;
72 --nbProp_;
73 }
74#pragma omp critical(stats)
75 { curTime = sweepStart_.getElapsedTime(); }
76 propTimes_[curProp - 1] = curTime;
77 }
78#endif
79 return;
80 }
81
82 PRINT("<" << curVert << " " << localProp->goUp() << " a "
83 << localProp->getNbArcs());
84
85#ifdef TTK_ENABLE_FTR_VERT_STATS
86 graph_.incTouch(curVert);
87 graph_.setNbArcActive(curVert, localProp->getNbArcs());
88#endif
89
90 visitStar(localProp, star);
91
92 if(propagations_.hasVisitedOpposite(
93 curVert, localProp) /*&& !graph_.isNode(curVert)*/) {
94 bool ignoreVert = false;
95 for(auto edge : star.lower) {
96 const idSuperArc tmpLowArc = dynGraph(localProp).getSubtreeArc(edge);
97 if(tmpLowArc != nullSuperArc && !graph_.getArc(tmpLowArc).isVisible()
98 && graph_.getArc(tmpLowArc).getPropagation() == localProp) {
99 PRINT("-" << curVert << " " << graph_.printArc(tmpLowArc));
100#ifdef TTK_ENABLE_FTR_VERT_STATS
101 graph_.incAvoid();
102#endif
103 ignoreVert = true;
104 break;
105 } else if(tmpLowArc != nullSuperArc) {
106 PRINT("!" << graph_.printArc(tmpLowArc));
107 }
108 }
109 if(ignoreVert)
110 continue;
111 }
112
113#ifndef TTK_DISABLE_FTR_LAZY
114 if(valences_.lower[curVert] < 2 && valences_.upper[curVert] < 2) {
115
116 // not a local min (for local min, currentArc is already set)
117 if(star.lower.size()) {
118 // not a min nor a saddle: 1 CC below
119 currentArc = dynGraph(localProp).getSubtreeArc(star.lower[0]);
120 if(currentArc == nullSuperArc) {
121 PRINT("n-" << curVert);
122 continue;
123 }
124 if(valences_.upper[curVert] && valences_.lower[curVert]) {
125 // not saddle neither extrema
126 graph_.getArc(currentArc).visit(curVert);
127 }
128 }
129
130 mergeIn = visit(localProp, currentArc);
131
132 lazyUpdatePreimage(localProp, currentArc);
133
134 // ensure we will always recover this arc from the upper neighbors
135 for(const idEdge dgNode : star.upper) {
136 dynGraph(localProp).setCorArc(dgNode, currentArc);
137 }
138 } else {
139 // locally apply the lazy one the current growing arc
140 for(const idEdge e : star.lower) {
141 const auto node{dynGraph(localProp).getNode(e)};
142 const idSuperArc a
143 = node != nullptr ? node->findRootArc() : nullSuperArc;
144 if(a != nullSuperArc && graph_.getArc(a).isVisible()
145 && graph_.getArc(a).getPropagation()->getId()
146 == localProp->getId()) {
147 lazyApply(localProp, a);
148 }
149 }
150#else
151 {
152#endif
153 comp.lower = lowerComps(star.lower, localProp);
154
155 if(comp.lower.size() > 1) {
156 isJoin = true;
157 isJoinLast = checkLast(localProp, star.lower);
158 break;
159 } else {
160 if(comp.lower.size()) {
161 currentArc = (*comp.lower.begin())->getCorArc();
162 if(currentArc == nullSuperArc) {
163 PRINT("n--" << curVert);
164 continue;
165 }
166 }
167 mergeIn = visit(localProp, currentArc);
168 }
169 updatePreimage(localProp, currentArc);
170 comp.upper = upperComps(star.upper, localProp);
171 if(comp.upper.size() > 1) {
172 isSplit = true;
173 }
174
175 if(!isJoin && !isSplit && comp.upper.size()) {
176 // this arc is not empty (not saddle not max)
177 graph_.getArc(currentArc).visit(curVert);
178 }
179 }
180
181 // merge current arc
182 if(mergeIn != nullSuperArc && graph_.getArc(currentArc).isVisible()) {
183 graph_.getArc(currentArc).merge(mergeIn);
184 localProp->lessArc();
185 PRINT(">" << graph_.printArc(currentArc) << " "
186 << graph_.printArc(mergeIn));
187 // Can't stop here
188 // try interleaved launch sequential on dragon.vtu
189 // if (localProp->getNbArcs() == 0) return;
190 }
191
192 // stop on leaves
193 if(!star.upper.size()) {
194 // We have reached a local extrema (max from this propagation)
195 const idNode leafNode = graph_.makeNode(curVert);
196 graph_.closeArc(currentArc, leafNode);
197 PRINT("^" << graph_.printArc(currentArc));
198 if(graph_.getArc(currentArc).isVisible()) {
199 // do not decrease on merged arcs
200 localProp->lessArc();
201 }
202 if(localProp->getNbArcs() == 0) {
203 // no more active arcs
204 PRINT(curVert << " stop");
205#ifdef TTK_ENABLE_FTR_TASK_STATS
206 {
207 // This only when tasks grows exclusively from min
208 // This propagation is dying here
209 idVertex curProp;
210 float curTime;
211#pragma omp atomic capture seq_cst
212 {
213 curProp = nbProp_;
214 --nbProp_;
215 }
216#pragma omp critical(stats)
217 { curTime = sweepStart_.getElapsedTime(); }
218 propTimes_[curProp - 1] = curTime;
219 }
220#endif
221 return;
222 }
223 }
224
225 // add upper star for futur visit
226 localGrowth(localProp, star.upper);
227 } // end propagation while
228
229 // get the corresponding critical point on which
230 // the propagation has stopped (join, split, max)
231 const idVertex upVert = localProp->getCurVertex();
232
233 if(localProp->getNbArcs() == 0 || localProp->empty()) {
234 PRINT(upVert << " stop " << localProp->getNbArcs());
235#ifdef TTK_ENABLE_FTR_TASK_STATS
236 {
237 // This only when tasks grows exclusively from min
238 // This propagation is dying here
239 idVertex curProp;
240 float curTime;
241#pragma omp atomic capture seq_cst
242 {
243 curProp = nbProp_;
244 --nbProp_;
245 }
246#pragma omp critical(stats)
247 { curTime = sweepStart_.getElapsedTime(); }
248 propTimes_[curProp - 1] = curTime;
249 }
250#endif
251 return;
252 }
253
254 PRINT(upVert << " active " << localProp->getNbArcs());
255
256 // reached node id and whether it has been created by this task or already
257 // existed
258 idNode saddleNode;
259 idSuperArc joinParentArc{};
260 bool hideFromHere = false; // if true, new arc are hidden to stop propagation.
261
262#ifdef TTK_ENABLE_OPENMP4
263#pragma omp critical
264#endif
265 {
266 bool const alreadyNode = graph_.isNode(upVert);
267 hideFromHere = alreadyNode;
268 if(isJoin) {
269 PRINT(upVert << " join " << isJoinLast << " h " << hideFromHere);
270 if(isJoinLast) {
271 graph_.makeNode(upVert);
272 }
273 }
274 if(isSplit) {
275 PRINT(upVert << " split " << hideFromHere);
276 graph_.makeNode(upVert);
277 }
278 }
279
280 // arc management
281 if(isJoinLast) {
282 // ensure we have the good values here, even if other tasks were doing
283 // stuff
284 {
285 // here to solve a 1 over thousands execution bug in parallel
286 // TODO Still required ??
287 visitStar(localProp, star);
288 comp.lower = lowerComps(star.lower, localProp);
289 }
290 saddleNode = graph_.getNodeId(upVert);
291 idSuperArc const visibleMerged
292 = mergeAtSaddle(saddleNode, localProp, comp.lower);
293 localProp->lessArc(visibleMerged - 1);
294
295 localGrowth(localProp, star.upper);
296
297 joinParentArc = graph_.openArc(saddleNode, localProp);
298 visit(localProp, joinParentArc);
299 updatePreimage(localProp, joinParentArc);
300 comp.upper = upperComps(star.upper, localProp);
301
302 // do not propagate
303 if(hideFromHere) {
304 if(graph_.getArc(joinParentArc).hide()) {
305 localProp->lessArc();
306 }
307 }
308
309 // split detection required after the merge
310 if(comp.upper.size() > 1) {
311 // this node is both join and split
312 isSplit = true;
313 // will be replaced be new arcs of the split
314 if(graph_.getArc(joinParentArc).hide()) {
315 localProp->lessArc();
316 }
317 }
318
319 PRINT("+" << graph_.printArc(joinParentArc));
320 } else if(!isJoin) {
321 // only one arc coming here
322 saddleNode = graph_.getNodeId(upVert);
323 graph_.closeArc(currentArc, saddleNode);
324 if(localProp->getNbArcs() == 0) {
325 // no more active arcs
326 PRINT(upVert << " stop");
327#ifdef TTK_ENABLE_FTR_TASK_STATS
328 {
329 // This only when tasks grows exclusively from min
330 // This propagation is dying here
331 idVertex curProp;
332 float curTime;
333#pragma omp atomic capture seq_cst
334 {
335 curProp = nbProp_;
336 --nbProp_;
337 }
338#pragma omp critical(stats)
339 { curTime = sweepStart_.getElapsedTime(); }
340 propTimes_[curProp - 1] = curTime;
341 }
342#endif
343 return;
344 }
345 if(graph_.getArc(currentArc).isVisible()) {
346 // if not visible, already decremented the counter
347 localProp->lessArc();
348 }
349 PRINT("|" << graph_.printArc(currentArc));
350 }
351
352 if(isSplit) {
353 splitAtSaddle(localProp, comp.upper, hideFromHere);
354 if(!hideFromHere) {
355 localProp->moreArc(comp.upper.size());
356 }
357 }
358
359 // starting from the saddle
360 if(isSplit && (!isJoin || isJoinLast)) {
361#ifdef TTK_ENABLE_OPENMP4
362#pragma omp task OPTIONAL_PRIORITY(PriorityLevel::Low)
363#endif
364 growthFromSeed(upVert, localProp);
365
366 } else if(isJoinLast) {
367
368#ifdef TTK_ENABLE_OPENMP4
369#pragma omp task OPTIONAL_PRIORITY(PriorityLevel::Average)
370#endif
371 growthFromSeed(upVert, localProp, joinParentArc);
372 }
373#ifdef TTK_ENABLE_FTR_TASK_STATS
374 else {
375 // This only when tasks grows exclusively from min
376 // This propagation is dying here
377 idVertex curProp;
378 float curTime;
379#pragma omp atomic capture seq_cst
380 {
381 curProp = nbProp_;
382 --nbProp_;
383 }
384#pragma omp critical(stats)
385 { curTime = sweepStart_.getElapsedTime(); }
386 propTimes_[curProp - 1] = curTime;
387 }
388#endif
389}
390
391template <typename ScalarType, typename triangulationType>
393 const idVertex begin, const idVertex stop) {
394 Star star;
395 Comp comp;
396
397 const bool fromMin = begin < stop;
398 Propagation *localProp
399 = newPropagation(scalars_.getSortedVert(begin), fromMin);
400 const idVertex incr = fromMin ? 1 : -1;
401 for(idVertex idv = begin; idv < stop; idv = idv + incr) {
402 const idVertex curVert = scalars_.getSortedVert(idv);
403 localProp->setCurvert(curVert); // never use Fibo Heap here
404
405 idSuperArc currentArc = nullSuperArc;
406 visitStar(localProp, star);
407
408 if(valences_.lower[curVert] == 0) { // min
409 const idNode minNode = graph_.makeNode(curVert);
410 currentArc = graph_.openArc(minNode, localProp);
411 }
412
413#ifndef TTK_DISABLE_FTR_LAZY
414 if(valences_.lower[curVert] < 2 && valences_.upper[curVert] < 2) {
415
416 // simple reeb regular, laziness
417 if(!star.lower.empty()) {
418 // not a min nor a saddle: 1 CC below (need findSubtree)
419 currentArc = dynGraph(localProp).getSubtreeArc(star.lower[0]);
420 if(valences_.upper[curVert] && valences_.lower[curVert]) {
421 // not saddle neither extrema
422 graph_.getArc(currentArc).visit(curVert);
423 }
424 }
425 if(star.upper.size()) {
426 for(const idEdge dgNode : star.upper) {
427 dynGraph(localProp).setCorArc(dgNode, currentArc);
428 }
429 } else { // max
430 const idNode maxNode = graph_.makeNode(curVert);
431 graph_.closeArc(currentArc, maxNode);
432 }
433
434 visit(localProp, currentArc);
435
436 lazyUpdatePreimage(localProp, currentArc);
437 } else {
438
439 // locally aply the lazy one the current growing arc
440 for(const idEdge e : star.lower) {
441 const idSuperArc a = dynGraph(localProp).getNode(e)->findRootArc();
442 if(!lazy_.isEmpty(a)) {
443 // process lazy
444 // sort both list
445 // for each:
446 // if del < add: delete in real RG
447 // if add < del: add in real RG
448 // else: drop both, computation avoided
449 lazyApply(localProp, a);
450 }
451 }
452#else
453 {
454#endif
455 bool isJoin = false;
456 comp.lower = lowerComps(star.lower, localProp);
457 if(comp.lower.size() == 1) { // regular
458 currentArc = (*comp.lower.begin())->getCorArc();
459 } else if(comp.lower.size() > 1) { // join saddle
460 const idNode sadNode = graph_.makeNode(curVert);
461 currentArc = graph_.openArc(sadNode, localProp);
462 mergeAtSaddle(sadNode, comp.lower);
463 isJoin = true;
464 }
465
466 graph_.visit(curVert, currentArc);
467 propagations_.visit(curVert, localProp);
468 updatePreimage(localProp, currentArc);
469
470 comp.upper = upperComps(star.upper, localProp);
471 if(!comp.upper.size()) { // max
472 const idNode maxNode = graph_.makeNode(curVert);
473 graph_.closeArc(currentArc, maxNode);
474 } else if(comp.upper.size() < 2) {
475 if(!isJoin) {
476 // this arc is not empty
477 graph_.getArc(currentArc).visit(curVert);
478 }
479 } else {
480 if(isJoin) {
481 graph_.getArc(currentArc).hide();
482 } else { // split
483 const idNode splitNode = graph_.makeNode(curVert);
484 graph_.closeArc(currentArc, splitNode);
485 }
486 splitAtSaddle(localProp, comp.upper);
487 }
488 }
489 } // end for each vertex
490}
491
492template <typename ScalarType, typename triangulationType>
494 const Propagation *const localProp, Star &star) const {
495
496 star.lower.clear();
497 star.upper.clear();
498
499 const idEdge nbAdjEdges
500 = mesh_.getVertexEdgeNumber(localProp->getCurVertex());
501 star.lower.reserve(nbAdjEdges);
502 star.upper.reserve(nbAdjEdges);
503
504 for(idEdge e = 0; e < nbAdjEdges; ++e) {
505 idEdge edgeId;
506 mesh_.getVertexEdge(localProp->getCurVertex(), e, edgeId);
507 idVertex edgeLowerVert, edgeUpperVert;
508 std::tie(edgeLowerVert, edgeUpperVert)
509 = mesh_.getOrderedEdge(edgeId, localProp->goUp());
510 if(edgeLowerVert == localProp->getCurVertex()) {
511 star.upper.emplace_back(edgeId);
512 } else {
513 star.lower.emplace_back(edgeId);
514 }
515 }
516}
517
518template <typename ScalarType, typename triangulationType>
519std::set<ttk::ftr::DynGraphNode<ttk::ftr::idVertex> *>
521 const std::vector<idEdge> &finishingEdges,
522 const Propagation *const localProp) {
523 return dynGraph(localProp).findRoot(finishingEdges);
524}
525
526template <typename ScalarType, typename triangulationType>
527std::set<ttk::ftr::DynGraphNode<ttk::ftr::idVertex> *>
529 const std::vector<idEdge> &startingEdges,
530 const Propagation *const localProp) {
531 return dynGraph(localProp).findRoot(startingEdges);
532}
533
534template <typename ScalarType, typename triangulationType>
536 const std::vector<DynGraphNode<idVertex> *> &compVect) {
537 for(const auto *dgNode : compVect) {
538 const idSuperArc arc = dgNode->getCorArc();
539 if(arc != nullSuperArc && !graph_.getArc(arc).isVisible()) {
540 return true;
541 }
542 }
543 return false;
544}
545
546template <typename ScalarType, typename triangulationType>
547std::pair<ttk::ftr::valence, ttk::ftr::valence>
549 const idVertex curVert,
550 LocalForests &localForests,
551 const VertCompFN &comp) {
552 // traduce edge id in a local id for the forests
553 std::unordered_map<idEdge, std::size_t> mapNeighDown, mapNeighUp;
554 std::size_t nextId = 0;
555
556 localForests.up.reset();
557 localForests.down.reset();
558 const idVertex oldUpCC = localForests.up.getNbCC();
559 const idVertex oldDownCC = localForests.down.getNbCC();
560 const idCell nbTri = mesh_.getVertexTriangleNumber(curVert);
561 for(idCell t = 0; t < nbTri; ++t) {
562 idCell curTri;
563 mesh_.getVertexTriangle(curVert, t, curTri);
564 // edges found, max 2 per triangles.
565 std::size_t downSide[2], upSide[2];
566 unsigned char curDownSide = 0, curUpSide = 0;
567 for(idVertex v = 0; v < 3; ++v) {
568 idEdge triEdge;
569 mesh_.getTriangleEdge(curTri, v, triEdge);
570 idVertex v0, v1;
571 mesh_.getEdgeVertex(triEdge, 0, v0);
572 mesh_.getEdgeVertex(triEdge, 1, v1);
573
574 // only consider the edges in the star
575 if(v0 == curVert) {
576 if(comp(curVert, v1)) {
577 if(mapNeighUp.count(triEdge)) {
578 upSide[curUpSide++] = mapNeighUp[triEdge];
579 } else {
580 upSide[curUpSide++] = nextId;
581 mapNeighUp[triEdge] = nextId++;
582 }
583 } else {
584 if(mapNeighDown.count(triEdge)) {
585 downSide[curDownSide++] = mapNeighDown[triEdge];
586 } else {
587 downSide[curDownSide++] = nextId;
588 mapNeighDown[triEdge] = nextId++;
589 }
590 }
591 } else if(v1 == curVert) {
592 if(comp(curVert, v0)) {
593 if(mapNeighUp.count(triEdge)) {
594 upSide[curUpSide++] = mapNeighUp[triEdge];
595 } else {
596 upSide[curUpSide++] = nextId;
597 mapNeighUp[triEdge] = nextId++;
598 }
599 } else {
600 if(mapNeighDown.count(triEdge)) {
601 downSide[curDownSide++] = mapNeighDown[triEdge];
602 } else {
603 downSide[curDownSide++] = nextId;
604 mapNeighDown[triEdge] = nextId++;
605 }
606 }
607 }
608 }
609
610 // if both edges of the triangle were up or down, we add a link btwn
611 // them This is how the number of component is reduced
612 if(curDownSide == 2) {
613 localForests.down.insertEdge(downSide[0], downSide[1], 0, nullSuperArc);
614 } else if(curUpSide == 2) {
615 localForests.up.insertEdge(upSide[0], upSide[1], 0, nullSuperArc);
616 }
617 }
618
619 const valence down
620 = mapNeighDown.size() - (oldDownCC - localForests.down.getNbCC());
621 const valence up = mapNeighUp.size() - (oldUpCC - localForests.up.getNbCC());
622 return {down, up};
623}
624
625template <typename ScalarType, typename triangulationType>
627 const Propagation *const localProp, const idSuperArc curArc) {
628 const idCell nbAdjTriangles
629 = mesh_.getVertexTriangleNumber(localProp->getCurVertex());
630
631 orderedTriangle oTriangle;
632
633 // TODO SORT TRANGLES HERE ?
634
635 for(idCell t = 0; t < nbAdjTriangles; ++t) {
636 // Classify current cell
637 idCell curTriangleid;
638 mesh_.getVertexTriangle(localProp->getCurVertex(), t, curTriangleid);
639
640 mesh_.getOrderedTriangle(curTriangleid, localProp->goUp(), oTriangle);
641 vertPosInTriangle const curVertPos
642 = getVertPosInTriangle(oTriangle, localProp);
643
644 // Update DynGraph
645 // We can have an end pos on an unvisited triangle
646 // in case of saddle points
647 switch(curVertPos) {
648 case vertPosInTriangle::Start:
649 updatePreimageStartCell(oTriangle, localProp, curArc);
650 break;
651 case vertPosInTriangle::Middle:
652 updatePreimageMiddleCell(oTriangle, localProp, curArc);
653 break;
654 case vertPosInTriangle::End:
655 updatePreimageEndCell(oTriangle, localProp, curArc);
656 break;
657 default:
658 std::cout << "[FTR]: update preimage error, unknown vertPos type"
659 << std::endl;
660 break;
661 }
662 }
663}
664
665template <typename ScalarType, typename triangulationType>
667 const orderedTriangle &oTriangle,
668 const Propagation *const localProp,
669 const idSuperArc curArc) {
670 const orderedEdge e0
671 = mesh_.getOrderedEdge(std::get<0>(oTriangle), localProp->goUp());
672 const orderedEdge e1
673 = mesh_.getOrderedEdge(std::get<1>(oTriangle), localProp->goUp());
674 const idVertex w = getWeight(e0, e1, localProp);
675
676 // this order for history
677 dynGraph(localProp).insertEdge(
678 std::get<1>(oTriangle), std::get<0>(oTriangle), w, curArc);
679}
680
681template <typename ScalarType, typename triangulationType>
683 updatePreimageMiddleCell(const orderedTriangle &oTriangle,
684 const Propagation *const localProp,
685 const idSuperArc curArc) {
686 // Check if exist ?
687 // If not, the triangle will be visited again once a merge have occurred.
688 // So we do not add the edge now
689 dynGraph(localProp).removeEdge(
690 std::get<0>(oTriangle), std::get<1>(oTriangle));
691
692 // keep history inside the dyngraph structure
693 dynGraph(localProp).setCorArc(std::get<0>(oTriangle), curArc);
694 // dynGraph(localProp).setCorArc(std::get<1>(oTriangle), curArc);
695
696 const orderedEdge e1
697 = mesh_.getOrderedEdge(std::get<1>(oTriangle), localProp->goUp());
698 const orderedEdge e2
699 = mesh_.getOrderedEdge(std::get<2>(oTriangle), localProp->goUp());
700 const idVertex w = getWeight(e1, e2, localProp);
701
702 // this order for history
703 dynGraph(localProp).insertEdge(
704 std::get<1>(oTriangle), std::get<2>(oTriangle), w, curArc);
705}
706
707template <typename ScalarType, typename triangulationType>
709 const orderedTriangle &oTriangle,
710 const Propagation *const localProp,
711 const idSuperArc curArc) {
712 dynGraph(localProp).removeEdge(
713 std::get<1>(oTriangle), std::get<2>(oTriangle));
714 dynGraph(localProp).setCorArc(std::get<1>(oTriangle), curArc);
715 // dynGraph(localProp).setCorArc(std::get<2>(oTriangle), curArc);
716}
717
718template <typename ScalarType, typename triangulationType>
720 const idVertex seed,
721 const idEdge neigEdge,
722 const idSuperArc curArc,
723 const Propagation *const localProp) {
724 idVertex v0;
725 idVertex v1;
726 mesh_.getEdgeVertex(neigEdge, 0, v0);
727 mesh_.getEdgeVertex(neigEdge, 1, v1);
728
729 const idVertex other = (v0 == seed) ? v1 : v0;
730
731 if(localProp->compare(seed, other)) {
732 dynGraph(localProp).setSubtreeArc(neigEdge, curArc);
733 }
734}
735
736#ifndef TTK_DISABLE_FTR_LAZY
737template <typename ScalarType, typename triangulationType>
739 Propagation *const localProp, const idSuperArc curArc) {
740 const idCell nbAdjTriangles
741 = mesh_.getVertexTriangleNumber(localProp->getCurVertex());
742
743 orderedTriangle oTriangle;
744
745 for(idCell t = 0; t < nbAdjTriangles; ++t) {
746 // Classify current cell
747 idCell curTriangleid;
748 mesh_.getVertexTriangle(localProp->getCurVertex(), t, curTriangleid);
749
750 mesh_.getOrderedTriangle(curTriangleid, localProp->goUp(), oTriangle);
751 vertPosInTriangle const curVertPos
752 = getVertPosInTriangle(oTriangle, localProp);
753
754 // Update DynGraph
755 // We can have an end pos on an unvisited triangle
756 // in case of saddle points
757 switch(curVertPos) {
758 case vertPosInTriangle::Start:
759 updateLazyStart(oTriangle, localProp, curArc);
760 break;
761 case vertPosInTriangle::Middle:
762 updateLazyMiddle(oTriangle, localProp, curArc);
763 break;
764 case vertPosInTriangle::End:
765 updateLazyEnd(oTriangle, localProp, curArc);
766 break;
767 default:
768 std::cout << "[FTR]: lazy update preimage error, unknown vertPos type"
769 << std::endl;
770 break;
771 }
772 }
773}
774
775template <typename ScalarType, typename triangulationType>
777 const orderedTriangle &oTriangle,
778 Propagation *const ttkNotUsed(localProp),
779 const idSuperArc curArc) {
780 lazy_.addEmplace(std::get<0>(oTriangle), std::get<1>(oTriangle), curArc);
781}
782
783template <typename ScalarType, typename triangulationType>
785 const orderedTriangle &oTriangle,
786 Propagation *const localProp,
787 const idSuperArc curArc) {
788 lazy_.delEmplace(std::get<0>(oTriangle), std::get<1>(oTriangle), curArc);
789 dynGraph(localProp).removeEdge(
790 std::get<0>(oTriangle), std::get<1>(oTriangle));
791 dynGraph(localProp).setCorArc(std::get<0>(oTriangle), curArc);
792 dynGraph(localProp).setCorArc(std::get<1>(oTriangle), curArc);
793 lazy_.addEmplace(std::get<1>(oTriangle), std::get<2>(oTriangle), curArc);
794}
795
796template <typename ScalarType, typename triangulationType>
798 const orderedTriangle &oTriangle,
799 Propagation *const localProp,
800 const idSuperArc curArc) {
801 lazy_.delEmplace(std::get<1>(oTriangle), std::get<2>(oTriangle), curArc);
802 dynGraph(localProp).removeEdge(
803 std::get<1>(oTriangle), std::get<2>(oTriangle));
804 dynGraph(localProp).setCorArc(std::get<1>(oTriangle), curArc);
805 dynGraph(localProp).setCorArc(std::get<2>(oTriangle), curArc);
806}
807
808template <typename ScalarType, typename triangulationType>
810 const Propagation *const localProp,
811 const linkEdge edge,
812 const idSuperArc arc) {
813 const orderedEdge e0
814 = mesh_.getOrderedEdge(std::get<0>(edge), localProp->goUp());
815 const orderedEdge e1
816 = mesh_.getOrderedEdge(std::get<1>(edge), localProp->goUp());
817 const idVertex w = getWeight(e0, e1, localProp);
818 dynGraph(localProp).insertEdge(std::get<1>(edge), std::get<0>(edge), w, arc);
819}
820
821template <typename ScalarType, typename triangulationType>
823 const Propagation *const localProp,
824 const linkEdge edge,
825 const idSuperArc ttkNotUsed(arc)) {
826 dynGraph(localProp).removeEdge(std::get<0>(edge), std::get<1>(edge));
827}
828
829template <typename ScalarType, typename triangulationType>
831 Propagation *const localProp, const idSuperArc a) {
832 auto add = lazy_.addGetNext(a);
833 while(add != nullLink) {
834 updateLazyAdd(localProp, add, a);
835 add = lazy_.addGetNext(a);
836 }
837}
838
839#endif
840
841template <typename ScalarType, typename triangulationType>
843 const idVertex seed,
844 const idSuperArc curArc,
845 const Propagation *const localProp) {
846 const idVertex nbEdgesNeigh = mesh_.getVertexEdgeNumber(seed);
847 for(idVertex nid = 0; nid < nbEdgesNeigh; ++nid) {
848 idEdge edgeId;
849 mesh_.getVertexEdge(seed, nid, edgeId);
850
851 updateDynGraphCurArc(seed, edgeId, curArc, localProp);
852 }
853}
854
855template <typename ScalarType, typename triangulationType>
857 Propagation *const localProp, const std::vector<idEdge> &upperEdges) {
858 const idVertex curVert = localProp->getCurVertex();
859 for(const idEdge e : upperEdges) {
860 idVertex v0, v1;
861 mesh_.getEdgeVertex(e, 0, v0);
862 mesh_.getEdgeVertex(e, 1, v1);
863 const idVertex other = (v0 == curVert) ? v1 : v0;
864 if(localProp->compare(curVert, other)) {
865 if(!propagations_.willVisit(other, localProp)) {
866 localProp->addNewVertex(other);
867 propagations_.toVisit(other, localProp);
868 }
869 }
870 }
871}
872
873template <typename ScalarType, typename triangulationType>
875 Propagation *const localProp, const std::vector<idEdge> &starVect) {
876 const idVertex curSaddle = localProp->getCurVertex();
877 AtomicUF *curId = localProp->getId();
878 valence decr = 0;
879
880 // NOTE:
881 // Using propagation id allows to decrement by the number of time this
882 // propagation has reached the saddle, even if the propagation take care
883 // of several of these arcs (after a Hole-split).
884 for(idEdge const edgeId : starVect) {
885 const idSuperArc edgeArc = dynGraph(localProp).getSubtreeArc(edgeId);
886 if(edgeArc == nullSuperArc) {
887 continue;
888 }
889 AtomicUF *tmpId = graph_.getArc(edgeArc).getPropagation()->getId();
890 if(tmpId == curId) {
891 graph_.getArc(edgeArc).setEnd(curSaddle);
892 ++decr;
893 }
894 }
895
896#if defined(__GNUC__)
897#pragma GCC diagnostic push
898#pragma GCC diagnostic ignored "-Wunused-value"
899#endif // __GNUC__
900
901 valence oldVal = 0;
902 if(localProp->goUp()) {
903 // for gcc 4.8 and old openMP
904 valence *const vd = &graph_.valDown_[curSaddle];
905#ifdef TTK_ENABLE_OPENMP4
906#pragma omp atomic capture
907#endif
908 {
909 oldVal = *vd;
910 *vd -= decr;
911 }
912
913 } else {
914 valence *const vu = &graph_.valUp_[curSaddle];
915#ifdef TTK_ENABLE_OPENMP4
916#pragma omp atomic capture
917#endif
918 {
919 oldVal = *vu;
920 *vu -= decr;
921 }
922 }
923
924 if(oldVal == -1) {
925 // First task to touch this saddle, compute the valence
926 idVertex const totalVal = starVect.size();
927 valence newVal = 0;
928 if(localProp->goUp()) {
929 valence *const vd = &graph_.valDown_[curSaddle];
930#ifdef TTK_ENABLE_OPENMP4
931#pragma omp atomic capture
932#endif
933 {
934 newVal = *vd;
935 *vd += (totalVal + 1);
936 }
937
938 } else {
939 valence *const vu = &graph_.valUp_[curSaddle];
940#ifdef TTK_ENABLE_OPENMP4
941#pragma omp atomic capture
942#endif
943 {
944 newVal = *vu;
945 *vu += (totalVal + 1);
946 }
947 }
948 oldVal = decr + newVal + (totalVal + 1);
949 }
950
951#if defined(__GNUC__)
952#pragma GCC diagnostic pop
953#endif // __GNUC__
954
955 return oldVal == decr;
956}
957
958template <typename ScalarType, typename triangulationType>
961 const idNode saddleId,
962 Propagation *localProp,
963 const std::set<DynGraphNode<idVertex> *> &compVect) {
964
965#ifndef TTK_ENABLE_KAMIKAZE
966 if(compVect.size() < 2) {
967 std::cerr << "[FTR]: merge at saddle with only one lower CC" << std::endl;
968 }
969#endif
970
971 idSuperArc visibleClosed = 0;
972 for(auto *dgNode : compVect) {
973 // read in the history (lower comp already contains roots)
974 const idSuperArc endingArc = dgNode->getCorArc();
975 graph_.closeArc(endingArc, saddleId);
976 PRINT("/" << graph_.printArc(endingArc));
977 if(graph_.getArc(endingArc).isVisible()) {
978 ++visibleClosed;
979 }
980 Propagation *arcProp = graph_.getArc(endingArc).getPropagation();
981 localProp->merge(*arcProp);
982 }
983 return visibleClosed;
984}
985
986template <typename ScalarType, typename triangulationType>
989 const idNode saddleId, const std::set<DynGraphNode<idVertex> *> &compVect) {
990 // version for the sequential arc growth, do not merge the propagations
991
992#ifndef TTK_ENABLE_KAMIKAZE
993 if(compVect.size() < 2) {
994 std::cerr << "[FTR]: merge at saddle with only one lower CC" << std::endl;
995 }
996#endif
997
998 idSuperArc visibleClosed = 0;
999 for(auto *dgNode : compVect) {
1000 const idSuperArc endingArc = dgNode->getCorArc();
1001 graph_.closeArc(endingArc, saddleId);
1002 PRINT("/" << graph_.printArc(endingArc));
1003 if(graph_.getArc(endingArc).isVisible()) {
1004 ++visibleClosed;
1005 }
1006 }
1007 return visibleClosed;
1008}
1009
1010template <typename ScalarType, typename triangulationType>
1012 Propagation *const localProp,
1013 const std::set<DynGraphNode<idVertex> *> &compVect,
1014 const bool hidden) {
1015 const idVertex curVert = localProp->getCurVertex();
1016 const idNode curNode = graph_.getNodeId(curVert);
1017
1018 for(auto *dgNode : compVect) {
1019 const idSuperArc newArc = graph_.openArc(curNode, localProp);
1020 dgNode->setRootArc(newArc);
1021 visit(localProp, newArc);
1022
1023 if(hidden)
1024 graph_.getArc(newArc).hide();
1025
1026 PRINT("v" << graph_.printArc(newArc));
1027 }
1028}
1029
1030template <typename ScalarType, typename triangulationType>
1032 Propagation *const localProp, const idSuperArc curArc) {
1033 const idVertex curVert = localProp->getCurVertex();
1034 Visit opposite;
1035 idSuperArc retArc;
1036 // #pragma omp critical
1037 {
1038 propagations_.visit(curVert, localProp);
1039 opposite = propagations_.visitOpposite(curVert, localProp);
1040 bool done;
1041#ifdef TTK_ENABLE_OPENMP4
1042#pragma omp atomic read seq_cst
1043#endif
1044 done = opposite.done;
1045 if(!done) {
1046 graph_.visit(curVert, curArc);
1047 retArc = nullSuperArc;
1048 } else {
1049 retArc = graph_.getArcId(curVert);
1050 }
1051 }
1052 return retArc;
1053}
1054
1056
1057template <typename ScalarType, typename triangulationType>
1060 const idVertex leaf, const bool fromMin) {
1061 VertCompFN comp;
1062 if(fromMin)
1063 comp = [&](idVertex a, idVertex b) { return scalars_.isHigher(a, b); };
1064 else
1065 comp = [&](idVertex a, idVertex b) { return scalars_.isLower(a, b); };
1066 return propagations_.newPropagation(leaf, comp, fromMin);
1067}
1068
1069template <typename ScalarType, typename triangulationType>
1071 const orderedEdge &e0,
1072 const orderedEdge &e1,
1073 const Propagation *const localProp) {
1074 const idVertex end0 = std::get<1>(e0);
1075 const idVertex end1 = std::get<1>(e1);
1076
1077 if(localProp->compare(end0, end1)) {
1078 if(localProp->goDown()) {
1079 return -scalars_.getMirror(end0);
1080 }
1081 return scalars_.getMirror(end0);
1082 }
1083
1084 if(localProp->goDown()) {
1085 return -scalars_.getMirror(end1);
1086 }
1087 return scalars_.getMirror(end1);
1088}
1089
1090template <typename ScalarType, typename triangulationType>
1093 const orderedTriangle &oTriangle,
1094 const Propagation *const localProp) const {
1095 orderedEdge firstEdge
1096 = mesh_.getOrderedEdge(std::get<0>(oTriangle), localProp->goUp());
1097 if(std::get<0>(firstEdge) == localProp->getCurVertex()) {
1098 return vertPosInTriangle::Start;
1099 } else if(std::get<1>(firstEdge) == localProp->getCurVertex()) {
1100 return vertPosInTriangle::Middle;
1101 } else {
1102 return vertPosInTriangle::End;
1103 }
1104}
1105
1106template <typename ScalarType, typename triangulationType>
1109 const orderedTriangle &oTriangle,
1110 const Propagation *const localProp) const {
1111 const orderedEdge &higherEdge
1112 = mesh_.getOrderedEdge(std::get<1>(oTriangle), localProp->goUp());
1113 return std::get<1>(higherEdge);
1114}
1115
1116template <typename ScalarType, typename triangulationType>
1119 const orderedTriangle oTri, const idVertex v0, const idVertex v1) {
1120 idVertex edge0Vert, edge1Vert;
1121
1122 mesh_.getEdgeVertex(std::get<0>(oTri), 0, edge0Vert);
1123 mesh_.getEdgeVertex(std::get<0>(oTri), 1, edge1Vert);
1124 if((edge0Vert == v0 && edge1Vert == v1)
1125 || (edge0Vert == v1 && edge1Vert == v0)) {
1126 return std::get<0>(oTri);
1127 }
1128
1129 mesh_.getEdgeVertex(std::get<1>(oTri), 0, edge0Vert);
1130 mesh_.getEdgeVertex(std::get<1>(oTri), 1, edge1Vert);
1131 if((edge0Vert == v0 && edge1Vert == v1)
1132 || (edge0Vert == v1 && edge1Vert == v0)) {
1133 return std::get<1>(oTri);
1134 }
1135
1136#ifndef TTK_ENABLE_KAMIKAZE
1137 mesh_.getEdgeVertex(std::get<2>(oTri), 0, edge0Vert);
1138 mesh_.getEdgeVertex(std::get<2>(oTri), 1, edge1Vert);
1139 if((edge0Vert == v0 && edge1Vert == v1)
1140 || (edge0Vert == v1 && edge1Vert == v0)) {
1141 return std::get<2>(oTri);
1142 }
1143
1144 std::cout << "[FTR]: edge not found in triangle " << v0 << " " << v1
1145 << std::endl;
1146 return nullEdge;
1147#else
1148 return std::get<2>(oTri);
1149#endif
1150}
#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
#define PRINT(msg)
TTK processing package that efficiently computes the contour tree of scalar data and more (data segme...
TTK FTRGraph processing package.
Definition FTRGraph.h:77
TTK fTRGraph propagation management with Fibonacci heaps.
vertPosInTriangle
position of a vertex in a triangle
long unsigned int idSuperArc
SuperArc index in vect_superArcs_.
SimplexId idVertex
Vertex index in scalars_.
SimplexId idEdge
Edge index in vect_edgeList_.
T begin(std::pair< T, T > &p)
Definition ripserpy.cpp:468