34#include <unordered_set>
36#define INTEGRAL_LINE_TABULAR_SIZE 50
38#define INTEGRAL_LINE_IS_ELEMENT_TO_PROCESS 0
39#define INTEGRAL_LINE_IS_MESSAGE_SIZE 1
70 struct GhostElementsToSort {
80 inline bool operator<(
const GhostElementsToSort &left,
81 const GhostElementsToSort &right) {
82 if(left.seedIdentifier != right.seedIdentifier) {
83 return left.seedIdentifier < right.seedIdentifier;
85 if(left.forkIdentifier != right.forkIdentifier) {
86 return left.forkIdentifier < right.forkIdentifier;
88 return left.minLocalVertexId < right.minLocalVertexId;
95 static int finishedElement_ __attribute__((aligned(64)));
96 static int addedElement_ __attribute__((aligned(64)));
104 struct ElementToBeSent {
107 double DistanceFromSeed1;
108 double DistanceFromSeed2;
125 template <
class triangulationType = ttk::AbstractTriangulation>
126 int execute(triangulationType *triangulation);
137 template <
class triangulationType = ttk::AbstractTriangulation>
152 template <
class triangulationType>
153 void createTask(
const triangulationType *triangulation,
154 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
156 int nbElement)
const;
171 template <
class triangulationType>
174 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
177 std::vector<SimplexId> *seeds)
const;
202 std::vector<ttk::SimplexId> &component,
217 template <
typename triangulationType>
218 int getGlobalIdentifiers(
219 std::vector<ttk::SimplexId> &globalVertexId,
220 std::vector<ttk::SimplexId> &globalCellId,
224 const triangulationType *triangulation);
237 const std::vector<std::vector<ttk::intgl::GhostElementsToSort>>
239 std::vector<ttk::SimplexId> &globalVertexId,
240 std::vector<ttk::SimplexId> &globalCellId);
253 template <
class triangulationType>
254 void storeToSendIfNecessary(
const triangulationType *triangulation,
273 template <
class triangulationType>
275 receiveElement(
const triangulationType *triangulation,
276 intgl::ElementToBeSent &element,
277 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
282 inline void setToSend(
283 std::vector<std::vector<std::vector<intgl::ElementToBeSent>>> *send) {
287 inline void setGlobalElementCounter(
int counter) {
288 globalElementCounter_ = counter;
291 inline void setNeighbors(
const std::vector<int> &neighbors) {
292 neighbors_ = neighbors;
293 neighborNumber_ = neighbors_.size();
295 for(
int neighbor : neighbors) {
296 neighborsToId_[neighbor] = idx;
305 void createMessageType() {
308 = {getMPIType(
id), getMPIType(
id), MPI_DOUBLE, MPI_DOUBLE,
309 getMPIType(
id), getMPIType(
id), getMPIType(
id), getMPIType(
id)};
310 int lengths[] = {1, 1, 1, 1, 1, 1, 1, 1};
311 const long int mpi_offsets[]
312 = {offsetof(intgl::ElementToBeSent, Id1),
313 offsetof(intgl::ElementToBeSent, Id2),
314 offsetof(intgl::ElementToBeSent, DistanceFromSeed1),
315 offsetof(intgl::ElementToBeSent, DistanceFromSeed2),
316 offsetof(intgl::ElementToBeSent, LocalVertexIdentifier1),
317 offsetof(intgl::ElementToBeSent, LocalVertexIdentifier2),
318 offsetof(intgl::ElementToBeSent, SeedIdentifier),
319 offsetof(intgl::ElementToBeSent, ForkIdentifier)};
320 MPI_Type_create_struct(
321 8, lengths, mpi_offsets, types, &(this->MessageType));
322 MPI_Type_commit(&(this->MessageType));
386 std::vector<std::vector<std::vector<intgl::ElementToBeSent>>> *toSend_{
389 std::unordered_map<int, int> neighborsToId_;
390 std::vector<int> neighbors_;
393 MPI_Datatype MessageType;
400template <
class triangulationType>
401void ttk::IntegralLines::receiveElement(
402 const triangulationType *triangulation,
403 intgl::ElementToBeSent &element,
404 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
411#ifdef TTK_ENABLE_OPENMP4
412 threadNum = omp_get_thread_num();
418 std::vector<ttk::SimplexId>(
419 {triangulation->getVertexLocalId(element.Id1),
420 triangulation->getVertexLocalId(element.Id2)}),
422 {element.DistanceFromSeed1, element.DistanceFromSeed2}),
423 std::vector<ttk::SimplexId>(
424 {element.LocalVertexIdentifier1, element.LocalVertexIdentifier2}),
425 element.SeedIdentifier, element.ForkIdentifier});
428 chunkIntegralLine[index] = integralLine;
431 if(index == taskSize - 1) {
432 this->createTask<triangulationType>(
433 triangulation, chunkIntegralLine, offsets, taskSize);
440template <
class triangulationType>
441void ttk::IntegralLines::storeToSendIfNecessary(
442 const triangulationType *triangulation,
446 if(ttk::isRunningWithMPI()) {
450 = triangulation->getVertexRank(integralLine->
trajectory.back());
452 intgl::ElementToBeSent element
453 = intgl::ElementToBeSent{-1,
462 = triangulation->getVertexGlobalId(integralLine->
trajectory.back());
463 element.Id1 = triangulation->getVertexGlobalId(
467 element.LocalVertexIdentifier2
469 element.LocalVertexIdentifier1
471#ifdef TTK_ENABLE_OPENMP4
473 ->at(neighborsToId_.find(rankArray)->second)[omp_get_thread_num()]
476 toSend_->at(neighborsToId_.find(rankArray)->second)[0].push_back(
490 std::vector<ttk::SimplexId> &component,
495 if(fnext < offsets[component[k]]) {
496 vnext = component[k];
497 fnext = offsets[component[k]];
500 if(fnext > offsets[component[k]]) {
501 vnext = component[k];
502 fnext = offsets[component[k]];
508template <
class triangulationType>
510 const triangulationType *triangulation,
517 triangulation->getVertexPoint(v, p0[0], p0[1], p0[2]);
519 std::vector<std::vector<ttk::SimplexId>> *components;
521 std::vector<std::vector<ttk::SimplexId>> upperComponents;
522 std::vector<std::vector<ttk::SimplexId>> lowerComponents;
524 char const criticalType
525 = this->scalarFieldCriticalPoints_.getCriticalType<triangulationType>(
526 v, offsets, triangulation, &upperComponents, &lowerComponents);
534 if(ttk::isRunningWithMPI()
536#ifdef TTK_ENABLE_OPENMP4
537#pragma omp atomic update seq_cst
539 ttk::intgl::finishedElement_++;
541 this->storeToSendIfNecessary<triangulationType>(
542 triangulation, integralLine, isMax);
548 components = &(lowerComponents);
550 components = &(upperComponents);
560#ifdef TTK_ENABLE_OPENMP4
561#pragma omp atomic update seq_cst
563 ttk::intgl::finishedElement_++;
564#ifdef TTK_ENABLE_OPENMP4
565#pragma omp atomic update seq_cst
567 ttk::intgl::addedElement_ += numberOfComponents;
570 for(
int i = 0; i < numberOfComponents; i++) {
573 this->findNextVertex(vnext, fnext, components->at(i), offsets);
577 = triangulation->getVertexGlobalId(vnext);
581 triangulation->getVertexPoint(vnext, p1[0], p1[1], p1[2]);
584#ifdef TTK_ENABLE_OPENMP4
585 threadNum = omp_get_thread_num();
588 = outputIntegralLines_->at(threadNum).addArrayElement(
590 std::vector<ttk::SimplexId>({v, vnext}),
591 std::vector<double>({distance, distance + distanceFork}),
592 std::vector<ttk::SimplexId>(
597#ifdef TTK_ENABLE_OPENMP4
598#pragma omp task firstprivate(integralLineFork)
602 bool hasBeenSent =
false;
603 this->storeToSendIfNecessary<triangulationType>(
604 triangulation, integralLineFork, hasBeenSent);
607 this->computeIntegralLine<triangulationType>(
608 triangulation, integralLineFork, offsets);
612#ifdef TTK_ENABLE_OPENMP4
621 = triangulation->getVertexNeighborNumber(v);
622 components->push_back(std::vector<ttk::SimplexId>());
625 triangulation->getVertexNeighbor(v, i,
id);
626 components->at(0).push_back(
id);
630 this->findNextVertex(vnext, fnext, components->at(0), offsets);
631 triangulation->getVertexPoint(vnext, p1[0], p1[1], p1[2]);
642 this->storeToSendIfNecessary<triangulationType>(
643 triangulation, integralLine, isMax);
650template <
class triangulationType>
653 const triangulationType *triangulation,
655 const triangulationType *
ttkNotUsed(triangulation),
657 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
660 std::vector<SimplexId> *seeds)
const {
662 for(
SimplexId j = 0; j < nbElement; j++) {
663 SimplexId const v{seeds->at(j + startingIndex)};
666 seedIdentifier = triangulation->getVertexGlobalId(v);
671#ifdef TTK_ENABLE_OPENMP4
672 threadNum = omp_get_thread_num();
674 chunkIntegralLine[j] = outputIntegralLines_->at(threadNum).addArrayElement(
676 std::vector<ttk::SimplexId>(1, v), std::vector<double>(1, 0),
677 std::vector<ttk::SimplexId>(1, 0), seedIdentifier, -1});
681template <
class triangulationType>
683 const triangulationType *triangulation,
684 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
686 int nbElement)
const {
687#ifdef TTK_ENABLE_OPENMP4
688#pragma omp task firstprivate(chunkIntegralLine)
691 for(
int j = 0; j < nbElement; j++) {
692 this->computeIntegralLine<triangulationType>(
693 triangulation, chunkIntegralLine[j], offsets);
695#ifdef TTK_ENABLE_OPENMP4
700template <
class triangulationType>
705 ttk::intgl::finishedElement_ = 0;
706 ttk::intgl::addedElement_ = 0;
708 const SimplexId *offsets = inputOffsets_;
709 std::vector<SimplexId> *seeds = vertexIdentifierScalarField_;
712 std::vector<ttk::intgl::IntegralLine *> chunkIntegralLine(chunkSize_);
713 int const taskNumber = (int)seedNumber_ / chunkSize_;
714#ifdef TTK_ENABLE_OPENMP4
716#pragma omp parallel shared( \
717 ttk::intgl::finishedElement_, toSend_, ttk::intgl::addedElement_) \
718 num_threads(threadNumber_)
721#pragma omp parallel num_threads(threadNumber_)
727 for(
SimplexId i = 0; i < taskNumber; ++i) {
728 this->prepareForTask<triangulationType>(
729 triangulation, chunkIntegralLine, i * chunkSize_, chunkSize_, seeds);
730 this->createTask<triangulationType>(
731 triangulation, chunkIntegralLine, offsets, chunkSize_);
733 int const rest = seedNumber_ % chunkSize_;
735 this->prepareForTask<triangulationType>(
736 triangulation, chunkIntegralLine, taskNumber * chunkSize_, rest,
738 this->createTask<triangulationType>(
739 triangulation, chunkIntegralLine, offsets, rest);
741#ifdef TTK_ENABLE_OPENMP4
746 if(ttk::isRunningWithMPI()) {
748 int finishedElementReceived = 0;
749 std::vector<int> sendMessageSize(neighborNumber_);
750 std::vector<int> recvMessageSize(neighborNumber_);
751 std::vector<std::vector<intgl::ElementToBeSent>> send_buf(neighborNumber_);
752 std::vector<std::vector<intgl::ElementToBeSent>> recv_buf(neighborNumber_);
753 for(i = 0; i < neighborNumber_; i++) {
754 send_buf.reserve((
int)seedNumber_ * 0.005);
755 recv_buf.reserve((
int)seedNumber_ * 0.005);
757 std::vector<MPI_Request> requests(2 * neighborNumber_, MPI_REQUEST_NULL);
758 std::vector<MPI_Status> statuses(4 * neighborNumber_);
761 int totalMessageSize;
762 while(keepWorking_) {
763 ttk::intgl::finishedElement_ -= ttk::intgl::addedElement_;
764 ttk::intgl::addedElement_ = 0;
766 MPI_Allreduce(&ttk::intgl::finishedElement_, &finishedElementReceived, 1,
767 MPI_INTEGER, MPI_SUM, ttk::MPIcomm_);
768 ttk::intgl::finishedElement_ = 0;
770 globalElementCounter_ -= finishedElementReceived;
772 if(globalElementCounter_ == 0) {
776 totalMessageSize = 0;
779 for(i = 0; i < neighborNumber_; i++) {
780 for(
int j = 0; j < threadNumber_; j++) {
781 send_buf[i].insert(send_buf[i].
end(), toSend_->at(i)[j].begin(),
782 toSend_->at(i)[j].end());
783 toSend_->at(i)[j].clear();
785 sendMessageSize[i] = (int)send_buf[i].size();
786 MPI_Isend(&sendMessageSize[i], 1, MPI_INTEGER, neighbors_.at(i),
787 INTEGRAL_LINE_IS_MESSAGE_SIZE, ttk::MPIcomm_,
789 MPI_Irecv(&recvMessageSize[i], 1, MPI_INTEGER, neighbors_.at(i),
790 INTEGRAL_LINE_IS_MESSAGE_SIZE, ttk::MPIcomm_,
791 &requests[2 * i + 1]);
793 MPI_Waitall(2 * neighborNumber_, requests.data(), MPI_STATUSES_IGNORE);
795 for(i = 0; i < neighborNumber_; i++) {
796 if(recv_buf[i].size() < (
size_t)recvMessageSize[i]) {
797 recv_buf[i].resize(recvMessageSize[i]);
799 if(recvMessageSize[i] > 0) {
800 MPI_Irecv(recv_buf[i].data(), recvMessageSize[i], this->MessageType,
801 neighbors_.at(i), INTEGRAL_LINE_IS_ELEMENT_TO_PROCESS,
802 ttk::MPIcomm_, &requests[2 * i]);
803 totalMessageSize += recvMessageSize[i];
806 if(sendMessageSize[i] > 0) {
807 MPI_Isend(send_buf[i].data(), sendMessageSize[i], this->MessageType,
808 neighbors_.at(i), INTEGRAL_LINE_IS_ELEMENT_TO_PROCESS,
809 ttk::MPIcomm_, &requests[2 * i + 1]);
812 MPI_Waitall(2 * neighborNumber_, requests.data(), MPI_STATUSES_IGNORE);
813 for(i = 0; i < neighborNumber_; i++) {
817#ifdef TTK_ENABLE_OPENMP4
818#pragma omp parallel shared(ttk::intgl::finishedElement_, toSend_) \
819 num_threads(threadNumber_)
826 (
ttk::SimplexId)std::max(totalMessageSize / (threadNumber_ * 100),
827 std::min(totalMessageSize, 50)),
829 chunkIntegralLine.resize(taskSize);
830 for(i = 0; i < neighborNumber_; i++) {
831 for(
int j = 0; j < recvMessageSize[i]; j++) {
832 this->receiveElement<triangulationType>(
833 triangulation, recv_buf[i][j], chunkIntegralLine, index,
838 this->createTask<triangulationType>(
839 triangulation, chunkIntegralLine, offsets, index);
841#ifdef TTK_ENABLE_OPENMP4
850 std::stringstream msg;
851 msg <<
"Processed " << vertexNumber_ <<
" points";
858template <
typename triangulationType>
859int ttk::IntegralLines::getGlobalIdentifiers(
860 std::vector<ttk::SimplexId> &globalVertexId,
861 std::vector<ttk::SimplexId> &globalCellId,
865 const triangulationType *triangulation) {
872#ifdef TTK_ENABLE_OPENMP4
873#pragma omp parallel for reduction(+:outputVertexNumber,outputCellNumber,realCellNumber,realVertexNumber) schedule(static,1) private(intervalSize)
875 for(
int thread = 0; thread < threadNumber_; thread++) {
879 = integralLines[thread].list_.begin();
880 while(integralLine != integralLines[thread].list_.end()) {
882 if(integralLine->at(i).trajectory.size() > 0) {
884 integralLine->at(i).trajectory.size());
885 outputVertexNumber += intervalSize;
886 outputCellNumber += intervalSize - 1;
887 if(triangulation->getVertexRank(integralLine->at(i).trajectory.at(0))
891 if(integralLine->at(i).trajectory.size() > 1) {
892 realCellNumber += intervalSize - 1;
893 if(triangulation->getVertexRank(
894 integralLine->at(i).trajectory.back())
899 realVertexNumber += intervalSize;
913 MPI_Exscan(&realVertexNumber, &vertIndex, 1, ttk::getMPIType(vertIndex),
914 MPI_SUM, ttk::MPIcomm_);
915 MPI_Exscan(&realCellNumber, &cellIndex, 1, ttk::getMPIType(cellIndex),
916 MPI_SUM, ttk::MPIcomm_);
929 globalVertexId.resize(outputVertexNumber);
930 globalCellId.resize(outputCellNumber);
931 std::vector<std::vector<ttk::intgl::GhostElementsToSort>> unmatchedGhosts(
933 std::vector<std::vector<ttk::SimplexId>> unmatchedGhostsVertexLocalId(
935 std::vector<std::vector<ttk::SimplexId>> unmatchedGhostsEdgeLocalId(
937 for(
int thread = 0; thread < threadNumber_; thread++) {
941 = integralLines[thread].list_.begin();
942 while(integralLine != integralLines[thread].list_.end()) {
944 if(integralLine->at(i).trajectory.size() > 0) {
945 if(triangulation->getVertexRank(integralLine->at(i).trajectory.at(0))
947 globalVertexId.at(startVertexId) = -1;
949 globalVertexId.at(startVertexId) = vertIndex;
953 if(integralLine->at(i).trajectory.size() > 1) {
954 if(triangulation->getVertexRank(
955 integralLine->at(i).trajectory.at(0))
957 globalCellId.at(startCellId) = -1;
959 .at(neighborsToId_[triangulation->getVertexRank(
960 integralLine->at(i).trajectory.at(0))])
961 .push_back(ttk::intgl::GhostElementsToSort{
962 vertIndex, integralLine->at(i).localVertexIdentifier.at(0),
963 integralLine->at(i).seedIdentifier,
964 integralLine->at(i).forkIdentifier, -1, startVertexId - 1,
967 globalCellId.at(startCellId) = cellIndex;
971 if(integralLine->at(i).trajectory.size() > 2) {
972 std::iota(globalCellId.begin() + startCellId,
973 globalCellId.begin() + startCellId
974 + integralLine->at(i).trajectory.size() - 2,
976 std::iota(globalVertexId.begin() + startVertexId,
977 globalVertexId.begin() + startVertexId
978 + integralLine->at(i).trajectory.size() - 2,
980 startCellId += integralLine->at(i).trajectory.size() - 2;
981 startVertexId += integralLine->at(i).trajectory.size() - 2;
982 vertIndex += integralLine->at(i).trajectory.size() - 2;
983 cellIndex += integralLine->at(i).trajectory.size() - 2;
985 if(triangulation->getVertexRank(
986 integralLine->at(i).trajectory.back())
988 globalVertexId.at(startVertexId) = -1;
990 .at(neighborsToId_[triangulation->getVertexRank(
991 integralLine->at(i).trajectory.back())])
992 .push_back(ttk::intgl::GhostElementsToSort{
993 globalVertexId.at(startVertexId - 1),
994 integralLine->at(i).localVertexIdentifier.at(
995 integralLine->at(i).localVertexIdentifier.size() - 2),
996 integralLine->at(i).seedIdentifier,
997 integralLine->at(i).forkIdentifier,
998 globalCellId.at(startCellId - 1), startVertexId,
1001 globalVertexId.at(startVertexId) = vertIndex;
1026 for(
int i = 0; i < neighborNumber_; i++) {
1027 TTK_PSORT(threadNumber_, unmatchedGhosts.at(i).begin(),
1028 unmatchedGhosts.at(i).end());
1030 this->exchangeGhosts(unmatchedGhosts, globalVertexId, globalCellId);
1036inline int ttk::IntegralLines::exchangeGhosts(
1037 const std::vector<std::vector<ttk::intgl::GhostElementsToSort>>
1039 std::vector<ttk::SimplexId> &globalVertexId,
1040 std::vector<ttk::SimplexId> &globalCellId) {
1042 std::vector<std::vector<ttk::SimplexId>> globalIdsToSend(neighborNumber_);
1043 std::vector<std::vector<ttk::SimplexId>> globalIdsToReceive(neighborNumber_);
1044 for(
int i = 0; i < neighborNumber_; i++) {
1045 globalIdsToSend[i].resize(2 * unmatchedGhosts[i].size());
1046 globalIdsToReceive[i].resize(2 * unmatchedGhosts[i].size());
1049#ifdef TTK_ENABLE_OPENMP4
1050#pragma omp parallel for
1052 for(
int i = 0; i < neighborNumber_; i++) {
1053 for(
size_t j = 0; j < unmatchedGhosts[i].size(); j++) {
1054 globalIdsToSend[i][2 * j] = unmatchedGhosts[i][j].ownedGlobalId;
1055 globalIdsToSend[i][2 * j + 1] = unmatchedGhosts[i][j].globalEdgeId;
1060 for(
int neighbor : neighbors_) {
1061 MPI_Sendrecv(globalIdsToSend[neighborsToId_[neighbor]].data(),
1062 globalIdsToSend[neighborsToId_[neighbor]].size(),
1064 globalIdsToReceive[neighborsToId_[neighbor]].data(),
1065 globalIdsToSend[neighborsToId_[neighbor]].size(),
1066 ttk::getMPIType(
id), neighbor, neighbor, ttk::MPIcomm_,
1071#ifdef TTK_ENABLE_OPENMP4
1072#pragma omp parallel for
1074 for(
int i = 0; i < neighborNumber_; i++) {
1075 for(
size_t j = 0; j < unmatchedGhosts[i].size(); j++) {
1076 globalVertexId.at(unmatchedGhosts[i][j].ghostVertexLocalId)
1077 = globalIdsToReceive[i][2 * j];
1078 if(globalCellId.at(unmatchedGhosts[i][j].ghostEdgeLocalId) == -1) {
1079 globalCellId.at(unmatchedGhosts[i][j].ghostEdgeLocalId)
1080 = globalIdsToReceive[i][j * 2 + 1];
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
#define INTEGRAL_LINE_TABULAR_SIZE
#define TTK_PSORT(NTHREADS,...)
Parallel sort macro.
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
virtual int preconditionVertexStars()
virtual int preconditionBoundaryVertices()
virtual int preconditionVertexNeighbors()
This class describes a dynamic size data structure for thread safe computation. It is a linked list o...
Minimalist debugging class.
TTK processing package for the computation of edge-based integral lines of the gradient of an input s...
std::vector< ttk::SimplexId > * vertexIdentifierScalarField_
ttk::ScalarFieldCriticalPoints scalarFieldCriticalPoints_
void buildScalarFieldCriticalPoints()
void setInputOffsets(const SimplexId *const data)
ttk::SimplexId chunkSize_
const ttk::SimplexId * inputOffsets_
void createTask(const triangulationType *triangulation, std::vector< ttk::intgl::IntegralLine * > &chunkIntegralLine, const ttk::SimplexId *offsets, int nbElement) const
Create an OpenMP task that contains the computation of nbElement integral lines.
void setDirection(int direction)
ttk::SimplexId direction_
void setInputScalarField(void *data)
void setChunkSize(int size)
void computeIntegralLine(const triangulationType *triangulation, ttk::intgl::IntegralLine *integralLine, const ttk::SimplexId *offsets) const
Computes the integral line starting at the vertex of global id seedIdentifier.
void findNextVertex(ttk::SimplexId &vnext, ttk::SimplexId &fnext, std::vector< ttk::SimplexId > &component, const SimplexId *offsets) const
Finds the vertex of highest or lowest offsets (depending on the direction of the integral line) in th...
int preconditionTriangulation(ttk::AbstractTriangulation *triangulation)
void setVertexNumber(const SimplexId &vertexNumber)
ttk::SimplexId seedNumber_
int execute(triangulationType *triangulation)
void setOutputIntegralLines(std::vector< ttk::ArrayLinkedList< ttk::intgl::IntegralLine, INTEGRAL_LINE_TABULAR_SIZE > > *integralLines)
void setVertexIdentifierScalarField(std::vector< SimplexId > *const data)
std::vector< ttk::ArrayLinkedList< ttk::intgl::IntegralLine, INTEGRAL_LINE_TABULAR_SIZE > > * outputIntegralLines_
~IntegralLines() override
ttk::SimplexId vertexNumber_
void prepareForTask(const triangulationType *triangulation, std::vector< ttk::intgl::IntegralLine * > &chunkIntegralLine, int startingIndex, int nbElement, std::vector< SimplexId > *seeds) const
Initializes the three attributes of an integral line: the global id of its seed, its trajectory,...
void setSeedNumber(const SimplexId &seedNumber)
TTK processing package for the computation of critical points in PL scalar fields defined on PL manif...
void preconditionTriangulation(AbstractTriangulation *triangulation)
T distance(const T *p0, const T *p1, const int &dimension=3)
COMMON_EXPORTS int MPIsize_
COMMON_EXPORTS int MPIrank_
int SimplexId
Identifier type for simplices of any dimension.
T end(std::pair< T, T > &p)
Struct containing the data of an integral line. trajectories: vector of identifiers of each vertex th...
std::vector< ttk::SimplexId > localVertexIdentifier
ttk::SimplexId forkIdentifier
std::vector< double > distanceFromSeed
ttk::SimplexId seedIdentifier
std::vector< ttk::SimplexId > trajectory
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)