25 doublePrecision_ =
false;
34 const auto printArrayFootprint
36 if(!array.
empty() && !name.empty()) {
37 this->
printMsg(name + std::string{
": "}
38 + std::to_string(array.
footprint()) +
" bytes");
43 size += printArrayFootprint(vertexNeighborData_,
"vertexNeighborData_");
44 size += printArrayFootprint(cellNeighborData_,
"cellNeighborData_");
45 size += printArrayFootprint(vertexEdgeData_,
"vertexEdgeData_");
46 size += printArrayFootprint(vertexTriangleData_,
"vertexTriangleData_");
47 size += printArrayFootprint(edgeTriangleData_,
"edgeTriangleData_");
48 size += printArrayFootprint(vertexStarData_,
"vertexStarData_");
49 size += printArrayFootprint(edgeStarData_,
"edgeStarData_");
50 size += printArrayFootprint(triangleStarData_,
"triangleStarData_");
51 size += printArrayFootprint(vertexLinkData_,
"vertexLinkData_");
52 size += printArrayFootprint(edgeLinkData_,
"edgeLinkData_");
53 size += printArrayFootprint(triangleLinkData_,
"triangleLinkData_");
60 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
62 if(!(ttk::isRunningWithMPI()))
64 this->
printErr(
"Empty dataset, precondition skipped");
80 if(edgeStarData_[i].size() == 1) {
88 for(
size_t i = 0; i < triangleStarData_.
size(); i++) {
89 if(triangleStarData_[i].size() == 1) {
90 for(
int j = 0; j < 3; j++) {
97 printErr(
"Unsupported dimension for edge boundary precondition");
103 if(ttk::isRunningWithMPI()) {
105 std::vector<unsigned char> charBoundary(edgeNumber,
false);
106 for(
int i = 0; i < edgeNumber; ++i) {
109 ttk::exchangeGhostDataWithoutTriangulation(
111 [
this](
const SimplexId a) { return this->edgeRankArray_[a]; },
112 [
this](
const SimplexId a) { return this->edgeLidToGid_[a]; },
113 [
this](
const SimplexId a) { return this->edgeGidToLid_[a]; }, edgeNumber,
114 ttk::MPIcomm_, this->getNeighborRanks());
115 for(
int i = 0; i < edgeNumber; ++i) {
122 this->
printMsg(
"Extracted boundary edges", 1.0, tm.getElapsedTime(), 1);
129int ExplicitTriangulation::preconditionVertexRankArray() {
130 if(vertexRankArray_.size() == 0) {
131 this->vertexRankArray_.resize(this->vertexNumber_, 0);
132 if(ttk::isRunningWithMPI()) {
133 ttk::produceRankArray(this->vertexRankArray_, this->vertGid_,
134 this->vertexGhost_, this->vertexNumber_,
135 this->boundingBox_.data(), this->neighborRanks_,
136 this->neighborsToId_);
137 ttk::preconditionNeighborsUsingRankArray<ttk::SimplexId>(
138 this->neighborRanks_, this->neighborsToId_,
139 [
this](
const ttk::SimplexId a) {
return this->getVertexRank(a); },
140 this->vertexNumber_, ttk::MPIcomm_);
146int ExplicitTriangulation::preconditionCellRankArray() {
147 if(cellRankArray_.size() == 0) {
148 this->cellRankArray_.resize(this->cellNumber_, 0);
149 if(ttk::isRunningWithMPI()) {
150 ttk::produceRankArray(this->cellRankArray_, this->cellGid_,
151 this->cellGhost_, this->cellNumber_,
152 this->boundingBox_.data(), this->neighborRanks_,
153 this->neighborsToId_);
159int ExplicitTriangulation::preconditionEdgeRankArray() {
161 edgeRankArray_.resize(edgeNumber, 0);
162 if(ttk::isRunningWithMPI()) {
172 if(this->cellRankArray_[sid] < this->cellRankArray_[min_id]) {
176 edgeRankArray_[id] = cellRankArray_[min_id];
182int ExplicitTriangulation::preconditionTriangleRankArray() {
184 triangleRankArray_.resize(triangleNumber, 0);
185 if(ttk::isRunningWithMPI()) {
196 if(this->cellRankArray_[sid] < this->cellRankArray_[min_id]) {
200 triangleRankArray_[id] = cellRankArray_[min_id];
210 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
212 if(!(ttk::isRunningWithMPI()))
214 this->
printErr(
"Empty dataset, precondition skipped");
234 for(
size_t i = 0; i < triangleStarData_.
size(); i++) {
235 if(triangleStarData_[i].size() == 1) {
241 printErr(
"Unsupported dimension for triangle boundary precondition");
247 if(ttk::isRunningWithMPI()) {
249 std::vector<unsigned char> charBoundary(triangleNumber,
false);
250 for(
int i = 0; i < triangleNumber; ++i) {
253 ttk::exchangeGhostDataWithoutTriangulation(
255 [
this](
const SimplexId a) { return this->triangleRankArray_[a]; },
256 [
this](
const SimplexId a) { return this->triangleLidToGid_[a]; },
257 [
this](
const SimplexId a) { return this->triangleGidToLid_[a]; },
258 triangleNumber, ttk::MPIcomm_, this->getNeighborRanks());
259 for(
int i = 0; i < triangleNumber; ++i) {
266 this->
printMsg(
"Extracted boundary triangles", 1.0, tm.getElapsedTime(), 1);
273 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
275 if(!(ttk::isRunningWithMPI()))
277 this->
printErr(
"Empty dataset, precondition skipped");
294 for(
size_t i = 0; i < vertexStarData_.
size(); i++) {
295 if(vertexStarData_[i].size() == 1) {
304 if(edgeStarData_[i].size() == 1) {
313 for(
size_t i = 0; i < triangleStarData_.
size(); i++) {
314 if(triangleStarData_[i].size() == 1) {
322 printErr(
"Unsupported dimension for vertex boundary precondition");
328 if(ttk::isRunningWithMPI()) {
329 this->preconditionDistributedVertices();
330 std::vector<unsigned char> charBoundary(vertexNumber_,
false);
331 for(
int i = 0; i < vertexNumber_; ++i) {
334 ttk::exchangeGhostVertices<unsigned char, ExplicitTriangulation>(
335 charBoundary.data(),
this, ttk::MPIcomm_);
337 for(
int i = 0; i < vertexNumber_; ++i) {
346 this->
printMsg(
"Extracted boundary vertices", 1.0, tm.getElapsedTime(), 1);
353 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
355 if(!(ttk::isRunningWithMPI()))
357 this->
printErr(
"Empty dataset, precondition skipped");
371 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
373 if(!(ttk::isRunningWithMPI()))
375 this->
printErr(
"Empty dataset, precondition skipped");
379 if(cellNeighborData_.
empty()) {
384 vertexNumber_, *cellArray_, cellNeighborData_, &triangleStarData_);
390 *cellArray_, cellNeighborData_, edgeStarData_);
399 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
401 if(!(ttk::isRunningWithMPI()))
403 this->
printErr(
"Empty dataset, precondition skipped");
414 if(!triangleStarData_.
empty()) {
421 nullptr, &triangleStarData_,
426 if(!triangleStarData_.
empty()) {
445 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
447 if(!(ttk::isRunningWithMPI()))
449 this->
printErr(
"Empty dataset, precondition skipped");
459 std::vector<std::array<SimplexId, 1>> tmp{};
461 vertexNumber_, *cellArray_,
edgeList_, edgeStarData_, tmp);
476 return this->preconditionDistributedEdges();
486 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
488 if(!(ttk::isRunningWithMPI()))
490 this->
printErr(
"Empty dataset, precondition skipped");
494 if(edgeLinkData_.
empty()) {
503 edgeList_, edgeStarData_, *cellArray_, edgeLinkData_);
515 printErr(
"Unsupported dimension for edge link precondition");
525 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
527 if(!(ttk::isRunningWithMPI()))
529 this->
printErr(
"Empty dataset, precondition skipped");
533 if(edgeStarData_.
empty()) {
541 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
543 if(!(ttk::isRunningWithMPI()))
545 this->
printErr(
"Empty dataset, precondition skipped");
549 if(edgeTriangleData_.
empty()) {
565 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
567 if(!(ttk::isRunningWithMPI()))
569 this->
printErr(
"Empty dataset, precondition skipped");
582 this->preconditionDistributedTriangles();
591 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
593 if(!(ttk::isRunningWithMPI()))
595 this->
printErr(
"Empty dataset, precondition skipped");
621 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
623 if(!(ttk::isRunningWithMPI()))
625 this->
printErr(
"Empty dataset, precondition skipped");
629 if(triangleLinkData_.
empty()) {
636 triangleList_, triangleStarData_, *cellArray_, triangleLinkData_);
644 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
646 if(!(ttk::isRunningWithMPI()))
648 this->
printErr(
"Empty dataset, precondition skipped");
652 if(triangleStarData_.
empty()) {
657 vertexNumber_, *cellArray_, &
triangleList_, &triangleStarData_);
665 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
667 if(!(ttk::isRunningWithMPI()))
669 this->
printErr(
"Empty dataset, precondition skipped");
682 vertexNumber_,
edgeList_, vertexEdgeData_);
689 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
691 if(!(ttk::isRunningWithMPI()))
693 this->
printErr(
"Empty dataset, precondition skipped");
717 printErr(
"Unsupported dimension for vertex link precondition");
726 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
728 if(!(ttk::isRunningWithMPI()))
730 this->
printErr(
"Empty dataset, precondition skipped");
739 vertexNumber_, vertexNeighborData_,
edgeList_);
746 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
748 if(!(ttk::isRunningWithMPI()))
750 this->
printErr(
"Empty dataset, precondition skipped");
759 vertexNumber_, *cellArray_, vertexStarData_);
766 if(this->cellArray_ ==
nullptr || this->vertexNumber_ == 0) {
768 if(!(ttk::isRunningWithMPI()))
770 this->
printErr(
"Empty dataset, precondition skipped");
793 if(this->getDimensionality() == 3) {
794 this->preconditionTriangleStarsInternal();
795 simplexStar = &this->triangleStarData_;
796 }
else if(this->getDimensionality() == 2) {
797 this->preconditionEdgeStarsInternal();
798 simplexStar = &this->edgeStarData_;
799 }
else if(this->getDimensionality() == 1) {
800 this->preconditionVertexStarsInternal();
801 simplexStar = &this->vertexStarData_;
804 if(simplexStar ==
nullptr) {
808 for(
const auto star : *simplexStar) {
809 if(star.size() < 1 || star.size() > 2) {
810 this->isManifold_ =
false;
811 this->printWrn(
"Non manifold data-set detected");
821int ExplicitTriangulation::preconditionDistributedCells() {
822 if(this->hasPreconditionedDistributedCells_) {
825 if(!ttk::hasInitializedMPI()) {
828 if(this->cellGid_ ==
nullptr) {
829 this->
printErr(
"Missing global cell identifiers array!");
835 this->preconditionCellRankArray();
841 this->cellGidToLid_.reserve(nLocCells);
843 this->cellGidToLid_[this->cellGid_[lcid]] = lcid;
846 this->preconditionExchangeGhostCells();
848 this->preconditionDistributedCellRanges();
850 this->hasPreconditionedDistributedCells_ =
true;
854 + std::to_string(this->gatheredCellRanges_.back().end + 1)
856 1.0, tm.getElapsedTime(), this->threadNumber_);
862int ttk::ExplicitTriangulation::preconditionExchangeGhostCells() {
864 if(this->hasPreconditionedExchangeGhostCells_) {
867 if(!ttk::hasInitializedMPI()) {
870 if(this->cellGid_ ==
nullptr) {
871 this->printErr(
"Missing global cell identifiers array!");
878 const auto nLocCells{this->getNumberOfCells()};
883 this->ghostCellsPerOwner_[this->cellRankArray_[lcid]].emplace_back(
884 this->cellGid_[lcid]);
895 for(
const auto neigh : this->neighborRanks_) {
897 const auto nCells{this->ghostCellsPerOwner_[neigh].size()};
898 MPI_Sendrecv(&nCells, 1, ttk::getMPIType(nCells), neigh,
ttk::MPIrank_,
899 &nOwnedGhostCellsPerRank[neigh], 1, ttk::getMPIType(nCells),
900 neigh, neigh, ttk::MPIcomm_, MPI_STATUS_IGNORE);
901 this->remoteGhostCells_[neigh].resize(nOwnedGhostCellsPerRank[neigh]);
904 MPI_Sendrecv(this->ghostCellsPerOwner_[neigh].data(),
905 this->ghostCellsPerOwner_[neigh].size(), MIT, neigh,
907 this->remoteGhostCells_[neigh].size(), MIT, neigh, neigh,
908 ttk::MPIcomm_, MPI_STATUS_IGNORE);
911 this->hasPreconditionedExchangeGhostCells_ =
true;
915int ttk::ExplicitTriangulation::preconditionDistributedCellRanges() {
919 std::vector<SimplexId> localCellIds{};
920 localCellIds.reserve(this->getNumberOfCells());
921 for(
SimplexId i = 0; i < this->getNumberOfCells(); ++i) {
923 localCellIds.emplace_back(i);
927 TTK_PSORT(this->threadNumber_, localCellIds.begin(), localCellIds.end(),
929 return this->cellGid_[a] < this->cellGid_[b];
935 while(begRange < localCellIds.size()) {
936 size_t endRange{begRange + 1};
938 if(begRange < localCellIds.size() - 1) {
939 for(
size_t j = begRange + 1; j < localCellIds.size(); ++j) {
940 if(this->cellGid_[localCellIds[j]]
941 > this->cellGid_[localCellIds[j - 1]] + 1) {
946 if(endRange == begRange + 1
947 && this->cellGid_[localCellIds[endRange]]
948 == this->cellGid_[localCellIds[endRange - 1]] + 1) {
949 endRange = localCellIds.size();
953 const size_t gbeg = this->cellGid_[localCellIds[begRange]];
954 const size_t gend = this->cellGid_[localCellIds[endRange - 1]];
955 const auto nRanges{this->localCellRanges_.size()};
958 this->localCellRanges_.emplace_back(
959 CellRange{nRanges, gbeg, gend,
static_cast<size_t>(
ttk::MPIrank_)});
970 const int rangeSize = this->localCellRanges_.size();
971 MPI_Gather(&rangeSize, 1, ttk::getMPIType(rangeSize),
972 this->nRangesPerRank_.data(), 1, ttk::getMPIType(rangeSize), 0,
975 std::vector<int> displacements{};
978 const auto nRanges{std::accumulate(
979 this->nRangesPerRank_.begin(), this->nRangesPerRank_.end(), 0)};
980 this->gatheredCellRanges_.resize(nRanges);
981 displacements.resize(this->nRangesPerRank_.size());
983 for(
size_t i = 0; i < this->nRangesPerRank_.size() - 1; ++i) {
984 displacements[i + 1] = displacements[i] + this->nRangesPerRank_[i];
988 auto cellRangeDT{CellRange::getMPIType()};
989 MPI_Type_commit(&cellRangeDT);
991 MPI_Gatherv(this->localCellRanges_.data(), this->localCellRanges_.size(),
992 cellRangeDT, this->gatheredCellRanges_.data(),
993 this->nRangesPerRank_.data(), displacements.data(), cellRangeDT,
996 MPI_Type_free(&cellRangeDT);
1002 this->threadNumber_, this->gatheredCellRanges_.begin(),
1003 this->gatheredCellRanges_.end(),
1004 [](
const CellRange &a,
const CellRange &b) { return a.begin < b.begin; });
1010size_t ttk::ExplicitTriangulation::computeCellRangeOffsets(
1011 std::vector<size_t> &nSimplicesPerRange)
const {
1015 std::vector<std::vector<size_t>> nSimplicesPerRangePerRank{};
1018 nSimplicesPerRangePerRank.resize(this->nRangesPerRank_.size());
1020 nSimplicesPerRangePerRank[i].resize(this->nRangesPerRank_[i]);
1027 MPI_Recv(nSimplicesPerRangePerRank[i].data(),
1028 nSimplicesPerRangePerRank[i].size(), ttk::getMPIType(
size_t{}),
1029 i, MPI_ANY_TAG, ttk::MPIcomm_, MPI_STATUS_IGNORE);
1031 std::swap(nSimplicesPerRangePerRank[0], nSimplicesPerRange);
1033 MPI_Send(nSimplicesPerRange.data(), nSimplicesPerRange.size(),
1034 ttk::getMPIType(
size_t{}), 0, 0, ttk::MPIcomm_);
1039 size_t nSimplices{};
1042 for(
const auto &range : this->gatheredCellRanges_) {
1043 auto &pSum{nSimplicesPerRangePerRank[range.rank][range.id]};
1044 std::swap(pSum, nSimplices);
1053 MPI_Send(nSimplicesPerRangePerRank[i].data(),
1054 nSimplicesPerRangePerRank[i].size(), ttk::getMPIType(
size_t{}),
1055 i, 0, ttk::MPIcomm_);
1057 std::swap(nSimplicesPerRange, nSimplicesPerRangePerRank[0]);
1059 MPI_Recv(nSimplicesPerRange.data(), nSimplicesPerRange.size(),
1060 ttk::getMPIType(
size_t{}), MPI_ANY_TAG, 0, ttk::MPIcomm_,
1067template <
typename Func0,
typename Func1,
typename Func2>
1068int ttk::ExplicitTriangulation::exchangeDistributedInternal(
1069 const Func0 &getGlobalSimplexId,
1070 const Func1 &storeGlobalSimplexId,
1071 const Func2 &iterCond,
1072 const int nSimplicesPerCell) {
1075 std::vector<std::vector<SimplexId>> globalIdPerOwnedGhostCell(
ttk::MPIsize_);
1077 std::vector<std::vector<SimplexId>> globalIdPerLocalGhostCell(
ttk::MPIsize_);
1092 for(
const auto neigh : this->neighborRanks_) {
1094 globalIdPerOwnedGhostCell[neigh].resize(
1095 nSimplicesPerCell * this->remoteGhostCells_[neigh].size());
1096 for(
size_t i = 0; i < this->remoteGhostCells_[neigh].size(); ++i) {
1097 const auto lcid{this->cellGidToLid_[this->remoteGhostCells_[neigh][i]]};
1098 for(
int j = 0; j < nSimplicesPerCell; ++j) {
1099 globalIdPerOwnedGhostCell[neigh][nSimplicesPerCell * i + j]
1100 = getGlobalSimplexId(lcid, j);
1104 globalIdPerLocalGhostCell[neigh].resize(
1105 nSimplicesPerCell * this->ghostCellsPerOwner_[neigh].size());
1108 MPI_Sendrecv(globalIdPerOwnedGhostCell[neigh].data(),
1109 globalIdPerOwnedGhostCell[neigh].size(), MIT, neigh,
1111 globalIdPerLocalGhostCell[neigh].size(), MIT, neigh, neigh,
1112 ttk::MPIcomm_, MPI_STATUS_IGNORE);
1116 for(
const auto neigh : this->neighborRanks_) {
1117 for(
size_t i = 0; i < this->ghostCellsPerOwner_[neigh].size(); ++i) {
1118 const auto gcid{this->ghostCellsPerOwner_[neigh][i]};
1119 const auto lcid{this->cellGidToLid_[gcid]};
1120 for(
int j = 0; j < nSimplicesPerCell; ++j) {
1122 globalIdPerLocalGhostCell[neigh][nSimplicesPerCell * i + j]};
1123 storeGlobalSimplexId(lcid, geid, j);
1140 MPI_Bcast(&doNextIter, 1, ttk::getMPIType(doNextIter), i, ttk::MPIcomm_);
1141 doIter |= (doNextIter == 1);
1145 this->
printMsg(
"Re-sending global ids to neighbors...");
1152int ExplicitTriangulation::preconditionDistributedEdges() {
1153 if(this->hasPreconditionedDistributedEdges_) {
1156 if(!ttk::hasInitializedMPI()) {
1159 if(this->cellGid_ ==
nullptr) {
1160 this->
printErr(
"Missing global cell identifiers array!");
1174 this->preconditionDistributedCells();
1183 std::vector<size_t> nEdgesPerRange(this->localCellRanges_.size());
1185 const auto edgeAlreadyProcessed = [
this](
const SimplexId leid,
1191 if(sid == -1 || sid == lcid) {
1196 if(this->cellRankArray_[sid] < this->cellRankArray_[lcid]) {
1204 const auto countCellEdges
1205 = [
this, &edgeAlreadyProcessed](
const SimplexId lcid,
1206 std::vector<SimplexId> &edgeGid,
1207 std::vector<SimplexId> &edgeRangeId,
1208 const size_t rangeId,
size_t &edgeCount) {
1210 if(this->maxCellDim_ == 3) {
1212 }
else if(this->maxCellDim_ == 2) {
1217 if(this->maxCellDim_ == 3) {
1219 }
else if(this->maxCellDim_ == 2) {
1222 const auto alreadyProcessed = edgeAlreadyProcessed(leid, lcid);
1223 if(!alreadyProcessed) {
1224 edgeGid[leid] = edgeCount;
1225 edgeRangeId[leid] = rangeId;
1231#ifdef TTK_ENABLE_OPENMP
1232#pragma omp parallel for num_threads(this->threadNumber_)
1234 for(
size_t i = 0; i < this->localCellRanges_.size(); ++i) {
1235 auto &range{this->localCellRanges_[i]};
1237 for(
size_t j = range.begin; j <= range.end; ++j) {
1239 const auto lcid{this->cellGidToLid_[j]};
1240 countCellEdges(lcid, this->edgeLidToGid_, edgeLidToRangeId, range.id,
1246 const auto nEdges = this->computeCellRangeOffsets(nEdgesPerRange);
1251 if(this->edgeLidToGid_[leid] == -1) {
1255 const auto geid{this->edgeLidToGid_[leid]
1256 + nEdgesPerRange[edgeLidToRangeId[leid]]};
1257 this->edgeLidToGid_[leid] = geid;
1258 this->edgeGidToLid_[geid] = leid;
1264 this->exchangeDistributedInternal(
1265 [
this](
const SimplexId lcid,
const int j) {
1268 return this->edgeLidToGid_[leid];
1273 if(this->edgeLidToGid_[leid] == -1 && geid != -1) {
1274 this->edgeLidToGid_[leid] = geid;
1275 this->edgeGidToLid_[geid] = leid;
1280 this->edgeLidToGid_.begin(), this->edgeLidToGid_.end(), -1)
1285 this->preconditionEdgeRankArray();
1288 this->
printMsg(
"Domain contains " + std::to_string(nEdges) +
" edges", 1.0,
1289 tm.getElapsedTime(), 1);
1292 this->hasPreconditionedDistributedEdges_ =
true;
1297int ExplicitTriangulation::preconditionDistributedTriangles() {
1298 if(this->hasPreconditionedDistributedTriangles_) {
1301 if(!ttk::hasInitializedMPI()) {
1304 if(this->cellGid_ ==
nullptr) {
1305 this->
printErr(
"Missing global cell identifiers array!");
1315 this->preconditionDistributedCells();
1323 std::vector<SimplexId> triangleLidToRangeId(
1325 std::vector<size_t> nTrianglesPerRange(this->localCellRanges_.size());
1327 const auto triangleAlreadyProcessed
1334 if(sid == -1 || sid == lcid) {
1339 if(this->cellRankArray_[sid] < this->cellRankArray_[lcid]) {
1347 const auto countCellTriangles
1348 = [
this, &triangleAlreadyProcessed](
1349 const SimplexId lcid, std::vector<SimplexId> &triangleGid,
1350 std::vector<SimplexId> &triangleRangeId,
const size_t rangeId,
1351 size_t &triangleCount) {
1353 for(
SimplexId k = 0; k < nTriangles; ++k) {
1356 const auto alreadyProcessed = triangleAlreadyProcessed(leid, lcid);
1357 if(!alreadyProcessed) {
1358 triangleGid[leid] = triangleCount;
1359 triangleRangeId[leid] = rangeId;
1365#ifdef TTK_ENABLE_OPENMP
1366#pragma omp parallel for num_threads(this->threadNumber_)
1368 for(
size_t i = 0; i < this->localCellRanges_.size(); ++i) {
1369 auto &range{this->localCellRanges_[i]};
1371 for(
size_t j = range.begin; j <= range.end; ++j) {
1373 const auto lcid{this->cellGidToLid_[j]};
1374 countCellTriangles(lcid, this->triangleLidToGid_, triangleLidToRangeId,
1375 range.id, nTrianglesPerRange[i]);
1380 const auto nTriangles = this->computeCellRangeOffsets(nTrianglesPerRange);
1385 if(this->triangleLidToGid_[leid] == -1) {
1389 const auto geid{this->triangleLidToGid_[leid]
1390 + nTrianglesPerRange[triangleLidToRangeId[leid]]};
1391 this->triangleLidToGid_[leid] = geid;
1392 this->triangleGidToLid_[geid] = leid;
1397 const auto nTrianglesPerCell{4};
1398 this->exchangeDistributedInternal(
1399 [
this](
const SimplexId lcid,
const int j) {
1402 return this->triangleLidToGid_[ltid];
1407 if(this->triangleLidToGid_[ltid] == -1 && gtid != -1) {
1408 this->triangleLidToGid_[ltid] = gtid;
1409 this->triangleGidToLid_[gtid] = ltid;
1413 return std::count(this->triangleLidToGid_.begin(),
1414 this->triangleLidToGid_.end(), -1)
1419 this->preconditionTriangleRankArray();
1423 "Domain contains " + std::to_string(nTriangles) +
" triangles", 1.0,
1424 tm.getElapsedTime(), 1);
1427 this->hasPreconditionedDistributedTriangles_ =
true;
1432int ExplicitTriangulation::preconditionDistributedVertices() {
1433 if(this->hasPreconditionedDistributedVertices_) {
1436 if(!hasInitializedMPI()) {
1439 if(this->vertGid_ ==
nullptr) {
1440 this->
printErr(
"Missing global vertex identifiers array!");
1444 this->hasPreconditionedDistributedVertices_ =
true;
1445 this->preconditionVertexRankArray();
1451 this->vertexGidToLid_.reserve(nLocVertices);
1453 this->vertexGidToLid_[this->vertGid_[lvid]] = lvid;
1456 this->preconditionExchangeGhostVertices();
1461int ttk::ExplicitTriangulation::preconditionExchangeGhostVertices() {
1463 if(this->hasPreconditionedExchangeGhostVertices_) {
1466 if(!ttk::hasInitializedMPI()) {
1469 if(this->vertGid_ ==
nullptr) {
1470 this->printErr(
"Missing global vertex identifiers array!");
1475 const auto nLocVertices{this->getNumberOfVertices()};
1482 this->ghostVerticesPerOwner_[this->vertexRankArray_[lvid]].emplace_back(
1483 this->vertGid_[lvid]);
1492 std::vector<size_t> nOwnedGhostVerticesPerRank(
ttk::MPIsize_);
1494 for(
const auto neigh : this->neighborRanks_) {
1496 const auto nVerts{this->ghostVerticesPerOwner_[neigh].size()};
1497 MPI_Sendrecv(&nVerts, 1, ttk::getMPIType(nVerts), neigh,
ttk::MPIrank_,
1498 &nOwnedGhostVerticesPerRank[neigh], 1, ttk::getMPIType(nVerts),
1499 neigh, neigh, ttk::MPIcomm_, MPI_STATUS_IGNORE);
1500 this->remoteGhostVertices_[neigh].resize(nOwnedGhostVerticesPerRank[neigh]);
1503 MPI_Sendrecv(this->ghostVerticesPerOwner_[neigh].data(),
1504 this->ghostVerticesPerOwner_[neigh].size(), MIT, neigh,
1506 this->remoteGhostVertices_[neigh].size(), MIT, neigh, neigh,
1507 ttk::MPIcomm_, MPI_STATUS_IGNORE);
1510 this->hasPreconditionedExchangeGhostVertices_ =
true;
1517template <
typename T>
1519 stream.write(
reinterpret_cast<const char *
>(&var),
sizeof(var));
1522template <
typename T>
1524 const T *
const buff,
1525 const size_t size) {
1526 stream.write(
reinterpret_cast<const char *
>(buff), size *
sizeof(T));
1530const char *ExplicitTriangulation::magicBytes_ =
"TTKTriangulationFileFormat";
1531const unsigned long ExplicitTriangulation::formatVersion_ = 1;
1536 stream.write(ttk::ExplicitTriangulation::magicBytes_,
1537 std::strlen(ttk::ExplicitTriangulation::magicBytes_));
1539 writeBin(stream, ttk::ExplicitTriangulation::formatVersion_);
1547 const auto edgesNumber = [
this, dim]() ->
SimplexId {
1550 }
else if(dim > 1) {
1555 const auto nEdges = edgesNumber();
1558 const auto trianglesNumber = [
this, dim]() ->
SimplexId {
1561 }
else if(dim == 3) {
1566 const auto nTriangles = trianglesNumber();
1577#define WRITE_FIXED(ARRAY) \
1578 if(ARRAY.empty()) { \
1579 writeBin(stream, char{0}); \
1581 writeBin(stream, char{1}); \
1582 writeBinArray(stream, ARRAY.data(), ARRAY.size()); \
1598#define WRITE_GUARD(ARRAY) \
1599 if(ARRAY.empty()) { \
1600 writeBin(stream, char{0}); \
1603 writeBin(stream, char{1}); \
1614 write_variable(this->vertexNeighborData_);
1616 write_variable(this->cellNeighborData_);
1618 write_variable(this->vertexEdgeData_);
1620 write_variable(this->vertexTriangleData_);
1622 write_variable(this->edgeTriangleData_);
1624 write_variable(this->vertexStarData_);
1626 write_variable(this->edgeStarData_);
1628 write_variable(this->triangleStarData_);
1630 write_variable(this->vertexLinkData_);
1632 write_variable(this->edgeLinkData_);
1634 write_variable(this->triangleLinkData_);
1636 const auto write_bool = [&stream](
const std::vector<bool> &arr) {
1639 for(
size_t i = 0; i < arr.size(); ++i) {
1640 const auto b =
static_cast<char>(arr[i]);
1657 stream << ttk::ExplicitTriangulation::magicBytes_ <<
'\n';
1659 stream << ttk::ExplicitTriangulation::formatVersion_ + 1 <<
'\n';
1662 stream <<
"dim " << dim <<
'\n';
1665 const auto edgesNumber = [
this, dim]() ->
SimplexId {
1668 }
else if(dim > 1) {
1673 const auto nEdges = edgesNumber();
1674 const auto trianglesNumber = [
this, dim]() ->
SimplexId {
1677 }
else if(dim == 3) {
1682 const auto nTriangles = trianglesNumber();
1684 stream << nVerts <<
' ' << nEdges <<
' ' << nTriangles <<
' ' << nTetras
1687#define WRITE_ASCII(ARRAY) \
1688 stream << #ARRAY << '\n'; \
1689 for(const auto &slice : ARRAY) { \
1690 for(size_t i = 0; i < slice.size(); ++i) { \
1694 stream << slice[i]; \
1699 const auto writeCellArray = [
this, &stream]() {
1700 stream <<
"this->cellArray_\n";
1701 for(
SimplexId i = 0; i < this->cellNumber_; ++i) {
1702 for(
SimplexId j = 0; j < this->cellArray_->getCellVertexNumber(i); ++j) {
1703 stream << this->cellArray_->getCellVertex(i, j) <<
' ';
1731#define WRITE_BOOL(ARRAY) \
1732 stream << #ARRAY << '\n'; \
1733 for(const auto el : ARRAY) { \
1734 stream << el << '\n'; \
1745template <
typename T>
1747 stream.read(
reinterpret_cast<char *
>(&res),
sizeof(res));
1750template <
typename T>
1752 stream.read(
reinterpret_cast<char *
>(res), size *
sizeof(T));
1758 const auto magicBytesLen
1759 = std::strlen(ttk::ExplicitTriangulation::magicBytes_);
1760 std::vector<char> mBytes(magicBytesLen + 1);
1761 stream.read(mBytes.data(), magicBytesLen);
1762 const auto hasMagicBytes
1763 = std::strcmp(mBytes.data(), ttk::ExplicitTriangulation::magicBytes_) == 0;
1764 if(!hasMagicBytes) {
1765 this->
printErr(
"Could not find magic bytes in input files!");
1770 unsigned long version{};
1772 if(version != ttk::ExplicitTriangulation::formatVersion_) {
1773 this->
printWrn(
"File format version (" + std::to_string(version)
1774 +
") and software version ("
1775 + std::to_string(ttk::ExplicitTriangulation::formatVersion_)
1776 +
") are different!");
1780 SimplexId nVerts{}, nEdges{}, nTriangles{}, nTetras{};
1794 this->
printErr(
"Incorrect dimension!");
1798 this->
printErr(
"Incorrect number of vertices!");
1803 this->
printErr(
"Incorrect number of cells!");
1809 const auto read_guard = [&stream]() {
1815#define READ_FIXED(ARRAY, N_ITEMS) \
1816 if(!read_guard()) { \
1817 ARRAY.resize(N_ITEMS); \
1818 readBinArray(stream, ARRAY.data(), N_ITEMS); \
1834 const auto read_variable
1840 std::vector<SimplexId> offsets{}, data{};
1841 offsets.resize(n_items + 1);
1843 data.resize(offsets.back());
1845 arr.setData(std::move(data), std::move(offsets));
1849 read_variable(this->vertexNeighborData_, nVerts);
1853 read_variable(this->vertexEdgeData_, nVerts);
1855 read_variable(this->vertexTriangleData_, nVerts);
1857 read_variable(this->edgeTriangleData_, nEdges);
1859 read_variable(this->vertexStarData_, nVerts);
1861 read_variable(this->edgeStarData_, nEdges);
1863 read_variable(this->triangleStarData_, nTriangles);
1865 read_variable(this->vertexLinkData_, nVerts);
1867 read_variable(this->edgeLinkData_, nEdges);
1869 read_variable(this->triangleLinkData_, nTriangles);
1871 const auto read_bool
1872 = [&stream, &read_guard](std::vector<bool> &arr,
const SimplexId n_items) {
1878 arr.resize(n_items);
1879 for(
SimplexId i = 0; i < n_items; ++i) {
1881 stream.read(&b,
sizeof(b));
1882 arr[i] =
static_cast<bool>(b);
#define TTK_TRIANGULATION_INTERNAL(NAME)
void readBinArray(std::ifstream &stream, T *const res, const size_t size)
void writeBin(std::ofstream &stream, const T var)
void readBin(std::ifstream &stream, T &res)
#define READ_FIXED(ARRAY, N_ITEMS)
#define WRITE_GUARD(ARRAY)
#define WRITE_FIXED(ARRAY)
void writeBinArray(std::ofstream &stream, const T *const buff, const size_t size)
#define WRITE_BOOL(ARRAY)
#define WRITE_ASCII(ARRAY)
#define TTK_PSORT(NTHREADS,...)
Parallel sort macro.
std::vector< std::array< SimplexId, 3 > > triangleList_
std::vector< bool > boundaryEdges_
virtual int getTriangleEdge(const SimplexId &triangleId, const int &localEdgeId, SimplexId &edgeId) const
std::vector< bool > boundaryTriangles_
std::vector< std::array< SimplexId, 4 > > tetraTriangleList_
virtual int preconditionTriangleEdges()
std::vector< bool > boundaryVertices_
std::vector< std::array< SimplexId, 2 > > edgeList_
std::vector< std::array< SimplexId, 6 > > tetraEdgeList_
size_t footprint(size_t size=0) const
std::vector< std::array< SimplexId, 3 > > triangleEdgeList_
int printWrn(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
int setWrapper(const Wrapper *wrapper) override
void setDebugMsgPrefix(const std::string &prefix)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
SimplexId getTriangleEdgeNumberInternal(const SimplexId &triangleId) const override
int preconditionEdgeStarsInternal() override
size_t footprint(size_t size=0) const
int preconditionTriangleStarsInternal() override
int preconditionTrianglesInternal() override
SimplexId getNumberOfTrianglesInternal() const override
SimplexId getCellEdgeNumberInternal(const SimplexId &cellId) const override
int writeToFile(std::ofstream &stream) const
Write internal state to disk.
int preconditionBoundaryTrianglesInternal() override
int preconditionEdgesInternal() override
int preconditionCellTrianglesInternal() override
int preconditionVertexNeighborsInternal() override
SimplexId TTK_TRIANGULATION_INTERNAL() getNumberOfCells() const override
int TTK_TRIANGULATION_INTERNAL() getTriangleStar(const SimplexId &triangleId, const int &localStarId, SimplexId &starId) const override
int preconditionCellEdgesInternal() override
int preconditionVertexLinksInternal() override
SimplexId TTK_TRIANGULATION_INTERNAL() getTriangleStarNumber(const SimplexId &triangleId) const override
int preconditionTriangleLinksInternal() override
int preconditionManifoldInternal() override
~ExplicitTriangulation() override
int preconditionEdgeLinksInternal() override
int preconditionVertexStarsInternal() override
int preconditionVertexEdgesInternal() override
int preconditionBoundaryEdgesInternal() override
int preconditionEdgeTrianglesInternal() override
int getCellEdgeInternal(const SimplexId &cellId, const int &localEdgeId, SimplexId &edgeId) const override
int preconditionBoundaryVerticesInternal() override
SimplexId getNumberOfEdgesInternal() const override
int preconditionTriangleEdgesInternal() override
SimplexId TTK_TRIANGULATION_INTERNAL() getEdgeStarNumber(const SimplexId &edgeId) const override
int TTK_TRIANGULATION_INTERNAL() getDimensionality() const override
int TTK_TRIANGULATION_INTERNAL() getEdgeStar(const SimplexId &edgeId, const int &localStarId, SimplexId &starId) const override
int preconditionCellNeighborsInternal() override
int writeToFileASCII(std::ofstream &stream) const
Write internal state to disk using an ASCII format.
SimplexId getCellTriangleNumberInternal(const SimplexId &cellId) const override
SimplexId TTK_TRIANGULATION_INTERNAL() getNumberOfVertices() const override
int getCellTriangleInternal(const SimplexId &cellId, const int &localTriangleId, SimplexId &triangleId) const override
int preconditionVertexTrianglesInternal() override
int readFromFile(std::ifstream &stream)
Read from disk into internal state.
Replacement for std::vector<std::vector<SimplexId>>
size_t footprint() const
Computes the memory footprint of the array.
SimplexId size(SimplexId id) const
Get the size of a particular sub-vector.
bool empty() const
If the underlying buffers are empty.
OneSkeleton processing package.
int buildEdgeLinks(const std::vector< std::array< SimplexId, 2 > > &edgeList, const FlatJaggedArray &edgeStars, const CellArray &cellArray, FlatJaggedArray &edgeLinks) const
int buildEdgeList(const SimplexId &vertexNumber, const CellArray &cellArray, std::vector< std::array< SimplexId, 2 > > &edgeList, FlatJaggedArray &edgeStars, std::vector< std::array< SimplexId, n > > &cellEdgeList) const
ThreeSkeleton processing package.
int buildCellNeighborsFromTriangles(const SimplexId &vertexNumber, const CellArray &cellArray, FlatJaggedArray &cellNeighbors, FlatJaggedArray *triangleStars=nullptr) const
TwoSkeleton processing package.
int buildTriangleEdgeList(const SimplexId &vertexNumber, const CellArray &cellArray, std::vector< std::array< SimplexId, 3 > > &triangleEdgeList, const std::vector< std::array< SimplexId, 2 > > &edgeList, FlatJaggedArray *vertexEdgeList=nullptr, std::vector< std::array< SimplexId, 3 > > *triangleList=nullptr, FlatJaggedArray *triangleStarList=nullptr, std::vector< std::array< SimplexId, 4 > > *cellTriangleList=nullptr) const
int buildVertexTriangles(const SimplexId &vertexNumber, const std::vector< std::array< SimplexId, 3 > > &triangleList, FlatJaggedArray &vertexTriangles) const
int buildCellNeighborsFromEdges(const CellArray &cellArray, FlatJaggedArray &cellNeighbors, const FlatJaggedArray &edgeStars) const
int buildTriangleLinks(const std::vector< std::array< SimplexId, 3 > > &triangleList, const FlatJaggedArray &triangleStars, const CellArray &cellArray, FlatJaggedArray &triangleLinks) const
int buildTriangleList(const SimplexId &vertexNumber, const CellArray &cellArray, std::vector< std::array< SimplexId, 3 > > *triangleList=nullptr, FlatJaggedArray *triangleStars=nullptr, std::vector< std::array< SimplexId, 4 > > *cellTriangleList=nullptr) const
int buildEdgeTriangles(const SimplexId &vertexNumber, const CellArray &cellArray, FlatJaggedArray &edgeTriangleList, const std::vector< std::array< SimplexId, 2 > > &edgeList, std::vector< std::array< SimplexId, 3 > > *triangleEdgeList=nullptr) const
ZeroSkeleton processing package.
int buildVertexEdges(const SimplexId &vertexNumber, const std::vector< std::array< SimplexId, 2 > > &edgeList, FlatJaggedArray &vertexEdges) const
int buildVertexStars(const SimplexId &vertexNumber, const CellArray &cellArray, FlatJaggedArray &vertexStars) const
int buildVertexLinks(const FlatJaggedArray &vertexStars, const std::vector< std::array< SimplexId, 3 > > &cellEdges, const std::vector< std::array< SimplexId, 2 > > &edgeList, FlatJaggedArray &vertexLinks) const
int buildVertexNeighbors(const SimplexId &vertexNumber, FlatJaggedArray &vertexNeighbors, const std::vector< std::array< SimplexId, 2 > > &edgeList) const
COMMON_EXPORTS int MPIsize_
COMMON_EXPORTS int MPIrank_
long long int LongSimplexId
Identifier type for simplices of any dimension.
int SimplexId
Identifier type for simplices of any dimension.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)