TTK
Loading...
Searching...
No Matches
Identifiers.h
Go to the documentation of this file.
1
11
12#pragma once
13
14// ttk common includes
15#include <Debug.h>
16#ifdef TTK_ENABLE_MPI
17#include <Geometry.h>
18#include <KDTree.h>
19#include <map>
20#endif
21
22namespace ttk {
23
24#ifdef TTK_ENABLE_MPI
25 struct Point {
26 double x;
27 double y;
28 double z;
29 ttk::SimplexId localId;
30 };
31
32 struct Response {
34 ttk::LongSimplexId globalId;
35 };
36
37#endif
38
45 class Identifiers : virtual public Debug {
46
47 public:
49
50 ~Identifiers() override = default;
51
52 protected:
57#ifdef TTK_ENABLE_MPI
58 std::unordered_map<ttk::SimplexId, ttk::SimplexId> *vertGtoL_;
59 std::vector<int> *neighbors_;
60 std::map<int, int> neighborToId_;
61 int neighborNumber_;
62 double *bounds_;
63 int *dims_;
64 double *spacing_;
65 MPI_Datatype mpiIdType_;
66 MPI_Datatype mpiResponseType_;
67 MPI_Datatype mpiPointType_;
68 int dimension_{};
69 int hasSentData_{0};
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_;
75 float *pointSet_;
76 ttk::LongSimplexId *connectivity_;
77 ttk::LongSimplexId *outdatedGlobalPointIds_{nullptr};
78 ttk::LongSimplexId *outdatedGlobalCellIds_{nullptr};
79 std::map<ttk::LongSimplexId, ttk::SimplexId> vertOutdatedGtoL_;
80 std::map<ttk::LongSimplexId, ttk::SimplexId> cellOutdatedGtoL_;
82#endif
83
84 public:
85 void setVertexNumber(const SimplexId &vertexNumber) {
86 vertexNumber_ = vertexNumber;
87 }
88
89 void setCellNumber(const SimplexId &cellNumber) {
90 cellNumber_ = cellNumber;
91 }
92
93 void setVertexIdentifiers(ttk::LongSimplexId *vertexIdentifiers) {
94 this->vertexIdentifiers_ = vertexIdentifiers;
95 }
96
97 void setCellIdentifiers(ttk::LongSimplexId *cellIdentifiers) {
98 this->cellIdentifiers_ = cellIdentifiers;
99 }
100
101#ifdef TTK_ENABLE_MPI
102
103 inline void setDomainDimension(const int &dimension) {
104 dimension_ = dimension;
105 }
106
107 inline void setPointsToCells(
108 const std::vector<std::vector<ttk::SimplexId>> &pointsToCells) {
109 pointsToCells_ = pointsToCells;
110 }
111
112 void setVertexRankArray(int *vertexRankArray) {
113 this->vertexRankArray_ = vertexRankArray;
114 }
115
116 void setCellRankArray(int *cellRankArray) {
117 this->cellRankArray_ = cellRankArray;
118 }
119
120 void setVertGhost(unsigned char *vertGhost) {
121 this->vertGhost_ = vertGhost;
122 }
123
124 void setCellGhost(unsigned char *cellGhost) {
125 this->cellGhost_ = cellGhost;
126 }
127
128 void setBounds(double *bounds) {
129 this->bounds_ = bounds;
130 }
131
132 void setVertGtoL(
133 std::unordered_map<ttk::SimplexId, ttk::SimplexId> *vertGtoL) {
134 this->vertGtoL_ = vertGtoL;
135 }
136
137 void setSpacing(double *spacing) {
138 this->spacing_ = spacing;
139 }
140
141 void setDims(int *dims) {
142 this->dims_ = dims;
143 }
144
145 void setPointSet(float *pointSet) {
146 pointSet_ = pointSet;
147 }
148
149 void setConnectivity(ttk::LongSimplexId *connectivity) {
150 connectivity_ = connectivity;
151 }
152
153 void setOutdatedGlobalPointIds(ttk::LongSimplexId *outdatedGlobalPointIds) {
154 outdatedGlobalPointIds_ = outdatedGlobalPointIds;
155 }
156
157 void buildKDTree() {
159 kdt_.build(pointSet_, vertexNumber_, 3);
160 }
161
162 void setOutdatedGlobalCellIds(ttk::LongSimplexId *outdatedGlobalCellIds) {
163 outdatedGlobalCellIds_ = outdatedGlobalCellIds;
164 }
165
166 void initializeMPITypes() {
167 ttk::SimplexId id{-1};
168 ttk::LongSimplexId longId{-1};
169 // Initialize id type
170 mpiIdType_ = getMPIType(id);
171
172 // Initialize Point Type
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_);
180
181 // Initialize Response Type
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_);
189 }
190
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_;
197 }
198
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);
205 }
206 neighbors_ = &neighborRanks;
207 neighborNumber_ = neighbors_->size();
208 neighborToId_ = neighborsToId;
209 }
210
225 void inline locatePoints(
226#ifdef TTK_ENABLE_OPENMP
227 std::vector<std::vector<Response>> &locatedSimplices,
228#else
229 std::vector<std::vector<Response>> &ttkNotUsed(locatedSimplices),
230#endif
231 std::vector<Point> &receivedPoints,
232 ttk::SimplexId &recvMessageSize,
233 std::vector<Response> &send_buf) {
234 ttk::LongSimplexId globalId{-1};
235 ttk::SimplexId id{-1};
236 send_buf.clear();
237#ifdef TTK_ENABLE_OPENMP
238#pragma omp parallel for num_threads(threadNumber_) firstprivate(globalId, id) \
239 shared(locatedSimplices)
240#endif
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) {
248 this->findPoint(
249 id, receivedPoints[n].x, receivedPoints[n].y, receivedPoints[n].z);
250 if((vertexRankArray_ != nullptr
251 && vertexRankArray_[id] == ttk::MPIrank_)
252 || (vertGhost_ != nullptr && vertGhost_[id] == 0)) {
253 globalId = vertexIdentifiers_[id];
254 if(globalId >= 0) {
255#ifdef TTK_ENABLE_OPENMP
256 locatedSimplices[omp_get_thread_num()].push_back(
257 Response{receivedPoints[n].localId, globalId});
258#else
259 send_buf.push_back(Response{receivedPoints[n].localId, globalId});
260#endif
261 }
262 }
263 }
264 }
265#ifdef TTK_ENABLE_OPENMP
266 for(int n = 0; n < threadNumber_; n++) {
267 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
268 locatedSimplices[n].end());
269 locatedSimplices[n].clear();
270 }
271#endif
272 }
286 void inline identifyPoints(
287#ifdef TTK_ENABLE_OPENMP
288 std::vector<std::vector<Response>> &locatedSimplices,
289#else
290 std::vector<std::vector<Response>> &ttkNotUsed(locatedSimplices),
291#endif
292 std::vector<ttk::SimplexId> &receivedOutdatedGlobalIds,
293 ttk::SimplexId &recvMessageSize,
294 std::vector<Response> &send_buf) {
295 send_buf.clear();
296 ttk::SimplexId globalId{-1};
297 std::map<ttk::LongSimplexId, ttk::SimplexId>::iterator search;
298#ifdef TTK_ENABLE_OPENMP
299#pragma omp parallel for num_threads(threadNumber_)
300#endif
301 for(int n = 0; n < recvMessageSize; n++) {
302 search = vertOutdatedGtoL_.find(receivedOutdatedGlobalIds[n]);
303 if(search != vertOutdatedGtoL_.end()) {
304 globalId = vertexIdentifiers_[search->second];
305 if(globalId >= 0) {
306#ifdef TTK_ENABLE_OPENMP
307 locatedSimplices[omp_get_thread_num()].push_back(
308 Response{receivedOutdatedGlobalIds[n], globalId});
309#else
310 send_buf.push_back(
311 Response{receivedOutdatedGlobalIds[n], globalId});
312#endif
313 }
314 }
315 }
316#ifdef TTK_ENABLE_OPENMP
317 for(int n = 0; n < threadNumber_; n++) {
318 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
319 locatedSimplices[n].end());
320 locatedSimplices[n].clear();
321 }
322#endif
323 }
337 void inline locateCells(
338#ifdef TTK_ENABLE_OPENMP
339 std::vector<std::vector<Response>> &locatedSimplices,
340#else
341 std::vector<std::vector<Response>> &ttkNotUsed(locatedSimplices),
342#endif
343 std::vector<ttk::SimplexId> &receivedCells,
344 ttk::SimplexId &recvMessageSize,
345 std::vector<Response> &send_buf) {
346 int id{-1};
347 send_buf.clear();
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)
355#endif
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);
362 } else {
363 break;
364 }
365 }
366 if(localPointIds.size() == expectedSize) {
367 bool foundIt = false;
368 int k = 0;
369 int l;
370 int m = 0;
371 while(!foundIt && m < dimension_ + 1) {
372 int size = pointsToCells_[localPointIds[m]].size();
373 k = 0;
374 while(!foundIt && k < size) {
375 l = 0;
376 while(l < dimension_ + 1) {
377 id = connectivity_[pointsToCells_[localPointIds[m]][k]
378 * (dimension_ + 1)
379 + l];
380 auto it = find(localPointIds.begin(), localPointIds.end(), id);
381 if(it == localPointIds.end()) {
382 break;
383 }
384 l++;
385 }
386 if(l == dimension_ + 1) {
387 foundIt = true;
388#ifdef TTK_ENABLE_OPENMP
389 locatedSimplices[omp_get_thread_num()].push_back(Response{
390 receivedCells[n],
391 cellIdentifiers_[pointsToCells_[localPointIds[m]][k]]});
392#else
393 send_buf.push_back(Response{
394 receivedCells[n],
395 cellIdentifiers_[pointsToCells_[localPointIds[m]][k]]});
396#endif
397 }
398 k++;
399 }
400 m++;
401 }
402 }
403 }
404#ifdef TTK_ENABLE_OPENMP
405 for(int n = 0; n < threadNumber_; n++) {
406 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
407 locatedSimplices[n].end());
408 locatedSimplices[n].clear();
409 }
410#endif
411 }
425 void inline identifyCells(
426#ifdef TTK_ENABLE_OPENMP
427 std::vector<std::vector<Response>> &locatedSimplices,
428#else
429 std::vector<std::vector<Response>> &ttkNotUsed(locatedSimplices),
430#endif
431 std::vector<ttk::SimplexId> &receivedOutdatedGlobalIds,
432 ttk::SimplexId &recvMessageSize,
433 std::vector<Response> &send_buf) {
434 ttk::LongSimplexId globalId{-1};
435 std::map<ttk::LongSimplexId, ttk::SimplexId>::iterator search;
436 send_buf.clear();
437#ifdef TTK_ENABLE_OPENMP
438#pragma omp parallel for num_threads(threadNumber_)
439#endif
440 for(int n = 0; n < recvMessageSize; n++) {
441 search = cellOutdatedGtoL_.find(receivedOutdatedGlobalIds[n]);
442 if(search != cellOutdatedGtoL_.end()) {
443 globalId = cellIdentifiers_[search->second];
444 if(globalId >= 0) {
445#ifdef TTK_ENABLE_OPENMP
446 locatedSimplices[omp_get_thread_num()].push_back(
447 Response{receivedOutdatedGlobalIds[n], globalId});
448#else
449 send_buf.push_back(
450 Response{receivedOutdatedGlobalIds[n], globalId});
451#endif
452 }
453 }
454 }
455#ifdef TTK_ENABLE_OPENMP
456 for(int n = 0; n < threadNumber_; n++) {
457 send_buf.insert(send_buf.end(), locatedSimplices[n].begin(),
458 locatedSimplices[n].end());
459 locatedSimplices[n].clear();
460 }
461#endif
462 }
463
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));
469 }
470 }
471
472 template <typename dataType>
473 void sendToAllNeighborsUsingRankArray(
474 std::vector<std::vector<dataType>> &vectorToSend,
475 MPI_Datatype messageType) {
476
477 for(int j = 0; j < neighborNumber_; j++) {
478 sendVector<dataType>(vectorToSend[neighborToId_[neighbors_->at(j)]],
479 messageType, neighbors_->at(j));
480 }
481 }
482
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) {
506 ttk::SimplexId realVertexNumber = vertexNumber_;
507 ttk::SimplexId realCellNumber = cellNumber_;
508 float p[3];
509
510 // Computes the number of vertices owned by the current process
511 // If the vertex is not owned, it will be added to the vector of
512 // ghosts.
513
514 if(vertexRankArray_ != nullptr) {
515 for(ttk::SimplexId i = 0; i < vertexNumber_; i++) {
516 if(vertexRankArray_[i] != ttk::MPIrank_) {
517 realVertexNumber--;
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});
524 } else {
525 vertGhostGlobalIdsPerRank[neighborToId_[vertexRankArray_[i]]]
526 .push_back(
527 static_cast<ttk::SimplexId>(outdatedGlobalPointIds_[i]));
528 }
529 }
530 }
531 } else {
532 for(ttk::SimplexId i = 0; i < vertexNumber_; i++) {
533 if(vertGhost_[i] != 0) {
534 realVertexNumber--;
535 if(outdatedGlobalPointIds_ == nullptr) {
536
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});
541 } else {
542 vertGhostGlobalIds.push_back(
543 static_cast<ttk::SimplexId>(outdatedGlobalPointIds_[i]));
544 }
545 }
546 }
547 }
548
549 // The number of cells owned by the process is computed
550 if(cellRankArray_ != nullptr) {
551 for(ttk::SimplexId i = 0; i < cellNumber_; i++) {
552 if(cellRankArray_[i] != ttk::MPIrank_) {
553 realCellNumber--;
554 }
555 }
556 } else {
557 for(ttk::SimplexId i = 0; i < cellNumber_; i++) {
558 if(cellGhost_[i] != 0) {
559 realCellNumber--;
560 }
561 }
562 }
563
564 ttk::SimplexId vertIndex;
565 ttk::SimplexId cellIndex;
566
567 // Perform exclusive prefix sum to find local offset for vertices and
568 // cells
569 MPI_Exscan(
570 &realVertexNumber, &vertIndex, 1, mpiIdType_, MPI_SUM, ttk::MPIcomm_);
571 MPI_Exscan(
572 &realCellNumber, &cellIndex, 1, mpiIdType_, MPI_SUM, ttk::MPIcomm_);
573
574 // Rank 0 received garbage values, it is replaced by the correct offset
575 // (always 0)
576 if(ttk::MPIrank_ == 0) {
577 vertIndex = 0;
578 cellIndex = 0;
579 }
580
581 // Generate global ids for vertices
582 if(vertexRankArray_ != nullptr) {
583 for(ttk::SimplexId i = 0; i < vertexNumber_; i++) {
584 if(vertexRankArray_[i] == ttk::MPIrank_) {
585 vertexIdentifiers_[i] = vertIndex;
586 (*vertGtoL_)[vertIndex] = i;
587 vertIndex++;
588 }
589 if(outdatedGlobalPointIds_ != nullptr) {
590 vertOutdatedGtoL_[outdatedGlobalPointIds_[i]] = i;
591 }
592 }
593 } else {
594 for(ttk::SimplexId i = 0; i < vertexNumber_; i++) {
595 if(vertGhost_[i] == 0) {
596 vertexIdentifiers_[i] = vertIndex;
597 (*vertGtoL_)[vertIndex] = i;
598 vertIndex++;
599 }
600 if(outdatedGlobalPointIds_ != nullptr) {
601 vertOutdatedGtoL_[outdatedGlobalPointIds_[i]] = i;
602 }
603 }
604 }
605
606 // Generate global ids for cells
607 if(cellRankArray_ != nullptr) {
608 for(ttk::SimplexId i = 0; i < cellNumber_; i++) {
609 if(cellRankArray_[i] == ttk::MPIrank_) {
610 cellIdentifiers_[i] = cellIndex;
611 cellIndex++;
612 }
613 if(outdatedGlobalCellIds_ != nullptr) {
614 cellOutdatedGtoL_[outdatedGlobalCellIds_[i]] = i;
615 }
616 }
617 } else {
618 for(ttk::SimplexId i = 0; i < cellNumber_; i++) {
619 if(cellGhost_[i] == 0) {
620 cellIdentifiers_[i] = cellIndex;
621 cellIndex++;
622 }
623 if(outdatedGlobalCellIds_ != nullptr) {
624 cellOutdatedGtoL_[outdatedGlobalCellIds_[i]] = i;
625 }
626 }
627 }
628 }
629
636 int executePolyData() {
637 vertGtoL_->clear();
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;
646 // In case RankArray is defined for vertices, a vector needs to be resized
647 // In case outdated global point ids are defined, then it is
648 // vertGhostGlobalIdsPerRank that need to be resized. This vector will
649 // store the outdated global ids of ghost points and their local id.
650 // Otherwise, vertGhostCoordinatesPerRank needs to be resized. This vector
651 // will store the coordinates of a ghost point and its local id.
652 if(vertexRankArray_ != nullptr) {
653 if(outdatedGlobalPointIds_ == nullptr) {
654 vertGhostCoordinatesPerRank.resize(neighborNumber_);
655 } else {
656 vertGhostGlobalIdsPerRank.resize(neighborNumber_);
657 }
658 }
659
660 // Similar as above, but with cells
661 if(cellRankArray_ != nullptr) {
662 if(outdatedGlobalCellIds_ == nullptr) {
663 cellGhostGlobalVertexIdsPerRank.resize(neighborNumber_);
664 } else {
665 cellGhostGlobalIdsPerRank.resize(neighborNumber_);
666 }
667 }
668
669 this->generateGlobalIds(vertGhostCoordinatesPerRank, vertGhostCoordinates,
670 vertGhostGlobalIdsPerRank, vertGhostGlobalIds);
671
672 // Start exchange of data to identify the global ids of ghost simplices
673 // records whether the process has sent its ghost simplices
674 hasSentData_ = 0;
675 ttk::SimplexId recvMessageSize = 0;
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_);
681 // For each neighbor, a process will receive the ghost points of all its
682 // neighbors or, if it is its turn, will receive the ghost points of all
683 // its neighbors
684 for(int i = 0; i < neighborNumber_ + 1; i++) {
685 if((i == neighborNumber_ && !hasSentData_)
686 || (!hasSentData_ && ttk::MPIrank_ < neighbors_->at(i))) {
687 // it is the turn of the current process to send its ghosts
688 if(outdatedGlobalPointIds_ == nullptr) {
689 if(vertexRankArray_ == nullptr) {
690 sendToAllNeighbors<Point>(vertGhostCoordinates, mpiPointType_);
691 } else {
692 sendToAllNeighborsUsingRankArray<Point>(
693 vertGhostCoordinatesPerRank, mpiPointType_);
694 }
695 } else {
696 if(vertexRankArray_ == nullptr) {
697 sendToAllNeighbors<ttk::SimplexId>(
698 vertGhostGlobalIds, mpiIdType_);
699 } else {
700 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
701 vertGhostGlobalIdsPerRank, mpiIdType_);
702 }
703 }
704 // The current process receives the responses of all the processes
705 // and associates its ghosts with the right global identifier
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++) {
711 vertexIdentifiers_[receivedResponse[n].id]
712 = receivedResponse[n].globalId;
713 (*vertGtoL_)[receivedResponse[n].globalId]
714 = receivedResponse[n].id;
715 }
716 } else {
717 for(int n = 0; n < recvMessageSize; n++) {
718 vertexIdentifiers_[vertOutdatedGtoL_[receivedResponse[n].id]]
719 = receivedResponse[n].globalId;
720 (*vertGtoL_)[receivedResponse[n].globalId]
721 = receivedResponse[n].id;
722 }
723 }
724 }
725 hasSentData_ = 1;
726 } else {
727 // It is not the turn of the current process to send its data.
728 if(outdatedGlobalPointIds_ == nullptr) {
729 recvVector<Point>(receivedPoints, recvMessageSize, mpiPointType_,
730 neighbors_->at(i - hasSentData_));
731 // Point coordinates are matched to a local point using a kd-tree
732 // and its global id is added to the vector send_buf
733 locatePoints(
734 locatedSimplices, receivedPoints, recvMessageSize, send_buf);
735 } else {
736 recvVector<ttk::SimplexId>(receivedIds, recvMessageSize, mpiIdType_,
737 neighbors_->at(i - hasSentData_));
738 // Outdated global ids are matched to a local point
739 // and its global id is added to the vector send_buf
740 identifyPoints(
741 locatedSimplices, receivedIds, recvMessageSize, send_buf);
742 }
743 // The points founds are sent back to the neighbor with their global
744 // ids
745 sendVector<Response>(
746 send_buf, mpiResponseType_, neighbors_->at(i - hasSentData_));
747 }
748 }
749 // Start of computation of ghost information for cells
750 int id{-1};
751 // If outdated global ids exist, for each ghost cell is added its local id
752 // and its outdated global id
753 if(cellRankArray_ != nullptr) {
754 for(ttk::SimplexId i = 0; i < cellNumber_; i++) {
755 if(cellRankArray_[i] != ttk::MPIrank_) {
756 if(outdatedGlobalCellIds_ == nullptr) {
757 cellGhostGlobalVertexIdsPerRank[neighborToId_[cellRankArray_[i]]]
758 .push_back(i);
759 for(int k = 0; k < dimension_ + 1; k++) {
760 id = connectivity_[i * (dimension_ + 1) + k];
761 cellGhostGlobalVertexIdsPerRank
762 [neighborToId_[cellRankArray_[i]]]
763 .push_back(vertexIdentifiers_[id]);
764 }
765 } else {
766 cellGhostGlobalIdsPerRank[neighborToId_[cellRankArray_[i]]]
767 .push_back(
768 static_cast<ttk::SimplexId>(outdatedGlobalCellIds_[i]));
769 }
770 }
771 }
772 } else {
773 // If no outdated global ids exist, for each ghost cell is added its
774 // local id and the global id of all of its vertices
775 for(ttk::SimplexId i = 0; i < cellNumber_; 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];
781 cellGhostGlobalVertexIds.push_back(vertexIdentifiers_[id]);
782 }
783 } else {
784 cellGhostGlobalIds.push_back(
785 static_cast<ttk::SimplexId>(outdatedGlobalCellIds_[i]));
786 }
787 }
788 }
789 }
790 hasSentData_ = 0;
791
792 // Exchange cells similarly to what is done for vertices
793 for(int i = 0; i < neighborNumber_ + 1; i++) {
794 if((i == neighborNumber_ && !hasSentData_)
795 || (!hasSentData_ && ttk::MPIrank_ < neighbors_->at(i))) {
796 // For each neighbor, a process will receive the ghost cells of all
797 // its neighbors or, if it is its turn, will receive the ghost cells
798 // of all its neighbors
799 if(outdatedGlobalCellIds_ == nullptr) {
800 if(cellRankArray_ == nullptr) {
801 sendToAllNeighbors<ttk::SimplexId>(
802 cellGhostGlobalVertexIds, mpiIdType_);
803 } else {
804 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
805 cellGhostGlobalVertexIdsPerRank, mpiIdType_);
806 }
807 } else {
808 if(cellRankArray_ == nullptr) {
809 sendToAllNeighbors<ttk::SimplexId>(
810 cellGhostGlobalIds, mpiIdType_);
811 } else {
812 sendToAllNeighborsUsingRankArray<ttk::SimplexId>(
813 cellGhostGlobalIdsPerRank, mpiIdType_);
814 }
815 }
816 // The current process receives the responses of all the processes
817 // and associates its ghosts with the right global identifier
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++) {
823 cellIdentifiers_[receivedResponse[n].id]
824 = receivedResponse[n].globalId;
825 }
826 } else {
827 for(int n = 0; n < recvMessageSize; n++) {
828 cellIdentifiers_[cellOutdatedGtoL_[receivedResponse[n].id]]
829 = receivedResponse[n].globalId;
830 }
831 }
832 }
833 hasSentData_ = 1;
834 } else {
835 // It is not the turn of the current process to send its data.
836 recvVector<ttk::SimplexId>(receivedIds, recvMessageSize, mpiIdType_,
837 neighbors_->at(i - hasSentData_));
838 if(outdatedGlobalCellIds_ == nullptr) {
839 // Point global ids are matched to a local cell and the global
840 // id of the cell is added to the vector send_buf
841 locateCells(
842 locatedSimplices, receivedIds, recvMessageSize, send_buf);
843 } else {
844 // Outdated global ids are matched to a local cell
845 // and its global id is added to the vector send_buf
846 identifyCells(
847 locatedSimplices, receivedIds, recvMessageSize, send_buf);
848 }
849 // The cells founds are sent back to the neighbor with their global
850 // ids
851 sendVector<Response>(
852 send_buf, mpiResponseType_, neighbors_->at(i - hasSentData_));
853 }
854 }
855
856 return 1; // return success
857 }
858
864 int executeImageData() {
865
866 // print horizontal separator
867 this->printMsg(ttk::debug::Separator::L1); // L1 is the '=' separator
868
869 // Reorganize bounds to only execute Allreduce twice
870 double tempBounds[6] = {
871 bounds_[0], bounds_[2], bounds_[4], bounds_[1], bounds_[3], bounds_[5]};
872 double tempGlobalBounds[6];
873 // Compute and send to all processes the lower bounds of the data set
874 MPI_Allreduce(
875 tempBounds, tempGlobalBounds, 3, MPI_DOUBLE, MPI_MIN, ttk::MPIcomm_);
876
877 // Compute and send to all processes the higher bounds of the data set
878 MPI_Allreduce(tempBounds + 3, tempGlobalBounds + 3, 3, MPI_DOUBLE,
879 MPI_MAX, ttk::MPIcomm_);
880 // Global bounds
881 double globalBounds[6]
882 = {tempGlobalBounds[0], tempGlobalBounds[3], tempGlobalBounds[1],
883 tempGlobalBounds[4], tempGlobalBounds[2], tempGlobalBounds[5]};
884 // Compute global width and height of the data set
885 int width
886 = static_cast<int>((globalBounds[1] - globalBounds[0]) / spacing_[0])
887 + 1;
888 int height
889 = static_cast<int>((globalBounds[3] - globalBounds[2]) / spacing_[1])
890 + 1;
891
892 // Compute offset of the current process for each direction
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]));
899 // Generate global ids for vertices
900#ifdef TTK_ENABLE_OPENMP
901#pragma omp parallel for num_threads(threadNumber_)
902#endif
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++) {
906 vertexIdentifiers_[k * dims_[0] * dims_[1] + j * dims_[0] + i]
907 = i + offsetWidth + (j + offsetHeight) * width
908 + (k + offsetLength) * width * height;
909 }
910 }
911 }
912
913 // Generate global ids for cells
914 dims_[0] -= 1;
915 dims_[1] -= 1;
916 dims_[2] -= 1;
917 width -= 1;
918 height -= 1;
919#ifdef TTK_ENABLE_OPENMP
920#pragma omp parallel for num_threads(threadNumber_)
921#endif
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++) {
925 cellIdentifiers_[k * dims_[0] * dims_[1] + j * dims_[0] + i]
926 = i + offsetWidth + (j + offsetHeight) * width
927 + (k + offsetLength) * width * height;
928 }
929 }
930 }
931
932 return 1; // return success
933 }
934
935#endif
936
943 // print horizontal separator
944 this->printMsg(ttk::debug::Separator::L1); // L1 is the '=' separator
945
946#ifdef TTK_ENABLE_OPENMP
947#pragma omp parallel for num_threads(threadNumber_)
948#endif
949 for(SimplexId i = 0; i < vertexNumber_; i++) {
950 // avoid any processing if the abort signal is sent
951 vertexIdentifiers_[i] = i;
952 }
953
954#ifdef TTK_ENABLE_OPENMP
955#pragma omp parallel for num_threads(threadNumber_)
956#endif
957 for(SimplexId i = 0; i < cellNumber_; i++) {
958 // avoid any processing if the abort signal is sent
959 cellIdentifiers_[i] = i;
960 }
961
962 return 1; // return success
963 }
964
965 }; // Identifiers class
966
967} // namespace ttk
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition BaseClass.h:47
boost::tuple< double, double > Point
Definition TopoMap.cpp:56
Minimalist debugging class.
Definition Debug.h:88
void setCellIdentifiers(ttk::LongSimplexId *cellIdentifiers)
Definition Identifiers.h:97
ttk::SimplexId cellNumber_
Definition Identifiers.h:54
void setVertexNumber(const SimplexId &vertexNumber)
Definition Identifiers.h:85
void setCellNumber(const SimplexId &cellNumber)
Definition Identifiers.h:89
ttk::LongSimplexId * vertexIdentifiers_
Definition Identifiers.h:55
int executeSequential()
Generates global ids for all data set type in sequential.
void setVertexIdentifiers(ttk::LongSimplexId *vertexIdentifiers)
Definition Identifiers.h:93
~Identifiers() override=default
ttk::SimplexId vertexNumber_
Definition Identifiers.h:53
ttk::LongSimplexId * cellIdentifiers_
Definition Identifiers.h:56
TTK KD-Tree.
Definition KDTree.h:21
KDTreeMap build(dataType *data, const int &ptNumber, const int &dimension, const std::vector< std::vector< dataType > > &weights={}, const int &weightNumber=1, const int &nodeNumber=-1, const bool &preciseBoundingBox=false)
Definition KDTree.h:154
void getKClosest(const unsigned int k, const Container &coordinates, KDTreeMap &neighbours, std::vector< dataType > &costs, const int weight_index=0)
Definition KDTree.h:433
The Topology ToolKit.
COMMON_EXPORTS int MPIrank_
Definition BaseClass.cpp:9
long long int LongSimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:15
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)