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[]
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 std::map<int, int> &neighborsToId) {
202 if(neighborRanks.empty()) {
203 preconditionNeighborsUsingBoundingBox(
204 boundingBox, neighborRanks, neighborsToId);
206 neighbors_ = &neighborRanks;
207 neighborNumber_ = neighbors_->size();
208 neighborToId_ = neighborsToId;
225 void inline locatePoints(
226#ifdef TTK_ENABLE_OPENMP
227 std::vector<std::vector<Response>> &locatedSimplices,
229 std::vector<std::vector<Response>> &
ttkNotUsed(locatedSimplices),
231 std::vector<Point> &receivedPoints,
233 std::vector<Response> &send_buf) {
237#ifdef TTK_ENABLE_OPENMP
238#pragma omp parallel for num_threads(threadNumber_) firstprivate(globalId, id) \
239 shared(locatedSimplices)
241 for(
int n = 0; n < recvMessageSize; n++) {
242 if(bounds_[0] <= receivedPoints[n].x
243 && bounds_[1] >= receivedPoints[n].x
244 && bounds_[2] <= receivedPoints[n].y
245 && bounds_[3] >= receivedPoints[n].y
246 && bounds_[4] <= receivedPoints[n].z
247 && bounds_[5] >= receivedPoints[n].z) {
249 id, receivedPoints[n].x, receivedPoints[n].y, receivedPoints[n].z);
250 if((vertexRankArray_ !=
nullptr
252 || (vertGhost_ !=
nullptr && vertGhost_[
id] == 0)) {
255#ifdef TTK_ENABLE_OPENMP
256 locatedSimplices[omp_get_thread_num()].push_back(
257 Response{receivedPoints[n].localId, globalId});
259 send_buf.push_back(Response{receivedPoints[n].localId, globalId});
265#ifdef TTK_ENABLE_OPENMP
267 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
268 locatedSimplices[n].end());
269 locatedSimplices[n].clear();
286 void inline identifyPoints(
287#ifdef TTK_ENABLE_OPENMP
288 std::vector<std::vector<Response>> &locatedSimplices,
290 std::vector<std::vector<Response>> &
ttkNotUsed(locatedSimplices),
292 std::vector<ttk::SimplexId> &receivedOutdatedGlobalIds,
294 std::vector<Response> &send_buf) {
297 std::map<ttk::LongSimplexId, ttk::SimplexId>::iterator search;
298#ifdef TTK_ENABLE_OPENMP
299#pragma omp parallel for num_threads(threadNumber_)
301 for(
int n = 0; n < recvMessageSize; n++) {
302 search = vertOutdatedGtoL_.find(receivedOutdatedGlobalIds[n]);
303 if(search != vertOutdatedGtoL_.end()) {
306#ifdef TTK_ENABLE_OPENMP
307 locatedSimplices[omp_get_thread_num()].push_back(
308 Response{receivedOutdatedGlobalIds[n], globalId});
311 Response{receivedOutdatedGlobalIds[n], globalId});
316#ifdef TTK_ENABLE_OPENMP
318 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
319 locatedSimplices[n].end());
320 locatedSimplices[n].clear();
337 void inline locateCells(
338#ifdef TTK_ENABLE_OPENMP
339 std::vector<std::vector<Response>> &locatedSimplices,
341 std::vector<std::vector<Response>> &
ttkNotUsed(locatedSimplices),
343 std::vector<ttk::SimplexId> &receivedCells,
345 std::vector<Response> &send_buf) {
348 std::unordered_map<ttk::SimplexId, ttk::SimplexId>::iterator search;
349 std::vector<ttk::SimplexId> localPointIds;
350 localPointIds.reserve(dimension_ + 1);
351 size_t expectedSize =
static_cast<size_t>(dimension_) + 1;
352#ifdef TTK_ENABLE_OPENMP
353#pragma omp parallel for num_threads(threadNumber_) \
354 firstprivate(search, localPointIds)
356 for(
int n = 0; n < recvMessageSize; n += dimension_ + 2) {
357 localPointIds.clear();
358 for(
int k = 1; k < dimension_ + 2; k++) {
359 search = vertGtoL_->find(receivedCells[n + k]);
360 if(search != vertGtoL_->end()) {
361 localPointIds.push_back(search->second);
366 if(localPointIds.size() == expectedSize) {
367 bool foundIt =
false;
371 while(!foundIt && m < dimension_ + 1) {
372 int size = pointsToCells_[localPointIds[m]].size();
374 while(!foundIt && k < size) {
376 while(l < dimension_ + 1) {
377 id = connectivity_[pointsToCells_[localPointIds[m]][k]
380 auto it = find(localPointIds.begin(), localPointIds.end(),
id);
381 if(it == localPointIds.end()) {
386 if(l == dimension_ + 1) {
388#ifdef TTK_ENABLE_OPENMP
389 locatedSimplices[omp_get_thread_num()].push_back(Response{
393 send_buf.push_back(Response{
404#ifdef TTK_ENABLE_OPENMP
406 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
407 locatedSimplices[n].end());
408 locatedSimplices[n].clear();
425 void inline identifyCells(
426#ifdef TTK_ENABLE_OPENMP
427 std::vector<std::vector<Response>> &locatedSimplices,
429 std::vector<std::vector<Response>> &
ttkNotUsed(locatedSimplices),
431 std::vector<ttk::SimplexId> &receivedOutdatedGlobalIds,
433 std::vector<Response> &send_buf) {
435 std::map<ttk::LongSimplexId, ttk::SimplexId>::iterator search;
437#ifdef TTK_ENABLE_OPENMP
438#pragma omp parallel for num_threads(threadNumber_)
440 for(
int n = 0; n < recvMessageSize; n++) {
441 search = cellOutdatedGtoL_.find(receivedOutdatedGlobalIds[n]);
442 if(search != cellOutdatedGtoL_.end()) {
445#ifdef TTK_ENABLE_OPENMP
446 locatedSimplices[omp_get_thread_num()].push_back(
447 Response{receivedOutdatedGlobalIds[n], globalId});
450 Response{receivedOutdatedGlobalIds[n], globalId});
455#ifdef TTK_ENABLE_OPENMP
457 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
458 locatedSimplices[n].end());
459 locatedSimplices[n].clear();
464 template <
typename dataType>
465 void sendToAllNeighbors(std::vector<dataType> &vectorToSend,
466 MPI_Datatype messageType)
const {
467 for(
int j = 0; j < neighborNumber_; j++) {
468 sendVector<dataType>(vectorToSend, messageType, neighbors_->at(j));
472 template <
typename dataType>
473 void sendToAllNeighborsUsingRankArray(
474 std::vector<std::vector<dataType>> &vectorToSend,
475 MPI_Datatype messageType) {
477 for(
int j = 0; j < neighborNumber_; j++) {
478 sendVector<dataType>(vectorToSend[neighborToId_[neighbors_->at(j)]],
479 messageType, neighbors_->at(j));
501 void generateGlobalIds(
502 std::vector<std::vector<Point>> &vertGhostCoordinatesPerRank,
503 std::vector<Point> &vertGhostCoordinates,
504 std::vector<std::vector<ttk::SimplexId>> &vertGhostGlobalIdsPerRank,
505 std::vector<ttk::SimplexId> &vertGhostGlobalIds) {
514 if(vertexRankArray_ !=
nullptr) {
518 if(outdatedGlobalPointIds_ ==
nullptr) {
519 p[0] = pointSet_[i * 3];
520 p[1] = pointSet_[i * 3 + 1];
521 p[2] = pointSet_[i * 3 + 2];
522 vertGhostCoordinatesPerRank[neighborToId_[vertexRankArray_[i]]]
523 .push_back(
Point{p[0], p[1], p[2], i});
525 vertGhostGlobalIdsPerRank[neighborToId_[vertexRankArray_[i]]]
533 if(vertGhost_[i] != 0) {
535 if(outdatedGlobalPointIds_ ==
nullptr) {
537 p[0] = pointSet_[i * 3];
538 p[1] = pointSet_[i * 3 + 1];
539 p[2] = pointSet_[i * 3 + 2];
540 vertGhostCoordinates.push_back(
Point{p[0], p[1], p[2], i});
542 vertGhostGlobalIds.push_back(
550 if(cellRankArray_ !=
nullptr) {
558 if(cellGhost_[i] != 0) {
570 &realVertexNumber, &vertIndex, 1, mpiIdType_, MPI_SUM, ttk::MPIcomm_);
572 &realCellNumber, &cellIndex, 1, mpiIdType_, MPI_SUM, ttk::MPIcomm_);
582 if(vertexRankArray_ !=
nullptr) {
586 (*vertGtoL_)[vertIndex] = i;
589 if(outdatedGlobalPointIds_ !=
nullptr) {
590 vertOutdatedGtoL_[outdatedGlobalPointIds_[i]] = i;
595 if(vertGhost_[i] == 0) {
597 (*vertGtoL_)[vertIndex] = i;
600 if(outdatedGlobalPointIds_ !=
nullptr) {
601 vertOutdatedGtoL_[outdatedGlobalPointIds_[i]] = i;
607 if(cellRankArray_ !=
nullptr) {
613 if(outdatedGlobalCellIds_ !=
nullptr) {
614 cellOutdatedGtoL_[outdatedGlobalCellIds_[i]] = i;
619 if(cellGhost_[i] == 0) {
623 if(outdatedGlobalCellIds_ !=
nullptr) {
624 cellOutdatedGtoL_[outdatedGlobalCellIds_[i]] = i;
636 int executePolyData() {
638 std::vector<Point> vertGhostCoordinates;
639 std::vector<ttk::SimplexId> vertGhostGlobalIds;
640 std::vector<ttk::SimplexId> cellGhostGlobalVertexIds;
641 std::vector<ttk::SimplexId> cellGhostGlobalIds;
642 std::vector<std::vector<Point>> vertGhostCoordinatesPerRank;
643 std::vector<std::vector<ttk::SimplexId>> vertGhostGlobalIdsPerRank;
644 std::vector<std::vector<ttk::SimplexId>> cellGhostGlobalVertexIdsPerRank;
645 std::vector<std::vector<ttk::SimplexId>> cellGhostGlobalIdsPerRank;
652 if(vertexRankArray_ !=
nullptr) {
653 if(outdatedGlobalPointIds_ ==
nullptr) {
654 vertGhostCoordinatesPerRank.resize(neighborNumber_);
656 vertGhostGlobalIdsPerRank.resize(neighborNumber_);
661 if(cellRankArray_ !=
nullptr) {
662 if(outdatedGlobalCellIds_ ==
nullptr) {
663 cellGhostGlobalVertexIdsPerRank.resize(neighborNumber_);
665 cellGhostGlobalIdsPerRank.resize(neighborNumber_);
669 this->generateGlobalIds(vertGhostCoordinatesPerRank, vertGhostCoordinates,
670 vertGhostGlobalIdsPerRank, vertGhostGlobalIds);
676 std::vector<Point> receivedPoints;
677 std::vector<ttk::SimplexId> receivedIds;
678 std::vector<Response> receivedResponse;
679 std::vector<Response> send_buf;
680 std::vector<std::vector<Response>> locatedSimplices(
threadNumber_);
684 for(
int i = 0; i < neighborNumber_ + 1; i++) {
685 if((i == neighborNumber_ && !hasSentData_)
686 || (!hasSentData_ && ttk::MPIrank_ < neighbors_->at(i))) {
688 if(outdatedGlobalPointIds_ ==
nullptr) {
689 if(vertexRankArray_ ==
nullptr) {
690 sendToAllNeighbors<Point>(vertGhostCoordinates, mpiPointType_);
692 sendToAllNeighborsUsingRankArray<Point>(
693 vertGhostCoordinatesPerRank, mpiPointType_);
696 if(vertexRankArray_ ==
nullptr) {
697 sendToAllNeighbors<ttk::SimplexId>(
698 vertGhostGlobalIds, mpiIdType_);
700 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
701 vertGhostGlobalIdsPerRank, mpiIdType_);
706 for(
int j = 0; j < neighborNumber_; j++) {
707 recvVector<Response>(receivedResponse, recvMessageSize,
708 mpiResponseType_, neighbors_->at(j));
709 if(outdatedGlobalPointIds_ ==
nullptr) {
710 for(
int n = 0; n < recvMessageSize; n++) {
712 = receivedResponse[n].globalId;
713 (*vertGtoL_)[receivedResponse[n].globalId]
714 = receivedResponse[n].id;
717 for(
int n = 0; n < recvMessageSize; n++) {
719 = receivedResponse[n].globalId;
720 (*vertGtoL_)[receivedResponse[n].globalId]
721 = receivedResponse[n].id;
728 if(outdatedGlobalPointIds_ ==
nullptr) {
729 recvVector<Point>(receivedPoints, recvMessageSize, mpiPointType_,
730 neighbors_->at(i - hasSentData_));
734 locatedSimplices, receivedPoints, recvMessageSize, send_buf);
736 recvVector<ttk::SimplexId>(receivedIds, recvMessageSize, mpiIdType_,
737 neighbors_->at(i - hasSentData_));
741 locatedSimplices, receivedIds, recvMessageSize, send_buf);
745 sendVector<Response>(
746 send_buf, mpiResponseType_, neighbors_->at(i - hasSentData_));
753 if(cellRankArray_ !=
nullptr) {
756 if(outdatedGlobalCellIds_ ==
nullptr) {
757 cellGhostGlobalVertexIdsPerRank[neighborToId_[cellRankArray_[i]]]
759 for(
int k = 0; k < dimension_ + 1; k++) {
760 id = connectivity_[i * (dimension_ + 1) + k];
761 cellGhostGlobalVertexIdsPerRank
762 [neighborToId_[cellRankArray_[i]]]
766 cellGhostGlobalIdsPerRank[neighborToId_[cellRankArray_[i]]]
776 if(cellGhost_[i] != 0) {
777 if(outdatedGlobalCellIds_ ==
nullptr) {
778 cellGhostGlobalVertexIds.push_back(i);
779 for(
int k = 0; k < dimension_ + 1; k++) {
780 id = connectivity_[i * (dimension_ + 1) + k];
784 cellGhostGlobalIds.push_back(
793 for(
int i = 0; i < neighborNumber_ + 1; i++) {
794 if((i == neighborNumber_ && !hasSentData_)
799 if(outdatedGlobalCellIds_ ==
nullptr) {
800 if(cellRankArray_ ==
nullptr) {
801 sendToAllNeighbors<ttk::SimplexId>(
802 cellGhostGlobalVertexIds, mpiIdType_);
804 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
805 cellGhostGlobalVertexIdsPerRank, mpiIdType_);
808 if(cellRankArray_ ==
nullptr) {
809 sendToAllNeighbors<ttk::SimplexId>(
810 cellGhostGlobalIds, mpiIdType_);
812 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
813 cellGhostGlobalIdsPerRank, mpiIdType_);
818 for(
int j = 0; j < neighborNumber_; j++) {
819 recvVector<Response>(receivedResponse, recvMessageSize,
820 mpiResponseType_, neighbors_->at(j));
821 if(outdatedGlobalCellIds_ ==
nullptr) {
822 for(
int n = 0; n < recvMessageSize; n++) {
824 = receivedResponse[n].globalId;
827 for(
int n = 0; n < recvMessageSize; n++) {
829 = receivedResponse[n].globalId;
836 recvVector<ttk::SimplexId>(receivedIds, recvMessageSize, mpiIdType_,
837 neighbors_->at(i - hasSentData_));
838 if(outdatedGlobalCellIds_ ==
nullptr) {
842 locatedSimplices, receivedIds, recvMessageSize, send_buf);
847 locatedSimplices, receivedIds, recvMessageSize, send_buf);
851 sendVector<Response>(
852 send_buf, mpiResponseType_, neighbors_->at(i - hasSentData_));
864 int executeImageData() {
870 double tempBounds[6] = {
871 bounds_[0], bounds_[2], bounds_[4], bounds_[1], bounds_[3], bounds_[5]};
872 double tempGlobalBounds[6];
875 tempBounds, tempGlobalBounds, 3, MPI_DOUBLE, MPI_MIN, ttk::MPIcomm_);
878 MPI_Allreduce(tempBounds + 3, tempGlobalBounds + 3, 3, MPI_DOUBLE,
879 MPI_MAX, ttk::MPIcomm_);
881 double globalBounds[6]
882 = {tempGlobalBounds[0], tempGlobalBounds[3], tempGlobalBounds[1],
883 tempGlobalBounds[4], tempGlobalBounds[2], tempGlobalBounds[5]};
886 =
static_cast<int>((globalBounds[1] - globalBounds[0]) / spacing_[0])
889 =
static_cast<int>((globalBounds[3] - globalBounds[2]) / spacing_[1])
893 int offsetWidth =
static_cast<int>(
894 std::round((bounds_[0] - globalBounds[0]) / spacing_[0]));
895 int offsetHeight =
static_cast<int>(
896 std::round((bounds_[2] - globalBounds[2]) / spacing_[1]));
897 int offsetLength =
static_cast<int>(
898 std::round((bounds_[4] - globalBounds[4]) / spacing_[2]));
900#ifdef TTK_ENABLE_OPENMP
901#pragma omp parallel for num_threads(threadNumber_)
903 for(
int k = 0; k < dims_[2]; k++) {
904 for(
int j = 0; j < dims_[1]; j++) {
905 for(
int i = 0; i < dims_[0]; i++) {
907 = i + offsetWidth + (j + offsetHeight) * width
908 + (k + offsetLength) * width * height;
919#ifdef TTK_ENABLE_OPENMP
920#pragma omp parallel for num_threads(threadNumber_)
922 for(
int k = 0; k < dims_[2]; k++) {
923 for(
int j = 0; j < dims_[1]; j++) {
924 for(
int i = 0; i < dims_[0]; i++) {
926 = i + offsetWidth + (j + offsetHeight) * width
927 + (k + offsetLength) * width * height;
946#ifdef TTK_ENABLE_OPENMP
947#pragma omp parallel for num_threads(threadNumber_)
954#ifdef TTK_ENABLE_OPENMP
955#pragma omp parallel for num_threads(threadNumber_)