29#include <unordered_set>
31#define INTEGRAL_LINE_TABULAR_SIZE 50
33#define INTEGRAL_LINE_IS_ELEMENT_TO_PROCESS 0
34#define INTEGRAL_LINE_IS_MESSAGE_SIZE 1
65 struct GhostElementsToSort {
75 inline bool operator<(
const GhostElementsToSort &left,
76 const GhostElementsToSort &right) {
77 if(left.seedIdentifier != right.seedIdentifier) {
78 return left.seedIdentifier < right.seedIdentifier;
80 if(left.forkIdentifier != right.forkIdentifier) {
81 return left.forkIdentifier < right.forkIdentifier;
83 return left.minLocalVertexId < right.minLocalVertexId;
90 static int finishedElement_ __attribute__((aligned(64)));
91 static int addedElement_ __attribute__((aligned(64)));
99 struct ElementToBeSent {
102 double DistanceFromSeed1;
103 double DistanceFromSeed2;
120 template <
class triangulationType = ttk::AbstractTriangulation>
121 int execute(triangulationType *triangulation);
132 template <
class triangulationType = ttk::AbstractTriangulation>
147 template <
class triangulationType>
148 void createTask(
const triangulationType *triangulation,
149 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
151 int nbElement)
const;
166 template <
class triangulationType>
169 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
172 std::vector<SimplexId> *seeds)
const;
197 std::vector<ttk::SimplexId> &component,
212 template <
typename triangulationType>
213 int getGlobalIdentifiers(
214 std::vector<ttk::SimplexId> &globalVertexId,
215 std::vector<ttk::SimplexId> &globalCellId,
219 const triangulationType *triangulation);
232 const std::vector<std::vector<ttk::intgl::GhostElementsToSort>>
234 std::vector<ttk::SimplexId> &globalVertexId,
235 std::vector<ttk::SimplexId> &globalCellId);
248 template <
class triangulationType>
249 void storeToSendIfNecessary(
const triangulationType *triangulation,
268 template <
class triangulationType>
270 receiveElement(
const triangulationType *triangulation,
271 intgl::ElementToBeSent &element,
272 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
277 inline void setToSend(
278 std::vector<std::vector<std::vector<intgl::ElementToBeSent>>> *send) {
282 inline void setGlobalElementCounter(
int counter) {
283 globalElementCounter_ = counter;
286 inline void setNeighbors(
const std::vector<int> &neighbors) {
287 neighbors_ = neighbors;
288 neighborNumber_ = neighbors_.size();
290 for(
int neighbor : neighbors) {
291 neighborsToId_[neighbor] = idx;
300 void createMessageType() {
303 = {getMPIType(
id), getMPIType(
id), MPI_DOUBLE, MPI_DOUBLE,
304 getMPIType(
id), getMPIType(
id), getMPIType(
id), getMPIType(
id)};
305 int lengths[] = {1, 1, 1, 1, 1, 1, 1, 1};
306 const long int mpi_offsets[]
307 = {offsetof(intgl::ElementToBeSent, Id1),
308 offsetof(intgl::ElementToBeSent, Id2),
309 offsetof(intgl::ElementToBeSent, DistanceFromSeed1),
310 offsetof(intgl::ElementToBeSent, DistanceFromSeed2),
311 offsetof(intgl::ElementToBeSent, LocalVertexIdentifier1),
312 offsetof(intgl::ElementToBeSent, LocalVertexIdentifier2),
313 offsetof(intgl::ElementToBeSent, SeedIdentifier),
314 offsetof(intgl::ElementToBeSent, ForkIdentifier)};
315 MPI_Type_create_struct(
316 8, lengths, mpi_offsets, types, &(this->MessageType));
317 MPI_Type_commit(&(this->MessageType));
381 std::vector<std::vector<std::vector<intgl::ElementToBeSent>>> *toSend_{
384 std::unordered_map<int, int> neighborsToId_;
385 std::vector<int> neighbors_;
388 MPI_Datatype MessageType;
395template <
class triangulationType>
396void ttk::IntegralLines::receiveElement(
397 const triangulationType *triangulation,
398 intgl::ElementToBeSent &element,
399 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
406#ifdef TTK_ENABLE_OPENMP
407 threadNum = omp_get_thread_num();
413 std::vector<ttk::SimplexId>(
414 {triangulation->getVertexLocalId(element.Id1),
415 triangulation->getVertexLocalId(element.Id2)}),
417 {element.DistanceFromSeed1, element.DistanceFromSeed2}),
418 std::vector<ttk::SimplexId>(
419 {element.LocalVertexIdentifier1, element.LocalVertexIdentifier2}),
420 element.SeedIdentifier, element.ForkIdentifier});
423 chunkIntegralLine[index] = integralLine;
426 if(index == taskSize - 1) {
427 this->createTask<triangulationType>(
428 triangulation, chunkIntegralLine, offsets, taskSize);
435template <
class triangulationType>
436void ttk::IntegralLines::storeToSendIfNecessary(
437 const triangulationType *triangulation,
441 if(ttk::isRunningWithMPI()) {
445 = triangulation->getVertexRank(integralLine->
trajectory.back());
447 intgl::ElementToBeSent element
448 = intgl::ElementToBeSent{-1,
457 = triangulation->getVertexGlobalId(integralLine->
trajectory.back());
458 element.Id1 = triangulation->getVertexGlobalId(
462 element.LocalVertexIdentifier2
464 element.LocalVertexIdentifier1
466#ifdef TTK_ENABLE_OPENMP
468 ->at(neighborsToId_.find(rankArray)->second)[omp_get_thread_num()]
471 toSend_->at(neighborsToId_.find(rankArray)->second)[0].push_back(
485 std::vector<ttk::SimplexId> &component,
490 if(fnext < offsets[component[k]]) {
491 vnext = component[k];
492 fnext = offsets[component[k]];
495 if(fnext > offsets[component[k]]) {
496 vnext = component[k];
497 fnext = offsets[component[k]];
503template <
class triangulationType>
505 const triangulationType *triangulation,
512 triangulation->getVertexPoint(v, p0[0], p0[1], p0[2]);
514 std::vector<std::vector<ttk::SimplexId>> *components;
516 std::vector<std::vector<ttk::SimplexId>> upperComponents;
517 std::vector<std::vector<ttk::SimplexId>> lowerComponents;
520 = this->scalarFieldCriticalPoints_.getCriticalType<triangulationType>(
521 v, offsets, triangulation, &upperComponents, &lowerComponents);
529 if(ttk::isRunningWithMPI()
531#ifdef TTK_ENABLE_OPENMP
532#pragma omp atomic update seq_cst
534 ttk::intgl::finishedElement_++;
536 this->storeToSendIfNecessary<triangulationType>(
537 triangulation, integralLine, isMax);
543 components = &(lowerComponents);
545 components = &(upperComponents);
555#ifdef TTK_ENABLE_OPENMP
556#pragma omp atomic update seq_cst
558 ttk::intgl::finishedElement_++;
559#ifdef TTK_ENABLE_OPENMP
560#pragma omp atomic update seq_cst
562 ttk::intgl::addedElement_ += numberOfComponents;
565 for(
int i = 0; i < numberOfComponents; i++) {
568 this->findNextVertex(vnext, fnext, components->at(i), offsets);
572 = triangulation->getVertexGlobalId(vnext);
576 triangulation->getVertexPoint(vnext, p1[0], p1[1], p1[2]);
579#ifdef TTK_ENABLE_OPENMP
580 threadNum = omp_get_thread_num();
583 = outputIntegralLines_->at(threadNum).addArrayElement(
585 std::vector<ttk::SimplexId>({v, vnext}),
586 std::vector<double>({distance, distance + distanceFork}),
587 std::vector<ttk::SimplexId>(
592#ifdef TTK_ENABLE_OPENMP
593#pragma omp task firstprivate(integralLineFork)
597 bool hasBeenSent =
false;
598 this->storeToSendIfNecessary<triangulationType>(
599 triangulation, integralLineFork, hasBeenSent);
602 this->computeIntegralLine<triangulationType>(
603 triangulation, integralLineFork, offsets);
607#ifdef TTK_ENABLE_OPENMP
616 = triangulation->getVertexNeighborNumber(v);
617 components->push_back(std::vector<ttk::SimplexId>());
620 triangulation->getVertexNeighbor(v, i,
id);
621 components->at(0).push_back(
id);
625 this->findNextVertex(vnext, fnext, components->at(0), offsets);
626 triangulation->getVertexPoint(vnext, p1[0], p1[1], p1[2]);
637 this->storeToSendIfNecessary<triangulationType>(
638 triangulation, integralLine, isMax);
645template <
class triangulationType>
648 const triangulationType *triangulation,
650 const triangulationType *
ttkNotUsed(triangulation),
652 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
655 std::vector<SimplexId> *seeds)
const {
657 for(
SimplexId j = 0; j < nbElement; j++) {
658 SimplexId v{seeds->at(j + startingIndex)};
661 seedIdentifier = triangulation->getVertexGlobalId(v);
666#ifdef TTK_ENABLE_OPENMP
667 threadNum = omp_get_thread_num();
669 chunkIntegralLine[j] = outputIntegralLines_->at(threadNum).addArrayElement(
671 std::vector<ttk::SimplexId>(1, v), std::vector<double>(1, 0),
672 std::vector<ttk::SimplexId>(1, 0), seedIdentifier, -1});
676template <
class triangulationType>
678 const triangulationType *triangulation,
679 std::vector<ttk::intgl::IntegralLine *> &chunkIntegralLine,
681 int nbElement)
const {
682#ifdef TTK_ENABLE_OPENMP
683#pragma omp task firstprivate(chunkIntegralLine)
686 for(
int j = 0; j < nbElement; j++) {
687 this->computeIntegralLine<triangulationType>(
688 triangulation, chunkIntegralLine[j], offsets);
690#ifdef TTK_ENABLE_OPENMP
695template <
class triangulationType>
700 ttk::intgl::finishedElement_ = 0;
701 ttk::intgl::addedElement_ = 0;
703 const SimplexId *offsets = inputOffsets_;
704 std::vector<SimplexId> *seeds = vertexIdentifierScalarField_;
707 std::vector<ttk::intgl::IntegralLine *> chunkIntegralLine(chunkSize_);
708 int taskNumber = (int)seedNumber_ / chunkSize_;
709#ifdef TTK_ENABLE_OPENMP
711#pragma omp parallel shared( \
712 ttk::intgl::finishedElement_, toSend_, ttk::intgl::addedElement_) \
713 num_threads(threadNumber_)
716#pragma omp parallel num_threads(threadNumber_)
722 for(
SimplexId i = 0; i < taskNumber; ++i) {
723 this->prepareForTask<triangulationType>(
724 triangulation, chunkIntegralLine, i * chunkSize_, chunkSize_, seeds);
725 this->createTask<triangulationType>(
726 triangulation, chunkIntegralLine, offsets, chunkSize_);
728 int rest = seedNumber_ % chunkSize_;
730 this->prepareForTask<triangulationType>(
731 triangulation, chunkIntegralLine, taskNumber * chunkSize_, rest,
733 this->createTask<triangulationType>(
734 triangulation, chunkIntegralLine, offsets, rest);
736#ifdef TTK_ENABLE_OPENMP
741 if(ttk::isRunningWithMPI()) {
743 int finishedElementReceived = 0;
744 std::vector<int> sendMessageSize(neighborNumber_);
745 std::vector<int> recvMessageSize(neighborNumber_);
746 std::vector<std::vector<intgl::ElementToBeSent>> send_buf(neighborNumber_);
747 std::vector<std::vector<intgl::ElementToBeSent>> recv_buf(neighborNumber_);
748 for(i = 0; i < neighborNumber_; i++) {
749 send_buf.reserve((
int)seedNumber_ * 0.005);
750 recv_buf.reserve((
int)seedNumber_ * 0.005);
752 std::vector<MPI_Request> requests(2 * neighborNumber_, MPI_REQUEST_NULL);
753 std::vector<MPI_Status> statuses(4 * neighborNumber_);
756 int totalMessageSize;
757 while(keepWorking_) {
758 ttk::intgl::finishedElement_ -= ttk::intgl::addedElement_;
759 ttk::intgl::addedElement_ = 0;
761 MPI_Allreduce(&ttk::intgl::finishedElement_, &finishedElementReceived, 1,
762 MPI_INTEGER, MPI_SUM, ttk::MPIcomm_);
763 ttk::intgl::finishedElement_ = 0;
765 globalElementCounter_ -= finishedElementReceived;
767 if(globalElementCounter_ == 0) {
771 totalMessageSize = 0;
774 for(i = 0; i < neighborNumber_; i++) {
775 for(
int j = 0; j < threadNumber_; j++) {
776 send_buf[i].insert(send_buf[i].end(), toSend_->at(i)[j].begin(),
777 toSend_->at(i)[j].end());
778 toSend_->at(i)[j].clear();
780 sendMessageSize[i] = (int)send_buf[i].size();
781 MPI_Isend(&sendMessageSize[i], 1, MPI_INTEGER, neighbors_.at(i),
782 INTEGRAL_LINE_IS_MESSAGE_SIZE, ttk::MPIcomm_,
784 MPI_Irecv(&recvMessageSize[i], 1, MPI_INTEGER, neighbors_.at(i),
785 INTEGRAL_LINE_IS_MESSAGE_SIZE, ttk::MPIcomm_,
786 &requests[2 * i + 1]);
788 MPI_Waitall(2 * neighborNumber_, requests.data(), MPI_STATUSES_IGNORE);
790 for(i = 0; i < neighborNumber_; i++) {
791 if(recv_buf[i].size() < (
size_t)recvMessageSize[i]) {
792 recv_buf[i].resize(recvMessageSize[i]);
794 if(recvMessageSize[i] > 0) {
795 MPI_Irecv(recv_buf[i].data(), recvMessageSize[i], this->MessageType,
796 neighbors_.at(i), INTEGRAL_LINE_IS_ELEMENT_TO_PROCESS,
797 ttk::MPIcomm_, &requests[2 * i]);
798 totalMessageSize += recvMessageSize[i];
801 if(sendMessageSize[i] > 0) {
802 MPI_Isend(send_buf[i].data(), sendMessageSize[i], this->MessageType,
803 neighbors_.at(i), INTEGRAL_LINE_IS_ELEMENT_TO_PROCESS,
804 ttk::MPIcomm_, &requests[2 * i + 1]);
807 MPI_Waitall(2 * neighborNumber_, requests.data(), MPI_STATUSES_IGNORE);
808 for(i = 0; i < neighborNumber_; i++) {
812#ifdef TTK_ENABLE_OPENMP
813#pragma omp parallel shared(ttk::intgl::finishedElement_, toSend_) \
814 num_threads(threadNumber_)
821 (
ttk::SimplexId)std::max(totalMessageSize / (threadNumber_ * 100),
822 std::min(totalMessageSize, 50)),
824 chunkIntegralLine.resize(taskSize);
825 for(i = 0; i < neighborNumber_; i++) {
826 for(
int j = 0; j < recvMessageSize[i]; j++) {
827 this->receiveElement<triangulationType>(
828 triangulation, recv_buf[i][j], chunkIntegralLine, index,
833 this->createTask<triangulationType>(
834 triangulation, chunkIntegralLine, offsets, index);
836#ifdef TTK_ENABLE_OPENMP
845 std::stringstream msg;
846 msg <<
"Processed " << vertexNumber_ <<
" points";
853template <
typename triangulationType>
854int ttk::IntegralLines::getGlobalIdentifiers(
855 std::vector<ttk::SimplexId> &globalVertexId,
856 std::vector<ttk::SimplexId> &globalCellId,
860 const triangulationType *triangulation) {
867#ifdef TTK_ENABLE_OPENMP
868#pragma omp parallel for reduction(+:outputVertexNumber,outputCellNumber,realCellNumber,realVertexNumber) schedule(static,1) private(intervalSize)
870 for(
int thread = 0; thread < threadNumber_; thread++) {
874 = integralLines[thread].list_.begin();
875 while(integralLine != integralLines[thread].list_.end()) {
877 if(integralLine->at(i).trajectory.size() > 0) {
879 integralLine->at(i).trajectory.size());
880 outputVertexNumber += intervalSize;
881 outputCellNumber += intervalSize - 1;
882 if(triangulation->getVertexRank(integralLine->at(i).trajectory.at(0))
886 if(integralLine->at(i).trajectory.size() > 1) {
887 realCellNumber += intervalSize - 1;
888 if(triangulation->getVertexRank(
889 integralLine->at(i).trajectory.back())
894 realVertexNumber += intervalSize;
908 MPI_Exscan(&realVertexNumber, &vertIndex, 1, ttk::getMPIType(vertIndex),
909 MPI_SUM, ttk::MPIcomm_);
910 MPI_Exscan(&realCellNumber, &cellIndex, 1, ttk::getMPIType(cellIndex),
911 MPI_SUM, ttk::MPIcomm_);
924 globalVertexId.resize(outputVertexNumber);
925 globalCellId.resize(outputCellNumber);
926 std::vector<std::vector<ttk::intgl::GhostElementsToSort>> unmatchedGhosts(
928 std::vector<std::vector<ttk::SimplexId>> unmatchedGhostsVertexLocalId(
930 std::vector<std::vector<ttk::SimplexId>> unmatchedGhostsEdgeLocalId(
932 for(
int thread = 0; thread < threadNumber_; thread++) {
936 = integralLines[thread].list_.begin();
937 while(integralLine != integralLines[thread].list_.end()) {
939 if(integralLine->at(i).trajectory.size() > 0) {
940 if(triangulation->getVertexRank(integralLine->at(i).trajectory.at(0))
942 globalVertexId.at(startVertexId) = -1;
944 globalVertexId.at(startVertexId) = vertIndex;
948 if(integralLine->at(i).trajectory.size() > 1) {
949 if(triangulation->getVertexRank(
950 integralLine->at(i).trajectory.at(0))
952 globalCellId.at(startCellId) = -1;
954 .at(neighborsToId_[triangulation->getVertexRank(
955 integralLine->at(i).trajectory.at(0))])
956 .push_back(ttk::intgl::GhostElementsToSort{
957 vertIndex, integralLine->at(i).localVertexIdentifier.at(0),
958 integralLine->at(i).seedIdentifier,
959 integralLine->at(i).forkIdentifier, -1, startVertexId - 1,
962 globalCellId.at(startCellId) = cellIndex;
966 if(integralLine->at(i).trajectory.size() > 2) {
967 std::iota(globalCellId.begin() + startCellId,
968 globalCellId.begin() + startCellId
969 + integralLine->at(i).trajectory.size() - 2,
971 std::iota(globalVertexId.begin() + startVertexId,
972 globalVertexId.begin() + startVertexId
973 + integralLine->at(i).trajectory.size() - 2,
975 startCellId += integralLine->at(i).trajectory.size() - 2;
976 startVertexId += integralLine->at(i).trajectory.size() - 2;
977 vertIndex += integralLine->at(i).trajectory.size() - 2;
978 cellIndex += integralLine->at(i).trajectory.size() - 2;
980 if(triangulation->getVertexRank(
981 integralLine->at(i).trajectory.back())
983 globalVertexId.at(startVertexId) = -1;
985 .at(neighborsToId_[triangulation->getVertexRank(
986 integralLine->at(i).trajectory.back())])
987 .push_back(ttk::intgl::GhostElementsToSort{
988 globalVertexId.at(startVertexId - 1),
989 integralLine->at(i).localVertexIdentifier.at(
990 integralLine->at(i).localVertexIdentifier.size() - 2),
991 integralLine->at(i).seedIdentifier,
992 integralLine->at(i).forkIdentifier,
993 globalCellId.at(startCellId - 1), startVertexId,
996 globalVertexId.at(startVertexId) = vertIndex;
1021 for(
int i = 0; i < neighborNumber_; i++) {
1022 TTK_PSORT(threadNumber_, unmatchedGhosts.at(i).begin(),
1023 unmatchedGhosts.at(i).end());
1025 this->exchangeGhosts(unmatchedGhosts, globalVertexId, globalCellId);
1031inline int ttk::IntegralLines::exchangeGhosts(
1032 const std::vector<std::vector<ttk::intgl::GhostElementsToSort>>
1034 std::vector<ttk::SimplexId> &globalVertexId,
1035 std::vector<ttk::SimplexId> &globalCellId) {
1037 std::vector<std::vector<ttk::SimplexId>> globalIdsToSend(neighborNumber_);
1038 std::vector<std::vector<ttk::SimplexId>> globalIdsToReceive(neighborNumber_);
1039 for(
int i = 0; i < neighborNumber_; i++) {
1040 globalIdsToSend[i].resize(2 * unmatchedGhosts[i].size());
1041 globalIdsToReceive[i].resize(2 * unmatchedGhosts[i].size());
1044#ifdef TTK_ENABLE_OPENMP
1045#pragma omp parallel for
1047 for(
int i = 0; i < neighborNumber_; i++) {
1048 for(
size_t j = 0; j < unmatchedGhosts[i].size(); j++) {
1049 globalIdsToSend[i][2 * j] = unmatchedGhosts[i][j].ownedGlobalId;
1050 globalIdsToSend[i][2 * j + 1] = unmatchedGhosts[i][j].globalEdgeId;
1055 for(
int neighbor : neighbors_) {
1056 MPI_Sendrecv(globalIdsToSend[neighborsToId_[neighbor]].data(),
1057 globalIdsToSend[neighborsToId_[neighbor]].size(),
1059 globalIdsToReceive[neighborsToId_[neighbor]].data(),
1060 globalIdsToSend[neighborsToId_[neighbor]].size(),
1061 ttk::getMPIType(
id), neighbor, neighbor, ttk::MPIcomm_,
1066#ifdef TTK_ENABLE_OPENMP
1067#pragma omp parallel for
1069 for(
int i = 0; i < neighborNumber_; i++) {
1070 for(
size_t j = 0; j < unmatchedGhosts[i].size(); j++) {
1071 globalVertexId.at(unmatchedGhosts[i][j].ghostVertexLocalId)
1072 = globalIdsToReceive[i][2 * j];
1073 if(globalCellId.at(unmatchedGhosts[i][j].ghostEdgeLocalId) == -1) {
1074 globalCellId.at(unmatchedGhosts[i][j].ghostEdgeLocalId)
1075 = 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.
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::GREEN+" "+debug::output::ENDCOLOR+debug::output::GREEN+"▒"+debug::output::ENDCOLOR+debug::output::GREEN+"▒▒▒▒▒▒▒▒▒▒▒▒▒░"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)