17 int computePersistenceDiagram,
const SimplexId *offsets) {
21 if(resumeProgressive_) {
22 resumeProgressive(computePersistenceDiagram, offsets);
28 decimationLevel_ = startingDecimationLevel_;
29 multiresTriangulation_.setDecimationLevel(0);
30 const SimplexId vertexNumber = multiresTriangulation_.getVertexNumber();
32#ifdef TTK_ENABLE_KAMIKAZE
33 if(vertexNumber == 0) {
34 this->printErr(
"No points in triangulation");
42 clearResumableState();
44 const auto dim = multiresTriangulation_.getDimensionality();
45 const size_t maxNeigh = dim == 3 ? 14 : (dim == 2 ? 6 : 0);
47 std::vector<std::vector<SimplexId>> saddleCCMin{}, saddleCCMax{};
48 std::vector<std::vector<SimplexId>> vertexRepresentativesMin{},
49 vertexRepresentativesMax{};
50 std::vector<polarity> isUpToDateMin{}, isUpToDateMax{};
51 std::vector<polarity> toPropagateMin{}, toPropagateMax{};
52 std::vector<char> vertexTypes{};
54 if(computePersistenceDiagram) {
55 saddleCCMin.resize(vertexNumber);
56 saddleCCMax.resize(vertexNumber);
57 vertexRepresentativesMin.resize(vertexNumber);
58 vertexRepresentativesMax.resize(vertexNumber);
59 toPropagateMin.resize(vertexNumber, 0);
60 toPropagateMax.resize(vertexNumber, 0);
61 isUpToDateMin.resize(vertexNumber, 0);
62 isUpToDateMax.resize(vertexNumber, 0);
68 std::vector<uint8_t> vertexLink(vertexNumber);
70 std::vector<DynamicTree> link(vertexNumber);
71 std::vector<polarity> isNew(vertexNumber, 255);
72 std::vector<std::vector<std::pair<polarity, polarity>>> vertexLinkPolarity(
74 std::vector<polarity> toProcess(vertexNumber, 0), toReprocess{};
76 if(this->startingDecimationLevel_ > this->stoppingDecimationLevel_
77 || this->isResumable_) {
79 toReprocess.resize(vertexNumber, 0);
83 std::vector<Lock> vertLockMin(vertexNumber), vertLockMax(vertexNumber);
86 if(preallocateMemory_) {
88 printMsg(
"Pre-allocating data structures", 0, 0, threadNumber_,
90 for(
SimplexId i = 0; i < vertexNumber; ++i) {
91 vertexLinkPolarity[i].reserve(maxNeigh);
92 link[i].alloc(maxNeigh);
94 printMsg(
"Pre-allocating data structures", 1,
99 printMsg(
"Total memory allocation", 1, tm_allocation, threadNumber_);
102 std::vector<SimplexId> boundReps{};
103 multiresTriangulation_.findBoundaryRepresentatives(boundReps);
105#ifdef TTK_ENABLE_OPENMP
106#pragma omp parallel for num_threads(threadNumber_)
108 for(
size_t i = 0; i < boundReps.size(); i++) {
109 if(boundReps[i] != -1) {
110 buildVertexLinkByBoundary(boundReps[i], vertexLinkByBoundaryType);
114 printMsg(this->resolutionInfoString(), 0,
117 multiresTriangulation_.setDecimationLevel(decimationLevel_);
119 if(computePersistenceDiagram) {
120 initSaddleSeeds(isNew, vertexLinkPolarity, toPropagateMin, toPropagateMax,
121 toProcess, link, vertexLink, vertexLinkByBoundaryType,
122 saddleCCMin, saddleCCMax, offsets);
123 initPropagation(toPropagateMin, toPropagateMax, vertexRepresentativesMin,
124 vertexRepresentativesMax, saddleCCMin, saddleCCMax,
125 vertLockMin, vertLockMax, isUpToDateMin, isUpToDateMax,
129 computePersistencePairsFromSaddles(
130 CTDiagram_, offsets, vertexRepresentativesMin, vertexRepresentativesMax,
131 toPropagateMin, toPropagateMax);
133 initCriticalPoints(isNew, vertexLinkPolarity, toProcess, toReprocess, link,
134 vertexLink, vertexLinkByBoundaryType, vertexTypes,
138 printMsg(this->resolutionInfoString(), 1,
143 > 0.9 * this->timeLimit_);
145 while(decimationLevel_ > stoppingDecimationLevel_) {
148 multiresTriangulation_.setDecimationLevel(decimationLevel_);
150 printMsg(this->resolutionInfoString(), 0,
154 if(computePersistenceDiagram) {
155 updateSaddleSeeds(isNew, vertexLinkPolarity, toPropagateMin,
156 toPropagateMax, toProcess, toReprocess, link,
157 vertexLink, vertexLinkByBoundaryType, saddleCCMin,
158 saddleCCMax, isUpToDateMin, isUpToDateMax, offsets);
159 updatePropagation(toPropagateMin, toPropagateMax,
160 vertexRepresentativesMin, vertexRepresentativesMax,
161 saddleCCMin, saddleCCMax, vertLockMin, vertLockMax,
162 isUpToDateMin, isUpToDateMax, offsets);
163 computePersistencePairsFromSaddles(
164 CTDiagram_, offsets, vertexRepresentativesMin, vertexRepresentativesMax,
165 toPropagateMin, toPropagateMax);
167 updateCriticalPoints(isNew, vertexLinkPolarity, toProcess, toReprocess,
168 link, vertexLink, vertexLinkByBoundaryType,
169 vertexTypes, offsets);
172 const auto itDuration = tmIter.getElapsedTime();
173 const auto nextItDuration
174 = predictNextIterationDuration(itDuration, CTDiagram_.size() + 1);
176 printMsg(this->resolutionInfoString(), 1,
180 stopComputationIf(timer.
getElapsedTime() + nextItDuration - tm_allocation
183 this->
printMsg(
"current iteration", 1.0, itDuration, 1,
185 this->
printMsg(
"next iteration duration prediction", 1.0, nextItDuration, 1,
190 if(computePersistenceDiagram) {
191 CTDiagram_.emplace_back(this->globalMin_, this->globalMax_, -1);
195 if(this->isResumable_ and decimationLevel_ > 0) {
196 if(computePersistenceDiagram) {
197 this->vertexRepresentativesMax_ = std::move(vertexRepresentativesMax);
198 this->vertexRepresentativesMin_ = std::move(vertexRepresentativesMin);
199 this->saddleCCMin_ = std::move(saddleCCMin);
200 this->saddleCCMax_ = std::move(saddleCCMax);
202 this->isNew_ = std::move(isNew);
203 this->toProcess_ = std::move(toProcess);
204 this->toReprocess_ = std::move(toReprocess);
205 this->vertexLinkPolarity_ = std::move(vertexLinkPolarity);
206 this->link_ = std::move(link);
207 this->vertexLink_ = std::move(vertexLink);
208 this->vertexLinkByBoundaryType_ = std::move(vertexLinkByBoundaryType);
209 this->resumeProgressive_ =
true;
213 vertexTypes_ = std::move(vertexTypes);
216 sortPersistenceDiagram2(CTDiagram_, offsets);
219 "Total", 1.0, timer.
getElapsedTime() - tm_allocation, this->threadNumber_);
226 const auto vertexNumber = multiresTriangulation_.getVertexNumber();
229 "Resuming computation from resolution level "
230 + std::to_string(multiresTriangulation_.DL_to_RL(decimationLevel_))
233 multiresTriangulation_.DL_to_RL(stoppingDecimationLevel_)));
236 std::vector<Lock> vertLockMin(vertexNumber), vertLockMax(vertexNumber);
238 std::vector<polarity> toPropagateMin{}, toPropagateMax{};
239 std::vector<polarity> isUpToDateMin{}, isUpToDateMax{};
241 if(computePersistenceDiagram) {
242 toPropagateMin.resize(vertexNumber, 0);
243 toPropagateMax.resize(vertexNumber, 0);
244 isUpToDateMin.resize(vertexNumber, 0);
245 isUpToDateMax.resize(vertexNumber, 0);
250 while(this->decimationLevel_ > this->stoppingDecimationLevel_) {
252 this->decimationLevel_--;
253 multiresTriangulation_.setDecimationLevel(this->decimationLevel_);
256 if(computePersistenceDiagram) {
257 updateSaddleSeeds(isNew_, vertexLinkPolarity_, toPropagateMin,
258 toPropagateMax, toProcess_, toReprocess_, link_,
259 vertexLink_, vertexLinkByBoundaryType_, saddleCCMin_,
260 saddleCCMax_, isUpToDateMin, isUpToDateMax, offsets);
261 updatePropagation(toPropagateMin, toPropagateMax,
262 vertexRepresentativesMin_, vertexRepresentativesMax_,
263 saddleCCMin_, saddleCCMax_, vertLockMin, vertLockMax,
264 isUpToDateMin, isUpToDateMax, offsets);
265 computePersistencePairsFromSaddles(
266 CTDiagram_, offsets, vertexRepresentativesMin_,
267 vertexRepresentativesMax_, toPropagateMin, toPropagateMax);
269 updateCriticalPoints(isNew_, vertexLinkPolarity_, toProcess_,
270 toReprocess_, link_, vertexLink_,
271 vertexLinkByBoundaryType_, vertexTypes_, offsets);
274 const auto itDuration = tmIter.getElapsedTime();
275 const auto nextItDuration
276 = predictNextIterationDuration(itDuration, CTDiagram_.size() + 1);
279 this->threadNumber_);
287 if(computePersistenceDiagram) {
288 CTDiagram_.emplace_back(this->globalMin_, this->globalMax_, -1);
291 sortPersistenceDiagram2(CTDiagram_, offsets);
296 if(this->decimationLevel_ == 0) {
297 clearResumableState();
304 std::vector<PersistencePair> &CTDiagram,
306 std::vector<std::vector<SimplexId>> &vertexRepresentativesMin,
307 std::vector<std::vector<SimplexId>> &vertexRepresentativesMax,
308 const std::vector<polarity> &toPropagateMin,
309 const std::vector<polarity> &toPropagateMax)
const {
312 std::vector<triplet> tripletsMax{}, tripletsMin{};
313 const SimplexId nbDecVert = multiresTriangulation_.getDecimatedVertexNumber();
315 for(
SimplexId localId = 0; localId < nbDecVert; localId++) {
317 = multiresTriangulation_.localToGlobalVertexId(localId);
318 if(toPropagateMin[globalId]) {
319 getTripletsFromSaddles(globalId, tripletsMin, vertexRepresentativesMin);
321 if(toPropagateMax[globalId]) {
322 getTripletsFromSaddles(globalId, tripletsMax, vertexRepresentativesMax);
326 this->
printMsg(
"TRIPLETS", 1.0, timer.getElapsedTime(), this->threadNumber_,
329 double const tm_pairs = timer.getElapsedTime();
331 sortTriplets(tripletsMax, offsets,
true);
332 sortTriplets(tripletsMin, offsets,
false);
334 const auto tm_sort = timer.getElapsedTime();
335 this->
printMsg(
"TRIPLETS SORT", 1.0, tm_sort - tm_pairs, this->threadNumber_,
338 typename std::remove_reference<
decltype(CTDiagram)>::type CTDiagramMin{},
341#ifdef TTK_ENABLE_OPENMP
342#pragma omp parallel sections num_threads(threadNumber_)
345#ifdef TTK_ENABLE_OPENMP
348 tripletsToPersistencePairs(
349 CTDiagramMin, vertexRepresentativesMax, tripletsMax, offsets,
true);
350#ifdef TTK_ENABLE_OPENMP
353 tripletsToPersistencePairs(
354 CTDiagramMax, vertexRepresentativesMin, tripletsMin, offsets,
false);
356 CTDiagram = std::move(CTDiagramMin);
357 CTDiagram.insert(CTDiagram.end(), CTDiagramMax.begin(), CTDiagramMax.end());
359 this->
printMsg(
"PAIRS", 1.0, timer.getElapsedTime() - tm_sort,
498 std::vector<polarity> &isNew,
499 std::vector<std::vector<std::pair<polarity, polarity>>> &vertexLinkPolarity,
500 std::vector<polarity> &toProcess,
501 std::vector<polarity> &toReprocess,
502 std::vector<DynamicTree> &link,
503 std::vector<uint8_t> &vertexLink,
505 std::vector<char> &vertexTypes,
509 const auto nDecVerts = multiresTriangulation_.getDecimatedVertexNumber();
512#ifdef TTK_ENABLE_OPENMP
513#pragma omp parallel for num_threads(threadNumber_)
515 for(
SimplexId localId = 0; localId < nDecVerts; localId++) {
517 = multiresTriangulation_.localToGlobalVertexId(localId);
518 if(isNew[globalId]) {
519 if(decimationLevel_ > stoppingDecimationLevel_ || isResumable_) {
520 buildVertexLinkPolarity(
521 globalId, vertexLinkPolarity[globalId], offsets);
524 getMonotonyChangeByOldPointCP(globalId, isNew, toProcess, toReprocess,
525 vertexLinkPolarity[globalId], offsets);
534#ifdef TTK_ENABLE_OPENMP
535#pragma omp parallel for num_threads(threadNumber_)
537 for(
int i = 0; i < nDecVerts; i++) {
538 SimplexId const globalId = multiresTriangulation_.localToGlobalVertexId(i);
540 if(isNew[globalId]) {
541 if(toProcess[globalId]) {
542 initDynamicLink(globalId, vertexLinkPolarity[globalId],
543 vertexLink[globalId], link[globalId],
544 vertexLinkByBoundaryType, offsets);
545 vertexTypes[globalId]
546 = getCriticalTypeFromLink(globalId, vertexLinkPolarity[globalId],
547 link[globalId], toReprocess[globalId]);
549 isNew[globalId] =
false;
552 if(toReprocess[globalId]) {
553 if(toProcess[globalId]) {
554 updateDynamicLink(link[globalId], vertexLinkPolarity[globalId],
555 vertexLinkByBoundaryType[vertexLink[globalId]]);
557 updateLinkPolarity(globalId, vertexLinkPolarity[globalId], offsets);
558 initDynamicLink(globalId, vertexLinkPolarity[globalId],
559 vertexLink[globalId], link[globalId],
560 vertexLinkByBoundaryType, offsets);
561 toProcess[globalId] = 255;
563 vertexTypes[globalId]
564 = getCriticalTypeFromLink(globalId, vertexLinkPolarity[globalId],
565 link[globalId], toReprocess[globalId]);
566 toReprocess[globalId] = 0;
572 this->
printMsg(
"CRITICAL POINTS UPDATE", 1.0,
578 std::vector<polarity> &isNew,
579 std::vector<std::vector<std::pair<polarity, polarity>>> &vertexLinkPolarity,
580 std::vector<polarity> &toPropagateMin,
581 std::vector<polarity> &toPropagateMax,
582 std::vector<polarity> &toProcess,
583 std::vector<polarity> &toReprocess,
584 std::vector<DynamicTree> &link,
585 std::vector<uint8_t> &vertexLink,
587 std::vector<std::vector<SimplexId>> &saddleCCMin,
588 std::vector<std::vector<SimplexId>> &saddleCCMax,
589 std::vector<polarity> &isUpdatedMin,
590 std::vector<polarity> &isUpdatedMax,
594 const auto nDecVerts = multiresTriangulation_.getDecimatedVertexNumber();
597#ifdef TTK_ENABLE_OPENMP
598#pragma omp parallel for num_threads(threadNumber_)
600 for(
SimplexId localId = 0; localId < nDecVerts; localId++) {
602 = multiresTriangulation_.localToGlobalVertexId(localId);
603 if(isNew[globalId]) {
604 if(decimationLevel_ > stoppingDecimationLevel_ || isResumable_) {
605 buildVertexLinkPolarity(
606 globalId, vertexLinkPolarity[globalId], offsets);
609 getMonotonyChangeByOldPointCP(globalId, isNew, toProcess, toReprocess,
610 vertexLinkPolarity[globalId], offsets);
619#ifdef TTK_ENABLE_OPENMP
620#pragma omp parallel for num_threads(threadNumber_)
622 for(
int i = 0; i < nDecVerts; i++) {
623 SimplexId const globalId = multiresTriangulation_.localToGlobalVertexId(i);
625 if(isNew[globalId]) {
626 if(toProcess[globalId]) {
627 initDynamicLink(globalId, vertexLinkPolarity[globalId],
628 vertexLink[globalId], link[globalId],
629 vertexLinkByBoundaryType, offsets);
630 getValencesFromLink(globalId, vertexLinkPolarity[globalId],
631 link[globalId], toPropagateMin, toPropagateMax,
632 saddleCCMin, saddleCCMax);
634 isNew[globalId] =
false;
637 if(toReprocess[globalId]) {
638 if(toProcess[globalId]) {
639 updateDynamicLink(link[globalId], vertexLinkPolarity[globalId],
640 vertexLinkByBoundaryType[vertexLink[globalId]]);
642 updateLinkPolarity(globalId, vertexLinkPolarity[globalId], offsets);
643 initDynamicLink(globalId, vertexLinkPolarity[globalId],
644 vertexLink[globalId], link[globalId],
645 vertexLinkByBoundaryType, offsets);
646 toProcess[globalId] = 255;
648 getValencesFromLink(globalId, vertexLinkPolarity[globalId],
649 link[globalId], toPropagateMin, toPropagateMax,
650 saddleCCMin, saddleCCMax);
651 toReprocess[globalId] = 0;
656 isUpdatedMin[globalId] = 0;
657 isUpdatedMax[globalId] = 0;
660 this->
printMsg(
"CRITICAL POINTS UPDATE", 1.0,
707 std::vector<Lock> &vertLock,
708 std::vector<polarity> &toPropagate,
709 std::vector<std::vector<SimplexId>> &vertexRepresentatives,
710 std::vector<std::vector<SimplexId>> &saddleCC,
711 std::vector<polarity> &isUpdated,
712 std::vector<SimplexId> &globalExtremum,
714 const bool splitTree)
const {
716 auto &toProp = toPropagate[vertexId];
717 auto &reps = vertexRepresentatives[vertexId];
718 auto &updated = isUpdated[vertexId];
721 return (offsets[a] > offsets[b]) == splitTree;
728 if(this->threadNumber_ > 1) {
729 vertLock[vertexId].lock();
733 const auto &CC = saddleCC[vertexId];
735 reps.reserve(CC.size());
736 for(
size_t r = 0; r < CC.size(); r++) {
739 multiresTriangulation_.getVertexNeighbor(vertexId, localId, neighborId);
740 SimplexId const ret = propagateFromSaddles(
741 neighborId, vertLock, toPropagate, vertexRepresentatives, saddleCC,
742 isUpdated, globalExtremum, offsets, splitTree);
743 reps.emplace_back(ret);
746 if(reps.size() > 1) {
748 std::sort(reps.begin(), reps.end(), gt);
749 const auto last = std::unique(reps.begin(), reps.end());
750 reps.erase(last, reps.end());
754 if(this->threadNumber_ > 1) {
755 vertLock[vertexId].unlock();
764 = multiresTriangulation_.getVertexNeighborNumber(vertexId);
766 for(
SimplexId i = 0; i < neighborNumber; i++) {
768 multiresTriangulation_.getVertexNeighbor(vertexId, i, neighborId);
769 if(gt(neighborId, maxNeighbor)) {
770 maxNeighbor = neighborId;
773 if(maxNeighbor != vertexId) {
774 ret = propagateFromSaddles(maxNeighbor, vertLock, toPropagate,
775 vertexRepresentatives, saddleCC, isUpdated,
776 globalExtremum, offsets, splitTree);
778#ifdef TTK_ENABLE_OPENMP
779 const auto tid = omp_get_thread_num();
783 if(gt(vertexId, globalExtremum[tid])) {
784 globalExtremum[tid] = vertexId;
790 if(this->threadNumber_ > 1) {
791 vertLock[vertexId].unlock();
798 std::vector<polarity> &isNew,
799 std::vector<std::vector<std::pair<polarity, polarity>>> &vertexLinkPolarity,
800 std::vector<polarity> &toProcess,
801 std::vector<polarity> &toReprocess,
802 std::vector<DynamicTree> &link,
803 std::vector<uint8_t> &vertexLink,
805 std::vector<char> &vertexTypes,
809 const size_t nDecVerts = multiresTriangulation_.getDecimatedVertexNumber();
812#ifdef TTK_ENABLE_OPENMP
813#pragma omp parallel for num_threads(threadNumber_)
815 for(
size_t i = 0; i < nDecVerts; i++) {
816 SimplexId const globalId = multiresTriangulation_.localToGlobalVertexId(i);
817 buildVertexLinkPolarity(globalId, vertexLinkPolarity[globalId], offsets);
818 initDynamicLink(globalId, vertexLinkPolarity[globalId],
819 vertexLink[globalId], link[globalId],
820 vertexLinkByBoundaryType, offsets);
821 vertexTypes[globalId]
822 = getCriticalTypeFromLink(globalId, vertexLinkPolarity[globalId],
823 link[globalId], toReprocess[globalId]);
824 toProcess[globalId] = 255;
828 this->
printMsg(
"initial critical types", 1.0, timer.getElapsedTime(),
834 std::vector<polarity> &isNew,
835 std::vector<std::vector<std::pair<polarity, polarity>>> &vertexLinkPolarity,
836 std::vector<polarity> &toPropagateMin,
837 std::vector<polarity> &toPropagateMax,
838 std::vector<polarity> &toProcess,
839 std::vector<DynamicTree> &link,
840 std::vector<uint8_t> &vertexLink,
842 std::vector<std::vector<SimplexId>> &saddleCCMin,
843 std::vector<std::vector<SimplexId>> &saddleCCMax,
847 const size_t nDecVerts = multiresTriangulation_.getDecimatedVertexNumber();
850#ifdef TTK_ENABLE_OPENMP
851#pragma omp parallel for num_threads(threadNumber_)
853 for(
size_t i = 0; i < nDecVerts; i++) {
854 SimplexId const globalId = multiresTriangulation_.localToGlobalVertexId(i);
855 buildVertexLinkPolarity(globalId, vertexLinkPolarity[globalId], offsets);
856 initDynamicLink(globalId, vertexLinkPolarity[globalId],
857 vertexLink[globalId], link[globalId],
858 vertexLinkByBoundaryType, offsets);
859 getValencesFromLink(globalId, vertexLinkPolarity[globalId], link[globalId],
860 toPropagateMin, toPropagateMax, saddleCCMin,
862 toProcess[globalId] = 255;
866 this->
printMsg(
"initial critical types", 1.0, timer.getElapsedTime(),
872 std::vector<polarity> &toPropagateMin,
873 std::vector<polarity> &toPropagateMax,
874 std::vector<std::vector<SimplexId>> &vertexRepresentativesMin,
875 std::vector<std::vector<SimplexId>> &vertexRepresentativesMax,
876 std::vector<std::vector<SimplexId>> &saddleCCMin,
877 std::vector<std::vector<SimplexId>> &saddleCCMax,
878 std::vector<Lock> &vertLockMin,
879 std::vector<Lock> &vertLockMax,
880 std::vector<polarity> &isUpdatedMin,
881 std::vector<polarity> &isUpdatedMax,
885 const size_t nDecVerts = multiresTriangulation_.getDecimatedVertexNumber();
887 std::vector<SimplexId> globalMaxThr(threadNumber_, 0);
888 std::vector<SimplexId> globalMinThr(threadNumber_, 0);
890#ifdef TTK_ENABLE_OPENMP
891#pragma omp parallel for num_threads(threadNumber_)
893 for(
size_t i = 0; i < nDecVerts; i++) {
894 SimplexId const v = multiresTriangulation_.localToGlobalVertexId(i);
895 if(toPropagateMin[v]) {
896 propagateFromSaddles(v, vertLockMin, toPropagateMin,
897 vertexRepresentativesMin, saddleCCMin, isUpdatedMin,
898 globalMinThr, offsets,
false);
900 if(toPropagateMax[v]) {
901 propagateFromSaddles(v, vertLockMax, toPropagateMax,
902 vertexRepresentativesMax, saddleCCMax, isUpdatedMax,
903 globalMaxThr, offsets,
true);
908 return offsets[a] < offsets[b];
911 globalMin_ = *std::min_element(globalMinThr.begin(), globalMinThr.end(), lt);
912 globalMax_ = *std::max_element(globalMaxThr.begin(), globalMaxThr.end(), lt);
914 this->
printMsg(
"FIRSTPROPAGATION", 1.0, timer.getElapsedTime(),
920 std::vector<polarity> &toPropagateMin,
921 std::vector<polarity> &toPropagateMax,
922 std::vector<std::vector<SimplexId>> &vertexRepresentativesMin,
923 std::vector<std::vector<SimplexId>> &vertexRepresentativesMax,
924 std::vector<std::vector<SimplexId>> &saddleCCMin,
925 std::vector<std::vector<SimplexId>> &saddleCCMax,
926 std::vector<Lock> &vertLockMin,
927 std::vector<Lock> &vertLockMax,
928 std::vector<polarity> &isUpdatedMin,
929 std::vector<polarity> &isUpdatedMax,
933 const size_t nDecVerts = multiresTriangulation_.getDecimatedVertexNumber();
935 std::vector<SimplexId> globalMaxThr(threadNumber_, 0);
936 std::vector<SimplexId> globalMinThr(threadNumber_, 0);
939#ifdef TTK_ENABLE_OPENMP
940#pragma omp parallel for num_threads(threadNumber_)
942 for(
size_t i = 0; i < nDecVerts; i++) {
943 SimplexId const v = multiresTriangulation_.localToGlobalVertexId(i);
944 if(toPropagateMin[v]) {
945 propagateFromSaddles(v, vertLockMin, toPropagateMin,
946 vertexRepresentativesMin, saddleCCMin, isUpdatedMin,
947 globalMinThr, offsets,
false);
949 if(toPropagateMax[v]) {
950 propagateFromSaddles(v, vertLockMax, toPropagateMax,
951 vertexRepresentativesMax, saddleCCMax, isUpdatedMax,
952 globalMaxThr, offsets,
true);
957 return offsets[a] < offsets[b];
960 globalMin_ = *std::min_element(globalMinThr.begin(), globalMinThr.end(), lt);
961 globalMax_ = *std::max_element(globalMaxThr.begin(), globalMaxThr.end(), lt);
963 this->
printMsg(
"PROPAGATION UPDATE", 1.0, tm.getElapsedTime(),
984 std::vector<std::pair<polarity, polarity>> &vlp,
985 std::vector<std::pair<SimplexId, SimplexId>> &vl)
const {
987 std::vector<SimplexId> monotony_changes_list{};
989 for(
size_t neighborId = 0; neighborId < vlp.size(); neighborId++) {
990 const polarity isBroken = vlp[neighborId].second;
992 monotony_changes_list.emplace_back(neighborId);
1001 std::vector<std::vector<std::pair<SimplexId, SimplexId>>> edgesToInsertLater(
1003 std::vector<std::vector<std::pair<SimplexId, SimplexId>>> edgesToRemoveLater(
1006 for(
size_t e = 0; e < vl.size(); e++) {
1009 const polarity isBroken0 = vlp[n0].second;
1010 const polarity isBroken1 = vlp[n1].second;
1012 if(isBroken0 != 0 and isBroken1 == 0) {
1013 if(vlp[n0].first != vlp[n1].first) {
1014 edgesToInsertLater[n0].emplace_back(n0, n1);
1016 edgesToRemoveLater[n0].emplace_back(n0, n1);
1018 }
else if(isBroken0 == 0 and isBroken1 != 0) {
1019 if(vlp[n0].first != vlp[n1].first) {
1020 edgesToInsertLater[n1].emplace_back(n1, n0);
1022 edgesToRemoveLater[n1].emplace_back(n1, n0);
1028 for(
const auto brokenNode : monotony_changes_list) {
1029 vlp[brokenNode].first = ~vlp[brokenNode].first;
1030 vlp[brokenNode].second = 0;
1033 for(
const auto &edge : edgesToRemoveLater[brokenNode]) {
1037 if(!edgesToRemoveLater.empty()) {
1039 for(
const auto &edge : vl) {
1040 if(vlp[edge.first].first == vlp[edge.second].first) {
1047 for(
const auto brokenNode : monotony_changes_list) {
1048 for(
const auto &edge : edgesToInsertLater[brokenNode]) {