58 std::unordered_map<ttk::SimplexId, ttk::SimplexId> *vertGtoL_;
59 std::vector<int> *neighbors_;
60 std::map<int, int> neighborToId_;
65 MPI_Datatype mpiIdType_;
66 MPI_Datatype mpiResponseType_;
67 MPI_Datatype mpiPointType_;
70 int *vertexRankArray_{
nullptr};
71 int *cellRankArray_{
nullptr};
72 unsigned char *vertGhost_{
nullptr};
73 unsigned char *cellGhost_{
nullptr};
74 std::vector<std::vector<ttk::SimplexId>> pointsToCells_;
79 std::map<ttk::LongSimplexId, ttk::SimplexId> vertOutdatedGtoL_;
80 std::map<ttk::LongSimplexId, ttk::SimplexId> cellOutdatedGtoL_;
94 this->vertexIdentifiers_ = vertexIdentifiers;
98 this->cellIdentifiers_ = cellIdentifiers;
103 inline void setDomainDimension(
const int &dimension) {
104 dimension_ = dimension;
107 inline void setPointsToCells(
108 const std::vector<std::vector<ttk::SimplexId>> &pointsToCells) {
109 pointsToCells_ = pointsToCells;
112 void setVertexRankArray(
int *vertexRankArray) {
113 this->vertexRankArray_ = vertexRankArray;
116 void setCellRankArray(
int *cellRankArray) {
117 this->cellRankArray_ = cellRankArray;
120 void setVertGhost(
unsigned char *vertGhost) {
121 this->vertGhost_ = vertGhost;
124 void setCellGhost(
unsigned char *cellGhost) {
125 this->cellGhost_ = cellGhost;
128 void setBounds(
double *bounds) {
129 this->bounds_ = bounds;
133 std::unordered_map<ttk::SimplexId, ttk::SimplexId> *vertGtoL) {
134 this->vertGtoL_ = vertGtoL;
137 void setSpacing(
double *spacing) {
138 this->spacing_ = spacing;
141 void setDims(
int *dims) {
145 void setPointSet(
float *pointSet) {
146 pointSet_ = pointSet;
150 connectivity_ = connectivity;
154 outdatedGlobalPointIds_ = outdatedGlobalPointIds;
163 outdatedGlobalCellIds_ = outdatedGlobalCellIds;
166 void initializeMPITypes() {
170 mpiIdType_ = getMPIType(
id);
173 MPI_Datatype types[] = {MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE, mpiIdType_};
174 int lengths[] = {1, 1, 1, 1};
175 const long int mpi_offsets[]
176 = {offsetof(Point, x), offsetof(Point, y), offsetof(Point, z),
177 offsetof(Point, localId)};
178 MPI_Type_create_struct(4, lengths, mpi_offsets, types, &mpiPointType_);
179 MPI_Type_commit(&mpiPointType_);
182 MPI_Datatype typesResponse[] = {mpiIdType_, getMPIType(longId)};
183 int lengthsResponse[] = {1, 1};
184 const long int mpi_offsetsResponse[]
185 = {offsetof(Response,
id), offsetof(Response, globalId)};
186 MPI_Type_create_struct(2, lengthsResponse, mpi_offsetsResponse,
187 typesResponse, &mpiResponseType_);
188 MPI_Type_commit(&mpiResponseType_);
191 void inline findPoint(
ttk::SimplexId &
id,
float x,
float y,
float z) {
192 std::array<float, 3> coordinates = {x, y, z};
193 std::vector<ttk::KDTree<float, std::array<float, 3>> *> neighbours;
194 std::vector<float> costs;
195 kdt_.
getKClosest(1, coordinates, neighbours, costs);
196 id = neighbours[0]->id_;
199 void initializeNeighbors(
double *boundingBox,
200 std::vector<int> &neighborRanks) {
201 if(neighborRanks.empty()) {
202 preconditionNeighborsUsingBoundingBox(boundingBox, neighborRanks);
204 neighbors_ = &neighborRanks;
205 neighborToId_.clear();
206 neighborNumber_ = neighbors_->size();
207 for(
int i = 0; i < neighborNumber_; i++) {
208 neighborToId_[neighbors_->at(i)] = i;
226 void inline locatePoints(
227#ifdef TTK_ENABLE_OPENMP
228 std::vector<std::vector<Response>> &locatedSimplices,
230 std::vector<std::vector<Response>> &
ttkNotUsed(locatedSimplices),
232 std::vector<Point> &receivedPoints,
234 std::vector<Response> &send_buf) {
238#ifdef TTK_ENABLE_OPENMP
239#pragma omp parallel for num_threads(threadNumber_) firstprivate(globalId, id) \
240 shared(locatedSimplices)
242 for(
int n = 0; n < recvMessageSize; n++) {
243 if(bounds_[0] <= receivedPoints[n].x
244 && bounds_[1] >= receivedPoints[n].x
245 && bounds_[2] <= receivedPoints[n].y
246 && bounds_[3] >= receivedPoints[n].y
247 && bounds_[4] <= receivedPoints[n].z
248 && bounds_[5] >= receivedPoints[n].z) {
250 id, receivedPoints[n].x, receivedPoints[n].y, receivedPoints[n].z);
251 if((vertexRankArray_ !=
nullptr
253 || (vertGhost_ !=
nullptr && vertGhost_[
id] == 0)) {
256#ifdef TTK_ENABLE_OPENMP
257 locatedSimplices[omp_get_thread_num()].push_back(
258 Response{receivedPoints[n].localId, globalId});
260 send_buf.push_back(Response{receivedPoints[n].localId, globalId});
266#ifdef TTK_ENABLE_OPENMP
268 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
269 locatedSimplices[n].end());
270 locatedSimplices[n].clear();
287 void inline identifyPoints(
288#ifdef TTK_ENABLE_OPENMP
289 std::vector<std::vector<Response>> &locatedSimplices,
291 std::vector<std::vector<Response>> &
ttkNotUsed(locatedSimplices),
293 std::vector<ttk::SimplexId> &receivedOutdatedGlobalIds,
295 std::vector<Response> &send_buf) {
298 std::map<ttk::LongSimplexId, ttk::SimplexId>::iterator search;
299#ifdef TTK_ENABLE_OPENMP
300#pragma omp parallel for num_threads(threadNumber_)
302 for(
int n = 0; n < recvMessageSize; n++) {
303 search = vertOutdatedGtoL_.find(receivedOutdatedGlobalIds[n]);
304 if(search != vertOutdatedGtoL_.end()) {
307#ifdef TTK_ENABLE_OPENMP
308 locatedSimplices[omp_get_thread_num()].push_back(
309 Response{receivedOutdatedGlobalIds[n], globalId});
312 Response{receivedOutdatedGlobalIds[n], globalId});
317#ifdef TTK_ENABLE_OPENMP
319 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
320 locatedSimplices[n].end());
321 locatedSimplices[n].clear();
338 void inline locateCells(
339#ifdef TTK_ENABLE_OPENMP
340 std::vector<std::vector<Response>> &locatedSimplices,
342 std::vector<std::vector<Response>> &
ttkNotUsed(locatedSimplices),
344 std::vector<ttk::SimplexId> &receivedCells,
346 std::vector<Response> &send_buf) {
349 std::unordered_map<ttk::SimplexId, ttk::SimplexId>::iterator search;
350 std::vector<ttk::SimplexId> localPointIds;
351 localPointIds.reserve(dimension_ + 1);
352 size_t expectedSize =
static_cast<size_t>(dimension_) + 1;
353#ifdef TTK_ENABLE_OPENMP
354#pragma omp parallel for num_threads(threadNumber_) \
355 firstprivate(search, localPointIds)
357 for(
int n = 0; n < recvMessageSize; n += dimension_ + 2) {
358 localPointIds.clear();
359 for(
int k = 1; k < dimension_ + 2; k++) {
360 search = vertGtoL_->find(receivedCells[n + k]);
361 if(search != vertGtoL_->end()) {
362 localPointIds.push_back(search->second);
367 if(localPointIds.size() == expectedSize) {
368 bool foundIt =
false;
372 while(!foundIt && m < dimension_ + 1) {
373 int size = pointsToCells_[localPointIds[m]].size();
375 while(!foundIt && k < size) {
377 while(l < dimension_ + 1) {
378 id = connectivity_[pointsToCells_[localPointIds[m]][k]
381 auto it = find(localPointIds.begin(), localPointIds.end(),
id);
382 if(it == localPointIds.end()) {
387 if(l == dimension_ + 1) {
389#ifdef TTK_ENABLE_OPENMP
390 locatedSimplices[omp_get_thread_num()].push_back(Response{
394 send_buf.push_back(Response{
405#ifdef TTK_ENABLE_OPENMP
407 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
408 locatedSimplices[n].end());
409 locatedSimplices[n].clear();
426 void inline identifyCells(
427#ifdef TTK_ENABLE_OPENMP
428 std::vector<std::vector<Response>> &locatedSimplices,
430 std::vector<std::vector<Response>> &
ttkNotUsed(locatedSimplices),
432 std::vector<ttk::SimplexId> &receivedOutdatedGlobalIds,
434 std::vector<Response> &send_buf) {
436 std::map<ttk::LongSimplexId, ttk::SimplexId>::iterator search;
438#ifdef TTK_ENABLE_OPENMP
439#pragma omp parallel for num_threads(threadNumber_)
441 for(
int n = 0; n < recvMessageSize; n++) {
442 search = cellOutdatedGtoL_.find(receivedOutdatedGlobalIds[n]);
443 if(search != cellOutdatedGtoL_.end()) {
446#ifdef TTK_ENABLE_OPENMP
447 locatedSimplices[omp_get_thread_num()].push_back(
448 Response{receivedOutdatedGlobalIds[n], globalId});
451 Response{receivedOutdatedGlobalIds[n], globalId});
456#ifdef TTK_ENABLE_OPENMP
458 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
459 locatedSimplices[n].end());
460 locatedSimplices[n].clear();
465 template <
typename dataType>
466 void sendToAllNeighbors(std::vector<dataType> &vectorToSend,
467 MPI_Datatype messageType)
const {
468 for(
int j = 0; j < neighborNumber_; j++) {
469 sendVector<dataType>(vectorToSend, messageType, neighbors_->at(j));
473 template <
typename dataType>
474 void sendToAllNeighborsUsingRankArray(
475 std::vector<std::vector<dataType>> &vectorToSend,
476 MPI_Datatype messageType) {
478 for(
int j = 0; j < neighborNumber_; j++) {
479 sendVector<dataType>(vectorToSend[neighborToId_[neighbors_->at(j)]],
480 messageType, neighbors_->at(j));
502 void generateGlobalIds(
503 std::vector<std::vector<Point>> &vertGhostCoordinatesPerRank,
504 std::vector<Point> &vertGhostCoordinates,
505 std::vector<std::vector<ttk::SimplexId>> &vertGhostGlobalIdsPerRank,
506 std::vector<ttk::SimplexId> &vertGhostGlobalIds) {
515 if(vertexRankArray_ !=
nullptr) {
519 if(outdatedGlobalPointIds_ ==
nullptr) {
520 p[0] = pointSet_[i * 3];
521 p[1] = pointSet_[i * 3 + 1];
522 p[2] = pointSet_[i * 3 + 2];
523 vertGhostCoordinatesPerRank[neighborToId_[vertexRankArray_[i]]]
524 .push_back(Point{p[0], p[1], p[2], i});
526 vertGhostGlobalIdsPerRank[neighborToId_[vertexRankArray_[i]]]
534 if(vertGhost_[i] != 0) {
536 if(outdatedGlobalPointIds_ ==
nullptr) {
538 p[0] = pointSet_[i * 3];
539 p[1] = pointSet_[i * 3 + 1];
540 p[2] = pointSet_[i * 3 + 2];
541 vertGhostCoordinates.push_back(Point{p[0], p[1], p[2], i});
543 vertGhostGlobalIds.push_back(
551 if(cellRankArray_ !=
nullptr) {
559 if(cellGhost_[i] != 0) {
571 &realVertexNumber, &vertIndex, 1, mpiIdType_, MPI_SUM, ttk::MPIcomm_);
573 &realCellNumber, &cellIndex, 1, mpiIdType_, MPI_SUM, ttk::MPIcomm_);
583 if(vertexRankArray_ !=
nullptr) {
587 (*vertGtoL_)[vertIndex] = i;
590 if(outdatedGlobalPointIds_ !=
nullptr) {
591 vertOutdatedGtoL_[outdatedGlobalPointIds_[i]] = i;
596 if(vertGhost_[i] == 0) {
598 (*vertGtoL_)[vertIndex] = i;
601 if(outdatedGlobalPointIds_ !=
nullptr) {
602 vertOutdatedGtoL_[outdatedGlobalPointIds_[i]] = i;
608 if(cellRankArray_ !=
nullptr) {
614 if(outdatedGlobalCellIds_ !=
nullptr) {
615 cellOutdatedGtoL_[outdatedGlobalCellIds_[i]] = i;
620 if(cellGhost_[i] == 0) {
624 if(outdatedGlobalCellIds_ !=
nullptr) {
625 cellOutdatedGtoL_[outdatedGlobalCellIds_[i]] = i;
637 int executePolyData() {
639 std::vector<Point> vertGhostCoordinates;
640 std::vector<ttk::SimplexId> vertGhostGlobalIds;
641 std::vector<ttk::SimplexId> cellGhostGlobalVertexIds;
642 std::vector<ttk::SimplexId> cellGhostGlobalIds;
643 std::vector<std::vector<Point>> vertGhostCoordinatesPerRank;
644 std::vector<std::vector<ttk::SimplexId>> vertGhostGlobalIdsPerRank;
645 std::vector<std::vector<ttk::SimplexId>> cellGhostGlobalVertexIdsPerRank;
646 std::vector<std::vector<ttk::SimplexId>> cellGhostGlobalIdsPerRank;
653 if(vertexRankArray_ !=
nullptr) {
654 if(outdatedGlobalPointIds_ ==
nullptr) {
655 vertGhostCoordinatesPerRank.resize(neighborNumber_);
657 vertGhostGlobalIdsPerRank.resize(neighborNumber_);
662 if(cellRankArray_ !=
nullptr) {
663 if(outdatedGlobalCellIds_ ==
nullptr) {
664 cellGhostGlobalVertexIdsPerRank.resize(neighborNumber_);
666 cellGhostGlobalIdsPerRank.resize(neighborNumber_);
670 this->generateGlobalIds(vertGhostCoordinatesPerRank, vertGhostCoordinates,
671 vertGhostGlobalIdsPerRank, vertGhostGlobalIds);
677 std::vector<Point> receivedPoints;
678 std::vector<ttk::SimplexId> receivedIds;
679 std::vector<Response> receivedResponse;
680 std::vector<Response> send_buf;
681 std::vector<std::vector<Response>> locatedSimplices(
threadNumber_);
685 for(
int i = 0; i < neighborNumber_ + 1; i++) {
686 if((i == neighborNumber_ && !hasSentData_)
687 || (!hasSentData_ && ttk::MPIrank_ < neighbors_->at(i))) {
689 if(outdatedGlobalPointIds_ ==
nullptr) {
690 if(vertexRankArray_ ==
nullptr) {
691 sendToAllNeighbors<Point>(vertGhostCoordinates, mpiPointType_);
693 sendToAllNeighborsUsingRankArray<Point>(
694 vertGhostCoordinatesPerRank, mpiPointType_);
697 if(vertexRankArray_ ==
nullptr) {
698 sendToAllNeighbors<ttk::SimplexId>(
699 vertGhostGlobalIds, mpiIdType_);
701 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
702 vertGhostGlobalIdsPerRank, mpiIdType_);
707 for(
int j = 0; j < neighborNumber_; j++) {
708 recvVector<Response>(receivedResponse, recvMessageSize,
709 mpiResponseType_, neighbors_->at(j));
710 if(outdatedGlobalPointIds_ ==
nullptr) {
711 for(
int n = 0; n < recvMessageSize; n++) {
713 = receivedResponse[n].globalId;
714 (*vertGtoL_)[receivedResponse[n].globalId]
715 = receivedResponse[n].id;
718 for(
int n = 0; n < recvMessageSize; n++) {
720 = receivedResponse[n].globalId;
721 (*vertGtoL_)[receivedResponse[n].globalId]
722 = receivedResponse[n].id;
729 if(outdatedGlobalPointIds_ ==
nullptr) {
730 recvVector<Point>(receivedPoints, recvMessageSize, mpiPointType_,
731 neighbors_->at(i - hasSentData_));
735 locatedSimplices, receivedPoints, recvMessageSize, send_buf);
737 recvVector<ttk::SimplexId>(receivedIds, recvMessageSize, mpiIdType_,
738 neighbors_->at(i - hasSentData_));
742 locatedSimplices, receivedIds, recvMessageSize, send_buf);
746 sendVector<Response>(
747 send_buf, mpiResponseType_, neighbors_->at(i - hasSentData_));
754 if(cellRankArray_ !=
nullptr) {
757 if(outdatedGlobalCellIds_ ==
nullptr) {
758 cellGhostGlobalVertexIdsPerRank[neighborToId_[cellRankArray_[i]]]
760 for(
int k = 0; k < dimension_ + 1; k++) {
761 id = connectivity_[i * (dimension_ + 1) + k];
762 cellGhostGlobalVertexIdsPerRank
763 [neighborToId_[cellRankArray_[i]]]
767 cellGhostGlobalIdsPerRank[neighborToId_[cellRankArray_[i]]]
777 if(cellGhost_[i] != 0) {
778 if(outdatedGlobalCellIds_ ==
nullptr) {
779 cellGhostGlobalVertexIds.push_back(i);
780 for(
int k = 0; k < dimension_ + 1; k++) {
781 id = connectivity_[i * (dimension_ + 1) + k];
785 cellGhostGlobalIds.push_back(
794 for(
int i = 0; i < neighborNumber_ + 1; i++) {
795 if((i == neighborNumber_ && !hasSentData_)
800 if(outdatedGlobalCellIds_ ==
nullptr) {
801 if(cellRankArray_ ==
nullptr) {
802 sendToAllNeighbors<ttk::SimplexId>(
803 cellGhostGlobalVertexIds, mpiIdType_);
805 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
806 cellGhostGlobalVertexIdsPerRank, mpiIdType_);
809 if(cellRankArray_ ==
nullptr) {
810 sendToAllNeighbors<ttk::SimplexId>(
811 cellGhostGlobalIds, mpiIdType_);
813 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
814 cellGhostGlobalIdsPerRank, mpiIdType_);
819 for(
int j = 0; j < neighborNumber_; j++) {
820 recvVector<Response>(receivedResponse, recvMessageSize,
821 mpiResponseType_, neighbors_->at(j));
822 if(outdatedGlobalCellIds_ ==
nullptr) {
823 for(
int n = 0; n < recvMessageSize; n++) {
825 = receivedResponse[n].globalId;
828 for(
int n = 0; n < recvMessageSize; n++) {
830 = receivedResponse[n].globalId;
837 recvVector<ttk::SimplexId>(receivedIds, recvMessageSize, mpiIdType_,
838 neighbors_->at(i - hasSentData_));
839 if(outdatedGlobalCellIds_ ==
nullptr) {
843 locatedSimplices, receivedIds, recvMessageSize, send_buf);
848 locatedSimplices, receivedIds, recvMessageSize, send_buf);
852 sendVector<Response>(
853 send_buf, mpiResponseType_, neighbors_->at(i - hasSentData_));
865 int executeImageData() {
871 double tempBounds[6] = {
872 bounds_[0], bounds_[2], bounds_[4], bounds_[1], bounds_[3], bounds_[5]};
873 double tempGlobalBounds[6];
876 tempBounds, tempGlobalBounds, 3, MPI_DOUBLE, MPI_MIN, ttk::MPIcomm_);
879 MPI_Allreduce(tempBounds + 3, tempGlobalBounds + 3, 3, MPI_DOUBLE,
880 MPI_MAX, ttk::MPIcomm_);
882 double globalBounds[6]
883 = {tempGlobalBounds[0], tempGlobalBounds[3], tempGlobalBounds[1],
884 tempGlobalBounds[4], tempGlobalBounds[2], tempGlobalBounds[5]};
887 =
static_cast<int>((globalBounds[1] - globalBounds[0]) / spacing_[0])
890 =
static_cast<int>((globalBounds[3] - globalBounds[2]) / spacing_[1])
894 int offsetWidth =
static_cast<int>(
895 std::round((bounds_[0] - globalBounds[0]) / spacing_[0]));
896 int offsetHeight =
static_cast<int>(
897 std::round((bounds_[2] - globalBounds[2]) / spacing_[1]));
898 int offsetLength =
static_cast<int>(
899 std::round((bounds_[4] - globalBounds[4]) / spacing_[2]));
901#ifdef TTK_ENABLE_OPENMP
902#pragma omp parallel for num_threads(threadNumber_)
904 for(
int k = 0; k < dims_[2]; k++) {
905 for(
int j = 0; j < dims_[1]; j++) {
906 for(
int i = 0; i < dims_[0]; i++) {
908 = i + offsetWidth + (j + offsetHeight) * width
909 + (k + offsetLength) * width * height;
920#ifdef TTK_ENABLE_OPENMP
921#pragma omp parallel for num_threads(threadNumber_)
923 for(
int k = 0; k < dims_[2]; k++) {
924 for(
int j = 0; j < dims_[1]; j++) {
925 for(
int i = 0; i < dims_[0]; i++) {
927 = i + offsetWidth + (j + offsetHeight) * width
928 + (k + offsetLength) * width * height;
947#ifdef TTK_ENABLE_OPENMP
948#pragma omp parallel for num_threads(threadNumber_)
955#ifdef TTK_ENABLE_OPENMP
956#pragma omp parallel for num_threads(threadNumber_)
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Minimalist debugging class.
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
void setCellIdentifiers(ttk::LongSimplexId *cellIdentifiers)
ttk::SimplexId cellNumber_
void setVertexNumber(const SimplexId &vertexNumber)
void setCellNumber(const SimplexId &cellNumber)
ttk::LongSimplexId * vertexIdentifiers_
int executeSequential()
Generates global ids for all data set type in sequential.
void setVertexIdentifiers(ttk::LongSimplexId *vertexIdentifiers)
~Identifiers() override=default
ttk::SimplexId vertexNumber_
ttk::LongSimplexId * cellIdentifiers_
void getKClosest(const unsigned int k, const Container &coordinates, KDTreeMap &neighbours, std::vector< dataType > &costs, const int weight_index=0)
KDTreeMap build(dataType *data, const int &ptNumber, const int &dimension, const std::vector< std::vector< dataType > > &weights={}, const int weight_number=1)
COMMON_EXPORTS int MPIrank_
long long int LongSimplexId
Identifier type for simplices of any dimension.
int SimplexId
Identifier type for simplices of any dimension.