21#ifdef __INTEL_COMPILER
25#ifndef TTK_ENABLE_OPENMP
29#ifdef TTK_ENABLE_OMP_PRIORITY
30#define OPTIONAL_PRIORITY(value) priority(value)
32#define OPTIONAL_PRIORITY(value)
39FTMTree_MT::FTMTree_MT(
const std::shared_ptr<Params> ¶ms,
40 const std::shared_ptr<Scalars> &scalars,
42 : params_(params), scalars_(scalars) {
94#ifdef TTK_ENABLE_FTM_TREE_STATS_TIME
110 vector<SimplexId> sizes(nbArcs);
115 for(
idSuperArc arcChunkId = 0; arcChunkId < arcChunkNb; ++arcChunkId) {
117#ifdef TTK_ENABLE_OPENMP
118#pragma omp task firstprivate(arcChunkId) shared(sizes) \
119 OPTIONAL_PRIORITY(isPrior())
122 const idSuperArc lowerBound = arcChunkId * arcChunkSize;
124 = min(nbArcs, (arcChunkId + 1) * arcChunkSize);
125 for(
idSuperArc a = lowerBound; a < upperBound; ++a) {
131#ifdef TTK_ENABLE_OPENMP
143 vector<SimplexId> posSegm(nbArcs, 0);
150 for(
SimplexId chunkId = 0; chunkId < chunkNb; ++chunkId) {
151#ifdef TTK_ENABLE_OPENMP
152#pragma omp task firstprivate(chunkId) shared(posSegm) \
153 OPTIONAL_PRIORITY(isPrior())
156 const SimplexId lowerBound = chunkId * chunkSize;
157 const SimplexId upperBound = min(nbVert, (chunkId + 1) * chunkSize);
158 for(
SimplexId i = lowerBound; i < upperBound; ++i) {
159 const auto vert =
scalars_->sortedVertices[i];
171#ifdef TTK_ENABLE_OPENMP
172#pragma omp atomic capture
174 vertToAdd = posSegm[sa]++;
182#ifdef TTK_ENABLE_OPENMP
186 printTime(segmentsSet,
"segmentation set vertices", 4);
191 Timer segmentsSortTime;
194#ifdef TTK_ENABLE_OPENMP
195#pragma omp task firstprivate(a) OPTIONAL_PRIORITY(isPrior())
200#ifdef TTK_ENABLE_OPENMP
203 printTime(segmentsSortTime,
"segmentation sort vertices", 4);
206 Timer segmentsArcTime;
210#ifdef TTK_ENABLE_OPENMP
211#pragma omp task firstprivate(a) OPTIONAL_PRIORITY(isPrior())
218#ifdef TTK_ENABLE_OPENMP
222 printTime(segmentsArcTime,
"segmentation arcs lists", 4);
229 for(
idSuperArc arcChunkId = 0; arcChunkId < arcChunkNb; ++arcChunkId) {
230#ifdef TTK_ENABLE_OPENMP
231#pragma omp task firstprivate(arcChunkId) OPTIONAL_PRIORITY(isPrior())
234 const idSuperArc lowerBound = arcChunkId * arcChunkSize;
236 = min(nbArcs, (arcChunkId + 1) * arcChunkSize);
237 for(
idSuperArc a = lowerBound; a < upperBound; ++a) {
246#ifdef TTK_ENABLE_OPENMP
272#ifndef TTK_ENABLE_KAMIKAZE
275 cout <<
"[Merge Tree] closeSuperArc on a inexisting arc !" << endl;
280 cout <<
"[Merge Tree] closeOpenedArc on a inexisting node !" << endl;
295#ifndef TTK_ENABLE_KAMIKAZE
298 cout << endl <<
"[FTMTree_MT]:delNode won't delete ";
299 cout << mainNode->
getVertexId() <<
" (root) with ";
340#ifndef TTK_ENABLE_KAMIKAZE
342 cerr <<
"delete node with multiple childrens " << endl;
348 arc.createSegmentation(
scalars_.get());
352tuple<SimplexId, SimplexId>
358 stop =
scalars_->offsets[trunkVerts[0]];
364 return make_tuple(
begin, stop);
413 const idNode last)
const {
415 const idNode rangeSize = range.size();
416 while(idRes + 1 < rangeSize &&
comp_.
vertLower(range[idRes + 1], v)) {
437 idNode upNodeId, newNodeId;
474#ifndef TTK_ENABLE_KAMIKAZE
475 if(vertexId < 0 || vertexId >=
scalars_->size) {
476 this->
printMsg({{
"make node, wrong vertex :", std::to_string(vertexId)},
477 {
" on ", std::to_string(
scalars_->size)}},
506 (*
mt_data_.
nodes)[downNodeId].addUpSuperArcId(newSuperArcId);
507 (*
mt_data_.
nodes)[upNodeId].addDownSuperArcId(newSuperArcId);
509 return newSuperArcId;
532 auto getNodeParentArcNb
541 auto getNodeParentArc
550 auto getArcParentNode
559 std::queue<tuple<idNode, bool>> q;
560 std::stack<tuple<idNode, bool>> qr;
584 tie(curNodeId, goUp) = q.front();
593 const idSuperArc nbArcParent = getNodeParentArcNb(curNodeId, goUp);
594 for(
idSuperArc pid = 0; pid < nbArcParent; pid++) {
595 const idSuperArc currentArcId = getNodeParentArc(curNodeId, goUp, pid);
597 if(
getSuperArc(currentArcId)->getNormalizedId() == nullSuperArc) {
600 if(!seenUp[currentArcId]) {
601 q.emplace(getArcParentNode(currentArcId, goUp), goUp);
602 seenUp[currentArcId] =
true;
605 if(
getSuperArc(currentArcId)->getNormalizedId() == nullSuperArc) {
608 if(!seenDown[currentArcId]) {
609 q.emplace(getArcParentNode(currentArcId, goUp), goUp);
610 seenDown[currentArcId] =
true;
616#ifndef TTK_ENABLE_KAMIKAZE
617 if(std::abs((
long)nIdMax - (
long)nIdMin) > 1) {
618 this->
printMsg({
"error during normalize, tree compromised: ",
619 std::to_string(nIdMin),
" ", std::to_string(nIdMax)},
628#ifndef TTK_ENABLE_KAMIKAZE
630 this->
printErr(
"openSuperArc on a inexisting node !");
637 (*
mt_data_.
nodes)[downNodeId].addUpSuperArcId(newSuperArcId);
639 return newSuperArcId;
649 if(dv != nullVertex) {
654 if(uv != nullVertex) {
660 res.seekg(0, ios::end);
661 while(res.tellg() < 25) {
663 res.seekg(0, ios::end);
665 res.seekg(0, ios::beg);
669 res.seekg(0, ios::end);
671 while(res.tellg() < 45) {
673 res.seekg(0, ios::end);
675 res.seekg(0, ios::beg);
721 this->
printMsg(
"* tree type : " + tt);
729 const int debugLevel)
const {
734 for(
int i = 3; i < debugLevel; i++)
744#ifdef TTK_ENABLE_OPENMP
748 cout <<
"Nodes----------" << endl;
753 cout <<
"Arcs-----------" << endl;
758 cout <<
"Leaves" << endl;
763 cout <<
"Roots" << endl;
771 auto indirect_sort = [&](
const idNode a,
const idNode b) {
785 std::vector<idNode> sortedNodes(this->mt_data_.nodes->size());
786 std::iota(sortedNodes.begin(), sortedNodes.end(), 0);
788 const auto direct_sort = [&](
const Node &a,
const Node &b) {
790 return this->comp_.vertLower(a.
getVertexId(), b.getVertexId());
793 const auto indirect_sort = [&](
const idNode a,
const idNode b) {
794 return direct_sort(*this->getNode(a), *this->getNode(b));
798 this->threadNumber_, sortedNodes.begin(), sortedNodes.end(), indirect_sort);
800 TTK_PSORT(this->threadNumber_, this->mt_data_.nodes->begin(),
801 this->mt_data_.nodes->end(), direct_sort);
804 std::vector<idNode> revSortedNodes(sortedNodes.size());
805 for(
size_t i = 0; i < sortedNodes.size(); ++i) {
806 revSortedNodes[sortedNodes[i]] = i;
810 for(
auto &leaf : this->mt_data_.leaves) {
811 leaf = revSortedNodes[leaf];
815 for(
auto &root : (*this->mt_data_.roots)) {
816 root = revSortedNodes[root];
820 for(
auto &arc : (*this->mt_data_.superArcs)) {
821 arc.setDownNodeId(revSortedNodes[arc.getDownNodeId()]);
822 arc.setUpNodeId(revSortedNodes[arc.getUpNodeId()]);
826 for(
size_t i = 0; i < sortedNodes.size(); ++i) {
827 const auto &node{(*this->mt_data_.nodes)[i]};
828 if(this->isCorrespondingNode(node.getVertexId())) {
829 this->updateCorrespondingNode(node.getVertexId(), i);
835 std::vector<idNode> sortedArcs(this->mt_data_.superArcs->size());
836 std::iota(sortedArcs.begin(), sortedArcs.end(), 0);
842 const auto bdn{b.getDownNodeId()};
843 const auto bun{b.getUpNodeId()};
844 return std::tie(adn, aun) < std::tie(bdn, bun);
848 const auto aa{this->getSuperArc(a)};
849 const auto bb{this->getSuperArc(b)};
850 return direct_sort(*aa, *bb);
854 this->threadNumber_, sortedArcs.begin(), sortedArcs.end(), indirect_sort);
856 TTK_PSORT(this->threadNumber_, this->mt_data_.superArcs->begin(),
857 this->mt_data_.superArcs->end(), direct_sort);
860 std::vector<idSuperArc> revSortedArcs(sortedArcs.size());
861 for(
size_t i = 0; i < sortedArcs.size(); ++i) {
862 revSortedArcs[sortedArcs[i]] = i;
866 std::vector<idSuperArc> updatedArcs{};
867 for(
auto &node : (*this->mt_data_.nodes)) {
869 const auto da{node.getNumberOfDownSuperArcs()};
871 updatedArcs.resize(da);
873 updatedArcs[i] = revSortedArcs[node.getDownSuperArcId(i)];
875 node.clearDownSuperArcs();
876 for(
const auto &arc : updatedArcs) {
877 node.addDownSuperArcId(arc);
881 const auto ua{node.getNumberOfUpSuperArcs()};
883 updatedArcs.resize(ua);
885 updatedArcs[i] = revSortedArcs[node.getUpSuperArcId(i)];
887 node.clearUpSuperArcs();
888 for(
const auto &arc : updatedArcs) {
889 node.addUpSuperArcId(arc);
895 for(
size_t i = 0; i < this->mt_data_.vert2tree.size(); ++i) {
896 if(this->isCorrespondingArc(i)) {
897 this->updateCorrespondingArc(
898 i, revSortedArcs[this->getCorrespondingSuperArcId(i)]);
907 auto indirect_sort = [&](
const idNode a,
const idNode b) {
916#ifdef TTK_ENABLE_OPENMP
928 const int nbTasksThreads = 40;
929 const auto sizeBackBone = abs(stop -
begin);
930 const auto chunkSize =
getChunkSize(sizeBackBone, nbTasksThreads);
931 const auto chunkNb =
getChunkCount(sizeBackBone, nbTasksThreads);
933 idNode lastVertInRange = 0;
935 for(
SimplexId chunkId = 0; chunkId < chunkNb; ++chunkId) {
936#ifdef TTK_ENABLE_OPENMP
937#pragma omp task firstprivate(chunkId, lastVertInRange) shared(trunkVerts) \
938 OPTIONAL_PRIORITY(isPrior())
941 vector<SimplexId> regularList;
943 regularList.reserve(25);
947 = min(stop, (
begin + (chunkId + 1) * chunkSize));
948 if(lowerBound != upperBound) {
953 for(
SimplexId v = lowerBound; v < upperBound; ++v) {
955 =
isST() ?
scalars_->sortedVertices[lowerBound + upperBound - 1 - v]
958 const idNode oldVertInRange = lastVertInRange;
964 if(oldVertInRange == lastVertInRange) {
965 regularList.emplace_back(s);
970 if(regularList.size()) {
971#ifdef TTK_ENABLE_OPENMP
980 regularList.emplace_back(s);
989 if(regularList.size()) {
990#ifdef TTK_ENABLE_OPENMP
1000#ifdef TTK_ENABLE_OPENMP
1012 const int nbTasksThreads = 40;
1013 const auto sizeBackBone = abs(stop -
begin);
1014 const auto chunkSize =
getChunkSize(sizeBackBone, nbTasksThreads);
1015 const auto chunkNb =
getChunkCount(sizeBackBone, nbTasksThreads);
1017 for(
SimplexId chunkId = 0; chunkId < chunkNb; ++chunkId) {
1018#ifdef TTK_ENABLE_OPENMP
1019#pragma omp task firstprivate(chunkId) shared(trunkVerts) \
1020 OPTIONAL_PRIORITY(isPrior())
1023 idNode lastVertInRange = 0;
1028 = min(stop, (
begin + (chunkId + 1) * chunkSize));
1029 for(
SimplexId v = lowerBound; v < upperBound; ++v) {
1031 =
isST() ?
scalars_->sortedVertices[lowerBound + upperBound - 1 - v]
1034 const idNode oldVertInRange = lastVertInRange;
1035 lastVertInRange =
getVertInRange(trunkVerts, s, lastVertInRange);
1040 if(oldVertInRange == lastVertInRange) {
1059#ifdef TTK_ENABLE_OPENMP
#define TTK_PSORT(NTHREADS,...)
Parallel sort macro.
void setDebugMsgPrefix(const std::string &prefix)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
FTMAtomicVector< idSuperArc > & getOpenedArcs()
Node * getUpperNode(const SuperArc *a)
bool isCorrespondingNode(const SimplexId val) const
std::shared_ptr< Params > params_
std::string printNode(idNode n)
SuperArc * getSuperArc(idSuperArc i)
Node * getDownNode(const SuperArc *a)
idNode getNumberOfNodes() const
idNode getUpNodeId(const SuperArc *a)
SimplexId getChunkSize(const SimplexId nbVerts=-1, const SimplexId nbtasks=100) const
bool isCorrespondingNull(const SimplexId val) const
void delNode(idNode node)
std::string printArc(idSuperArc a)
Node * vertex2Node(const SimplexId vert)
void move(FTMTree_MT &mt)
idSuperArc upArcFromVert(const SimplexId v)
std::tuple< SimplexId, SimplexId > getBoundsFromVerts(const std::vector< SimplexId > &nodes) const
Node * getLowerNode(const SuperArc *a)
idNode getDownNodeId(const SuperArc *a)
idSuperArc insertNode(Node *node, const bool segm=true)
bool isCorrespondingArc(const SimplexId val) const
void closeArcsUF(idNode closeNode, UF uf)
idNode getLowerNodeId(const SuperArc *a)
void sortUpArcs(const idNode nid)
virtual SimplexId trunkSegmentation(const std::vector< SimplexId > &pendingNodesVerts, const SimplexId begin, const SimplexId stop)
void sortNodes()
Sort tree nodes according to vertex order.
idNode getCorrespondingNodeId(const SimplexId val) const
idSuperArc getNumberOfSuperArcs() const
idNode getUpperNodeId(const SuperArc *a)
void sortLeaves(const bool parallel=false)
void finalizeSegmentation()
idNode getVertInRange(const std::vector< SimplexId > &range, const SimplexId v, const idNode last=0) const
void sortDownArcs(const idNode nid)
int printTime(Timer &t, const std::string &s, const int debugLevel=2) const
SimplexId getChunkCount(const SimplexId nbVerts=-1, const SimplexId nbTasks=100) const
SimplexId trunkCTSegmentation(const std::vector< SimplexId > &pendingNodesVerts, const SimplexId begin, const SimplexId stop)
idSuperArc openSuperArc(idNode downNodeId)
std::shared_ptr< FTMTree_MT > clone() const
idNode makeNode(SimplexId vertexId, SimplexId linked=nullVertex)
void buildSegmentation()
use vert2tree to compute the segmentation of the fresh built merge tree.
idSuperArc getCorrespondingSuperArcId(const SimplexId val) const
idSuperArc makeSuperArc(idNode downNodeId, idNode upNodeId)
void updateCorrespondingNode(const SimplexId vert, const idNode node)
Node * getUpNode(const SuperArc *a)
Node * getNode(idNode nodeId)
void closeSuperArc(idSuperArc superArcId, idNode upNodeId)
std::shared_ptr< Scalars > scalars_
void sortArcs()
Sort tree arcs.
void updateCorrespondingArc(const SimplexId vert, const idSuperArc arc)
std::vector< idNode > sortedNodes(const bool parallel=false)
idSuperArc getUpSuperArcId(idSuperArc neighborId) const
idSuperArc clearUpSuperArcs()
void addDownSuperArcId(idSuperArc downSuperArcId)
idSuperArc getNumberOfDownSuperArcs() const
idSuperArc getDownSuperArcId(idSuperArc neighborId) const
void removeUpSuperArc(idSuperArc idSa)
idSuperArc clearDownSuperArcs()
void removeDownSuperArc(idSuperArc idSa)
SimplexId getVertexId() const
idSuperArc getNumberOfUpSuperArcs() const
void resize(const std::vector< SimplexId > &sizes)
void setNormalizeIds(const idSuperArc id)
void atomicIncVisited(const SimplexId nb=1)
idNode getUpNodeId() const
SimplexId getNbVertSeen() const
std::string printReg() const
size_t regionSize() const
idNode getDownNodeId() const
long unsigned int idSuperArc
SuperArc index in vect_superArcs_.
std::ostream & operator<<(std::ostream &o, Node const &n)
unsigned int idNode
Node index in vect_nodes_.
int SimplexId
Identifier type for simplices of any dimension.
T begin(std::pair< T, T > &p)
std::shared_ptr< FTMAtomicVector< SuperArc > > superArcs
std::shared_ptr< FTMAtomicVector< CurrentState > > states
std::vector< std::list< std::vector< SimplexId > > > trunkSegments
std::shared_ptr< FTMAtomicVector< Node > > nodes
std::vector< SimplexId > visitOrder
std::vector< UF > propagation
std::vector< idCorresp > vert2tree
std::shared_ptr< FTMAtomicVector< idNode > > roots
std::vector< valence > valences
std::vector< idNode > leaves
std::vector< char > openedNodes
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)