10 this->SetNumberOfInputPorts(1);
11 this->SetNumberOfOutputPorts(1);
13 hasMPISupport_ =
true;
18 int port, vtkInformation *info) {
20 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkImageData");
27 int port, vtkInformation *info) {
29 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkImageData");
39 vtkInformationVector **inputVector,
40 vtkInformationVector *
ttkNotUsed(outputVector)) {
41 this->ComputeOutputExtent();
42 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
43 std::array<int, 6> outExtentWithoutGhost{outExtent_};
44 for(
int i = 0; i < 3; i++) {
45 if(std::abs(outExtent_[2 * i] - outExtent_[2 * i + 1]) > spacing_[i] / 10) {
46 if(!(localGlobalBounds_[2 * i].isBound == 1
47 && localGlobalBounds_[2 * i].isBound
48 == localGlobalBounds_[2 * i + 1].isBound)) {
49 outExtentWithoutGhost[2 * i] += 1;
50 outExtentWithoutGhost[2 * i + 1] -= 1;
54 inInfo->Set(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT(),
55 outExtentWithoutGhost[0], outExtentWithoutGhost[1],
56 outExtentWithoutGhost[2], outExtentWithoutGhost[3],
57 outExtentWithoutGhost[4], outExtentWithoutGhost[5]);
63 vtkInformationVector **inputVectors,
64 vtkInformationVector *outputVector) {
65 vtkInformation *inInfo = inputVectors[0]->GetInformationObject(0);
67 vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), inExtent_.data());
68 inInfo->Get(vtkDataObject::SPACING(), this->spacing_.data());
69 inInfo->Get(vtkDataObject::ORIGIN(), this->origin_.data());
70 this->ComputeOutputExtent();
71 vtkInformation *outInfo = outputVector->GetInformationObject(0);
73 vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), outExtent_.data(), 6);
74 outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_EXTENT());
78int ttkPeriodicGhostsGeneration::ComputeOutputExtent() {
81 vtkNew<vtkExtentTranslator> translator;
82 translator->SetWholeExtent(inExtent_.data());
85 translator->PieceToExtent();
87 translator->GetExtent(localExtent);
91 origin_[0] + localExtent[0] * spacing_[0],
92 origin_[0] + localExtent[1] * spacing_[0],
93 origin_[1] + localExtent[2] * spacing_[1],
94 origin_[1] + localExtent[3] * spacing_[1],
95 origin_[2] + localExtent[4] * spacing_[2],
96 origin_[2] + localExtent[5] * spacing_[2],
99 if(!isOutputExtentComputed_
100 || std::abs(boundsWithoutGhosts_[0] - bounds[0]) > spacing_[0] / 10
101 || std::abs(boundsWithoutGhosts_[1] - bounds[1]) > spacing_[0] / 10
102 || std::abs(boundsWithoutGhosts_[2] - bounds[2]) > spacing_[1] / 10
103 || std::abs(boundsWithoutGhosts_[3] - bounds[3]) > spacing_[1] / 10
104 || std::abs(boundsWithoutGhosts_[4] - bounds[4]) > spacing_[2] / 10
105 || std::abs(boundsWithoutGhosts_[5] - bounds[5]) > spacing_[2] / 10) {
107 = {bounds[0], bounds[1], bounds[2], bounds[3], bounds[4], bounds[5]};
109 globalBounds_ = {origin_[0] + inExtent_[0] * spacing_[0],
110 origin_[0] + inExtent_[1] * spacing_[0],
111 origin_[1] + inExtent_[2] * spacing_[1],
112 origin_[1] + inExtent_[3] * spacing_[1],
113 origin_[2] + inExtent_[4] * spacing_[2],
114 origin_[2] + inExtent_[5] * spacing_[2]};
116 std::map<int, int> neighborsToId{};
117 ttk::preconditionNeighborsUsingBoundingBox(
118 bounds, neighbors_, neighborsToId);
123 for(
int i = 0; i < 2; i++) {
124 if(std::abs(globalBounds_[i] - boundsWithoutGhosts_[i])
125 < spacing_[0] / 10) {
126 localGlobalBounds_[i].isBound = 1;
127 localGlobalBounds_[i].x = boundsWithoutGhosts_[i];
128 localGlobalBounds_[i].y
129 = (boundsWithoutGhosts_[2] + boundsWithoutGhosts_[3]) / 2;
130 localGlobalBounds_[i].z
131 = (boundsWithoutGhosts_[4] + boundsWithoutGhosts_[5]) / 2;
135 for(
int i = 0; i < 2; i++) {
136 if(std::abs(globalBounds_[2 + i] - boundsWithoutGhosts_[2 + i])
137 < spacing_[1] / 10) {
138 localGlobalBounds_[2 + i].isBound = 1;
139 localGlobalBounds_[2 + i].x
140 = (boundsWithoutGhosts_[0] + boundsWithoutGhosts_[1]) / 2;
141 localGlobalBounds_[2 + i].y = boundsWithoutGhosts_[2 + i];
142 localGlobalBounds_[2 + i].z
143 = (boundsWithoutGhosts_[4] + boundsWithoutGhosts_[5]) / 2;
147 for(
int i = 0; i < 2; i++) {
148 if(std::abs(globalBounds_[4 + i] - boundsWithoutGhosts_[4 + i])
149 < spacing_[2] / 10) {
150 localGlobalBounds_[4 + i].isBound = 1;
151 localGlobalBounds_[4 + i].x
152 = (boundsWithoutGhosts_[0] + boundsWithoutGhosts_[1]) / 2;
153 localGlobalBounds_[4 + i].y
154 = (boundsWithoutGhosts_[2] + boundsWithoutGhosts_[3]) / 2;
155 localGlobalBounds_[4 + i].z = boundsWithoutGhosts_[4 + i];
162 for(
int i = 0; i < 3; i++) {
163 if(!(localGlobalBounds_[2 * i].isBound == 1
164 && localGlobalBounds_[2 * i + 1].isBound == 1)) {
165 outExtent_[2 * i] = inExtent_[2 * i] - 1;
166 outExtent_[2 * i + 1] = inExtent_[2 * i + 1] + 1;
168 outExtent_[2 * i] = inExtent_[2 * i];
169 outExtent_[2 * i + 1] = inExtent_[2 * i + 1];
176 for(
int i = 0; i < 3; i++) {
177 if(localGlobalBounds_[2 * i].isBound == 1
178 && localGlobalBounds_[2 * i].isBound
179 == localGlobalBounds_[2 * i + 1].isBound) {
180 isBoundaryPeriodic_[2 * i] = 0;
181 isBoundaryPeriodic_[2 * i + 1] = 0;
183 isBoundaryPeriodic_[2 * i] = localGlobalBounds_[2 * i].isBound;
184 isBoundaryPeriodic_[2 * i + 1] = localGlobalBounds_[2 * i + 1].isBound;
187 isOutputExtentComputed_ =
true;
192template <
int matchesSize,
int metaDataSize>
193int ttkPeriodicGhostsGeneration::MarshalAndSendRecv(
194 vtkImageData *imageIn,
196 std::vector<std::vector<std::array<ttk::SimplexId, metaDataSize>>>
197 &charArrayBoundariesMetaData,
198 std::vector<std::array<ttk::SimplexId, matchesSize>> &matches,
200 std::vector<std::array<ttk::SimplexId, metaDataSize>>
201 &charArrayBoundariesMetaDataReceived,
204 int *default_VOI = imageIn->GetExtent();
205 std::array<ttk::SimplexId, 6> VOI;
207 std::vector<std::vector<int>> additionalNeighbors(
209 for(
int i = 0; i < matchesNumber; i++) {
211 VOI = {default_VOI[0], default_VOI[1], default_VOI[2],
212 default_VOI[3], default_VOI[4], default_VOI[5]};
214 for(
int k = 1; k <= dim; k++) {
215 if(matches[i][k] % 2 == 0) {
216 VOI[matches[i][k] + 1] = VOI[matches[i][k]];
218 VOI[matches[i][k] - 1] = VOI[matches[i][k]];
223 for(
const auto neigh : neighbors_) {
224 if(neigh != matches[i][0]) {
225 if(!(neighborVertexBBoxes_[neigh][0] == 0
226 && neighborVertexBBoxes_[neigh][1] == 0
227 && neighborVertexBBoxes_[neigh][2] == 0
228 && neighborVertexBBoxes_[neigh][3] == 0
229 && neighborVertexBBoxes_[neigh][4] == 0
230 && neighborVertexBBoxes_[neigh][5] == 0)) {
231 if(VOI[0] - inExtent_[0] <= neighborVertexBBoxes_[neigh][1]
232 && VOI[1] - inExtent_[0] >= neighborVertexBBoxes_[neigh][0]
233 && VOI[2] - inExtent_[2] <= neighborVertexBBoxes_[neigh][3]
234 && VOI[3] - inExtent_[2] >= neighborVertexBBoxes_[neigh][2]
235 && VOI[4] - inExtent_[4] <= neighborVertexBBoxes_[neigh][5]
236 && VOI[5] - inExtent_[4] >= neighborVertexBBoxes_[neigh][4]) {
237 if(std::find(additionalNeighbors[matches[i][0]].
begin(),
238 additionalNeighbors[matches[i][0]].
end(), neigh)
239 == additionalNeighbors[matches[i][0]].
end()) {
240 additionalNeighbors[matches[i][0]].push_back(neigh);
249 extractVOI->SetInputData(imageIn);
250 extractVOI->SetVOI(VOI[0], VOI[1], VOI[2], VOI[3], VOI[4], VOI[5]);
251 extractVOI->Update();
255 if(vtkCommunicator::MarshalDataObject(extracted, buffer) == 0) {
258 charArrayBoundaries[matches[i][0]].emplace_back(buffer);
259 std::array<ttk::SimplexId, metaDataSize> metaData;
260 for(
int j = 0; j < metaDataSize; j++) {
261 metaData.at(j) = matches[i][j + 1];
264 charArrayBoundariesMetaData[matches[i][0]].emplace_back(metaData);
269 std::array<ttk::SimplexId, metaDataSize + 1> sendMetadata;
270 std::array<ttk::SimplexId, metaDataSize + 1> recvMetaData;
274 for(
int j = 0; j < static_cast<int>(charArrayBoundaries[i].size()); j++) {
275 send_size = charArrayBoundaries[i][j]->GetNumberOfTuples();
276 MPI_Sendrecv(&send_size, 1, ttk::getMPIType(send_size), i, 0, &recv_size,
277 1, ttk::getMPIType(recv_size), i, 0, ttk::MPIcomm_,
281 buffer->SetNumberOfTuples(recv_size);
282 buffer->SetNumberOfComponents(1);
283 char *sendPointer = ttkUtils::GetPointer<char>(charArrayBoundaries[i][j]);
284 char *recvPointer = ttkUtils::GetPointer<char>(buffer);
285 MPI_Sendrecv(sendPointer, send_size, MPI_CHAR, i, 0, recvPointer,
286 recv_size, MPI_CHAR, i, 0, ttk::MPIcomm_, MPI_STATUS_IGNORE);
287 charArrayBoundariesReceived.emplace_back(buffer);
288 std::copy(charArrayBoundariesMetaData[i][j].
begin(),
289 charArrayBoundariesMetaData[i][j].
begin() + metaDataSize,
290 sendMetadata.begin());
291 sendMetadata.at(metaDataSize) = additionalNeighbors[i].size();
292 MPI_Sendrecv(sendMetadata.data(), metaDataSize + 1,
293 ttk::getMPIType(recv_size), i, 0, recvMetaData.data(),
294 metaDataSize + 1, ttk::getMPIType(recv_size), i, 0,
295 ttk::MPIcomm_, MPI_STATUS_IGNORE);
296 std::array<ttk::SimplexId, metaDataSize> aux;
297 std::copy(recvMetaData.begin(), recvMetaData.end() - 1, aux.begin());
298 charArrayBoundariesMetaDataReceived.emplace_back(aux);
299 std::vector<int> receivedNeighbors(recvMetaData.back());
300 MPI_Sendrecv(additionalNeighbors[i].data(), additionalNeighbors[i].size(),
301 MPI_INTEGER, i, 0, receivedNeighbors.data(),
302 recvMetaData.back(), MPI_INTEGER, i, 0, ttk::MPIcomm_,
304 for(
const int neigh : receivedNeighbors) {
305 if(std::find(neighbors_.begin(), neighbors_.end(), neigh)
306 == neighbors_.end()) {
307 neighbors_.push_back(neigh);
315template <
typename boundaryType>
316int ttkPeriodicGhostsGeneration::UnMarshalAndMerge(
317 std::vector<boundaryType> &metaDataReceived,
319 boundaryType direction,
321 vtkImageData *mergedImage) {
325 = std::find(metaDataReceived.begin(), metaDataReceived.end(), direction);
326 if(it != metaDataReceived.end()) {
327 vtkNew<vtkStructuredPoints> id;
328 vtkNew<vtkImageData> aux;
331 if(vtkCommunicator::UnMarshalDataObject(
332 boundariesReceived[std::distance(metaDataReceived.begin(), it)],
id)
338 this->MergeImageAndSlice(mergedImage,
id, aux, mergeDirection);
339 mergedImage->DeepCopy(aux);
344template <
typename boundaryType>
345int ttkPeriodicGhostsGeneration::UnMarshalAndCopy(
346 std::vector<boundaryType> &metaDataReceived,
348 boundaryType direction,
349 vtkImageData *mergedImage) {
353 = std::find(metaDataReceived.begin(), metaDataReceived.end(), direction);
354 if(it != metaDataReceived.end()) {
355 vtkNew<vtkStructuredPoints> id;
358 if(vtkCommunicator::UnMarshalDataObject(
359 boundariesReceived[std::distance(metaDataReceived.begin(), it)],
id)
365 mergedImage->DeepCopy(
id);
370int ttkPeriodicGhostsGeneration::MergeDataArrays(
371 vtkDataArray *imageArray,
372 vtkDataArray *sliceArray,
376 unsigned char ghostValue,
379 std::string arrayName(imageArray->GetName());
381#ifndef TTK_ENABLE_KAMIKAZE
384 +
" is not present in the Data of the second vtkImageData");
388 currentArray->SetNumberOfComponents(1);
389 currentArray->SetNumberOfTuples(numberOfSimplices);
390 currentArray->SetName(arrayName.c_str());
392 if(std::strcmp(currentArray->GetName(),
"vtkGhostType") == 0) {
393 if(ghostValue != 0) {
394 sliceArray->SetNumberOfTuples(numberOfTuples);
395 sliceArray->Fill(ghostValue);
397 for(
int i = 0; i < numberOfTuples; i++) {
398 if(sliceArray->GetTuple1(i) == 1) {
399 sliceArray->SetTuple1(i, 16);
404 int sliceCounter = 0;
405 int imageCounter = 0;
408 std::function<bool(
int,
int,
int,
int[3])> addSlice;
412 int ttkNotUsed(dimensions)[3]) {
return x == 0; };
416 int dimensions[3]) {
return x == dimensions[0] - 1; };
420 int ttkNotUsed(dimensions)[3]) {
return y == 0; };
424 int dimensions[3]) {
return y == dimensions[1] - 1; };
428 int ttkNotUsed(dimensions)[3]) {
return z == 0; };
432 int dimensions[3]) {
return z == dimensions[2] - 1; };
437 for(
int z = 0; z < dims[2]; z++) {
438 for(
int y = 0; y < dims[1]; y++) {
439 for(
int x = 0; x < dims[0]; x++) {
440 if(addSlice(x, y, z, dims)) {
441 currentArray->SetTuple1(counter, sliceArray->GetTuple1(sliceCounter));
444 currentArray->SetTuple1(counter, imageArray->GetTuple1(imageCounter));
454int ttkPeriodicGhostsGeneration::MergeImageAndSlice(vtkImageData *image,
456 vtkImageData *mergedImage,
458 vtkDataArray *arrayImage = image->GetCellData()->GetArray(
"Cell Type");
459 vtkDataArray *arraySlice = slice->GetCellData()->GetArray(
"Cell Type");
460 if(!(arrayImage && arraySlice) && arrayImage) {
461 image->GetCellData()->RemoveArray(
"Cell Type");
463 if(!(arrayImage && arraySlice) && arraySlice) {
464 slice->GetCellData()->RemoveArray(
"Cell Type");
467#ifndef TTK_ENABLE_KAMIKAZE
468 if(image->GetPointData()->GetNumberOfArrays()
469 != slice->GetPointData()->GetNumberOfArrays()) {
470 printErr(
"The two vtkImageData objects to merge don't have the same number "
471 "of arrays for their Point Data");
475 if(image->GetCellData()->GetNumberOfArrays()
476 != slice->GetCellData()->GetNumberOfArrays()) {
477 printErr(
"The two vtkImageData objects to merge don't have the same number "
478 "of arrays for their Cell Data");
482 mergedImage->SetSpacing(image->GetSpacing());
483 mergedImage->Initialize();
485 image->GetExtent(extentImage);
486 if(direction % 2 == 0) {
487 extentImage[direction] -= 1;
489 extentImage[direction] += 1;
491 mergedImage->SetExtent(extentImage);
493 mergedImage->GetDimensions(dims);
494 int cellDims[3] = {std::max(dims[0] - 1, 1), std::max(dims[1] - 1, 1),
495 std::max(dims[2] - 1, 1)};
496 int numberOfPoints = mergedImage->GetNumberOfPoints();
498 image->GetDimensions(imageDims);
500 slice->GetDimensions(sliceDims);
502 for(
int array = 0; array < image->GetPointData()->GetNumberOfArrays();
504 vtkDataArray *imageArray = image->GetPointData()->GetArray(array);
505 vtkDataArray *sliceArray
506 = slice->GetPointData()->GetArray(imageArray->GetName());
509 this->MergeDataArrays(imageArray, sliceArray, currentArray, direction, dims,
510 vtkDataSetAttributes::DUPLICATEPOINT, numberOfPoints,
511 slice->GetNumberOfPoints());
512 mergedImage->GetPointData()->AddArray(currentArray);
514 int numberOfCells = mergedImage->GetNumberOfCells();
516 for(
int array = 0; array < image->GetCellData()->GetNumberOfArrays();
518 vtkDataArray *imageArray = image->GetCellData()->GetArray(array);
519 std::string arrayName(imageArray->GetName());
520 vtkDataArray *sliceArray
521 = slice->GetCellData()->GetArray(arrayName.c_str());
522 if(std::strcmp(arrayName.c_str(),
"Cell Type") == 0) {
528 if(direction == 0 || direction == 2 || direction == 4) {
529 this->MergeDataArrays(imageArray, sliceArray, currentArray, direction,
530 cellDims, 0, numberOfCells,
531 slice->GetNumberOfCells());
535 this->MergeDataArrays(imageArray, sliceArray, currentArray, direction,
536 cellDims, vtkDataSetAttributes::EXTERIORCELL,
537 numberOfCells, slice->GetNumberOfCells());
540 mergedImage->GetCellData()->AddArray(currentArray);
543 vtkNew<vtkCharArray> cellTypes;
544 cellTypes->SetName(
"Cell Type");
545 cellTypes->SetNumberOfTuples(numberOfCells);
546 cellTypes->Fill(image->GetCellType(0));
547 mergedImage->GetCellData()->AddArray(cellTypes);
552int ttkPeriodicGhostsGeneration::MPIPeriodicGhostPipelinePreconditioning(
553 vtkImageData *imageIn, vtkImageData *imageOut) {
555 if(!ttk::isRunningWithMPI()) {
566 int dimensionality = imageIn->GetDataDimension();
570 neighborVertexBBoxes_ = triangulation->getNeighborVertexBBoxes();
574 std::map<int, ttk::SimplexId> dimensionOrder;
575 dimensionOrder[0] = inExtent_[1] - inExtent_[0];
576 dimensionOrder[2] = inExtent_[3] - inExtent_[2];
577 dimensionOrder[4] = inExtent_[5] - inExtent_[4];
583 auto maxMap = [](
const std::pair<int, ttk::SimplexId> &p1,
584 const std::pair<int, ttk::SimplexId> &p2) {
585 return p1.second <= p2.second;
587 auto pr = std::max_element(
588 std::begin(dimensionOrder), std::end(dimensionOrder), maxMap);
589 firstDim = pr->first;
590 dimensionOrder[pr->first] = std::round(pr->second / 2);
591 pr = std::max_element(
592 std::begin(dimensionOrder), std::end(dimensionOrder), maxMap);
593 if(firstDim != pr->first) {
594 secondDim = pr->first;
596 dimensionOrder[pr->first] = std::round(pr->second / 2);
598 pr = std::max_element(
599 std::begin(dimensionOrder), std::end(dimensionOrder), maxMap);
600 if(secondDim == -1) {
601 secondDim = pr->first;
603 thirdDim = 6 - (firstDim + secondDim);
605 this->ComputeOutputExtent();
608 MPI_Datatype partialGlobalBoundMPI;
609 std::vector<ttk::periodicGhosts::partialGlobalBound> allLocalGlobalBounds(
612 = {MPI_UNSIGNED_CHAR, MPI_DOUBLE, MPI_DOUBLE, MPI_DOUBLE};
613 int lengths[] = {1, 1, 1, 1};
614 const long int mpi_offsets[]
619 MPI_Type_create_struct(
620 4, lengths, mpi_offsets, types, &partialGlobalBoundMPI);
621 MPI_Type_commit(&partialGlobalBoundMPI);
623 MPI_Allgather(localGlobalBounds_.data(), 6, partialGlobalBoundMPI,
624 allLocalGlobalBounds.data(), 6, partialGlobalBoundMPI,
628 std::vector<std::array<ttk::SimplexId, 3>> matches;
631 for(
int j = 0; j < 6; j++) {
633 if(!(localGlobalBounds_[other(j)].isBound != 0
634 && localGlobalBounds_[j].isBound != 0)) {
635 if(localGlobalBounds_[other(j)].isBound != 0
636 && allLocalGlobalBounds[i * 6 + j].isBound != 0) {
637 if(0 <= j && j <= 1) {
639 = (boundsWithoutGhosts_[2] <= allLocalGlobalBounds[i * 6 + j].y
640 && boundsWithoutGhosts_[3]
641 >= allLocalGlobalBounds[i * 6 + j].y)
642 && (boundsWithoutGhosts_[4]
643 <= allLocalGlobalBounds[i * 6 + j].z
644 && boundsWithoutGhosts_[5]
645 >= allLocalGlobalBounds[i * 6 + j].z);
647 if(2 <= j && j <= 3) {
649 = (boundsWithoutGhosts_[0] <= allLocalGlobalBounds[i * 6 + j].x
650 && boundsWithoutGhosts_[1]
651 >= allLocalGlobalBounds[i * 6 + j].x)
652 && (boundsWithoutGhosts_[4]
653 <= allLocalGlobalBounds[i * 6 + j].z
654 && boundsWithoutGhosts_[5]
655 >= allLocalGlobalBounds[i * 6 + j].z);
657 if(4 <= j && j <= 5) {
659 = (boundsWithoutGhosts_[0] <= allLocalGlobalBounds[i * 6 + j].x
660 && boundsWithoutGhosts_[1]
661 >= allLocalGlobalBounds[i * 6 + j].x)
662 && (boundsWithoutGhosts_[2]
663 <= allLocalGlobalBounds[i * 6 + j].y
664 && boundsWithoutGhosts_[3]
665 >= allLocalGlobalBounds[i * 6 + j].y);
668 matches.emplace_back(
669 std::array<ttk::SimplexId, 3>{i, other(j), j});
670 if(std::find(neighbors_.begin(), neighbors_.end(), i)
671 == neighbors_.end()) {
672 neighbors_.push_back(i);
681 std::vector<std::array<ttk::SimplexId, 2>> local2DBounds;
682 std::vector<std::array<ttk::SimplexId, 3>> matches_2D;
683 if(dimensionality >= 2) {
684 for(
int i = 0; i < 4; i++) {
685 for(
int j = i + 1; j < 6; j++) {
686 if((abs(i - j) == 1 && i % 2 == 1) || abs(i - j) >= 2) {
687 if((localGlobalBounds_[i].isBound != 0
688 && localGlobalBounds_[j].isBound != 0)
689 && !(localGlobalBounds_[other(i)].isBound != 0
690 && localGlobalBounds_[other(j)].isBound != 0)) {
691 local2DBounds.emplace_back(std::array<ttk::SimplexId, 2>{i, j});
697 for(
int i = 0; i < static_cast<int>(local2DBounds.size()); i++) {
701 if((allLocalGlobalBounds[j * 6 + other(local2DBounds[i][0])].isBound
703 && (allLocalGlobalBounds[j * 6 + other(local2DBounds[i][1])]
707 = {other(local2DBounds[i][0]), other(local2DBounds[i][1])};
708 std::sort(dirs, dirs + 2);
709 if((dirs[0] < 2 && dirs[1] >= 2 && dirs[1] < 4)) {
710 isIn = (boundsWithoutGhosts_[4]
711 <= allLocalGlobalBounds[j * 6 + dirs[0]].z
712 && boundsWithoutGhosts_[5]
713 >= allLocalGlobalBounds[j * 6 + dirs[0]].z);
715 if((dirs[0] < 2 && dirs[1] >= 4)) {
716 isIn = (boundsWithoutGhosts_[2]
717 <= allLocalGlobalBounds[j * 6 + dirs[0]].y
718 && boundsWithoutGhosts_[3]
719 >= allLocalGlobalBounds[j * 6 + dirs[0]].y);
721 if((dirs[0] >= 2 && dirs[0] < 4 && dirs[1] >= 4)) {
722 isIn = (boundsWithoutGhosts_[0]
723 <= allLocalGlobalBounds[j * 6 + dirs[0]].x
724 && boundsWithoutGhosts_[1]
725 >= allLocalGlobalBounds[j * 6 + dirs[0]].x);
728 matches_2D.emplace_back(std::array<ttk::SimplexId, 3>{
729 j, local2DBounds[i][0], local2DBounds[i][1]});
730 if(std::find(neighbors_.begin(), neighbors_.end(), j)
731 == neighbors_.end()) {
732 neighbors_.push_back(j);
741 std::vector<std::array<ttk::SimplexId, 3>> local3DBounds;
742 std::vector<std::array<ttk::SimplexId, 4>> matches_3D;
743 if(dimensionality == 3) {
744 for(
int i = 0; i < 2; i++) {
745 for(
int j = 0; j < 2; j++) {
746 for(
int k = 0; k < 2; k++) {
747 if(localGlobalBounds_[i].isBound != 0
748 && localGlobalBounds_[2 + j].isBound != 0
749 && localGlobalBounds_[4 + k].isBound != 0) {
750 local3DBounds.emplace_back(
751 std::array<ttk::SimplexId, 3>{i, 2 + j, 4 + k});
756 for(
int i = 0; i < static_cast<int>(local3DBounds.size()); i++) {
759 if((allLocalGlobalBounds[j * 6 + other(local3DBounds[i][0])].isBound
761 && (allLocalGlobalBounds[j * 6 + other(local3DBounds[i][1])]
764 && (allLocalGlobalBounds[j * 6 + other(local3DBounds[i][2])]
767 matches_3D.emplace_back(std::array<ttk::SimplexId, 4>{
768 j, local3DBounds[i][0], local3DBounds[i][1],
769 local3DBounds[i][2]});
770 if(std::find(neighbors_.begin(), neighbors_.end(), j)
771 == neighbors_.end()) {
772 neighbors_.push_back(j);
780 std::vector<std::vector<vtkSmartPointer<vtkCharArray>>> charArrayBoundaries(
782 std::vector<std::vector<std::array<ttk::SimplexId, 1>>>
784 std::vector<vtkSmartPointer<vtkCharArray>> charArrayBoundariesReceived;
785 std::vector<std::array<ttk::SimplexId, 1>>
786 charArrayBoundariesMetaDataReceived;
787 if(this->MarshalAndSendRecv<3, 1>(
788 imageIn, charArrayBoundaries, charArrayBoundariesMetaData, matches,
789 charArrayBoundariesReceived, charArrayBoundariesMetaDataReceived, 1)
791 printErr(
"Error occurred when marshalling messages");
796 std::vector<std::vector<vtkSmartPointer<vtkCharArray>>> charArray2DBoundaries(
798 std::vector<std::vector<std::array<ttk::SimplexId, 2>>>
800 std::vector<vtkSmartPointer<vtkCharArray>> charArray2DBoundariesReceived;
801 std::vector<std::array<ttk::SimplexId, 2>>
802 charArray2DBoundariesMetaDataReceived;
803 if(dimensionality >= 2) {
804 if(this->MarshalAndSendRecv<3, 2>(imageIn, charArray2DBoundaries,
805 charArray2DBoundariesMetaData, matches_2D,
806 charArray2DBoundariesReceived,
807 charArray2DBoundariesMetaDataReceived, 2)
813 std::vector<std::vector<vtkSmartPointer<vtkCharArray>>> charArray3DBoundaries(
815 std::vector<std::vector<std::array<ttk::SimplexId, 3>>>
817 std::vector<vtkSmartPointer<vtkCharArray>> charArray3DBoundariesReceived;
818 std::vector<std::array<ttk::SimplexId, 3>>
819 charArray3DBoundariesMetaDataReceived;
820 if(dimensionality == 3) {
821 if(this->MarshalAndSendRecv<4, 3>(imageIn, charArray3DBoundaries,
822 charArray3DBoundariesMetaData, matches_3D,
823 charArray3DBoundariesReceived,
824 charArray3DBoundariesMetaDataReceived, 3)
829 imageOut->DeepCopy(imageIn);
832 for(
int dir = firstDim; dir < firstDim + 2; dir++) {
833 if(this->UnMarshalAndMerge<std::array<ttk::SimplexId, 1>>(
834 charArrayBoundariesMetaDataReceived, charArrayBoundariesReceived,
835 std::array<ttk::SimplexId, 1>{other(dir)}, dir, imageOut)
840 if(dimensionality >= 2) {
842 for(
int dir = secondDim; dir < secondDim + 2; dir++) {
845 if(this->UnMarshalAndCopy<std::array<ttk::SimplexId, 1>>(
846 charArrayBoundariesMetaDataReceived, charArrayBoundariesReceived,
847 std::array<ttk::SimplexId, 1>{other(dir)}, mergedImage)
851 if(mergedImage->GetNumberOfPoints() > 0) {
852 for(
int dir_2D = firstDim; dir_2D < firstDim + 2; dir_2D++) {
853 std::array<ttk::SimplexId, 2> merge_dir{
854 std::min(other(dir), other(dir_2D)),
855 std::max(other(dir_2D), other(dir))};
856 if(this->UnMarshalAndMerge<std::array<ttk::SimplexId, 2>>(
857 charArray2DBoundariesMetaDataReceived,
858 charArray2DBoundariesReceived, merge_dir, dir_2D, mergedImage)
865 if(this->MergeImageAndSlice(imageOut, mergedImage, aux, dir) == 0) {
868 imageOut->DeepCopy(aux);
872 if(dimensionality == 3) {
874 for(
int dir = thirdDim; dir < thirdDim + 2; dir++) {
875 vtkNew<vtkImageData> mergedImage1;
876 if(this->UnMarshalAndCopy<std::array<ttk::SimplexId, 1>>(
877 charArrayBoundariesMetaDataReceived, charArrayBoundariesReceived,
878 std::array<ttk::SimplexId, 1>{other(dir)}, mergedImage1)
882 if(mergedImage1->GetNumberOfPoints() > 0) {
883 for(
int dir_2D = firstDim; dir_2D < firstDim + 2; dir_2D++) {
884 std::array<ttk::SimplexId, 2> merge_dir{
885 std::min(other(dir), other(dir_2D)),
886 std::max(other(dir_2D), other(dir))};
887 if(this->UnMarshalAndMerge<std::array<ttk::SimplexId, 2>>(
888 charArray2DBoundariesMetaDataReceived,
889 charArray2DBoundariesReceived, merge_dir, dir_2D, mergedImage1)
894 for(
int dir_2D = secondDim; dir_2D < secondDim + 2; dir_2D++) {
895 vtkNew<vtkImageData> mergedImage2;
896 std::array<ttk::SimplexId, 2> merge_dir_2D{
897 std::min(other(dir), other(dir_2D)),
898 std::max(other(dir_2D), other(dir))};
899 if(this->UnMarshalAndCopy<std::array<ttk::SimplexId, 2>>(
900 charArray2DBoundariesMetaDataReceived,
901 charArray2DBoundariesReceived, merge_dir_2D, mergedImage2)
905 if(mergedImage2->GetNumberOfPoints() > 0) {
906 for(
int dir_3D = firstDim; dir_3D < firstDim + 2; dir_3D++) {
907 std::array<ttk::SimplexId, 3> merge_dir_3D{
908 other(dir), other(dir_2D), other(dir_3D)};
909 std::sort(merge_dir_3D.begin(), merge_dir_3D.end());
910 if(this->UnMarshalAndMerge<std::array<ttk::SimplexId, 3>>(
911 charArray3DBoundariesMetaDataReceived,
912 charArray3DBoundariesReceived, merge_dir_3D, dir_3D,
918 vtkNew<vtkImageData> aux;
919 if(this->MergeImageAndSlice(mergedImage1, mergedImage2, aux, dir_2D)
923 mergedImage1->DeepCopy(aux);
926 if(mergedImage1->GetNumberOfPoints() > 0) {
927 vtkNew<vtkImageData> aux;
928 if(this->MergeImageAndSlice(imageOut, mergedImage1, aux, dir) == 0) {
931 imageOut->DeepCopy(aux);
937 int nbArrays = imageOut->GetPointData()->GetNumberOfArrays();
938 for(
int i = nbArrays - 1; i >= 0; i--) {
939 vtkDataArray *array = imageOut->GetPointData()->GetArray(i);
940 std::string arrayName = std::string(array->GetName());
941 if(arrayName.rfind(
"_Order") == (arrayName.size() - 6)) {
942 imageOut->GetPointData()->RemoveArray(i);
951 vtkInformationVector **inputVector,
952 vtkInformationVector *outputVector) {
954 vtkImageData *imageIn = vtkImageData::GetData(inputVector[0]);
955 vtkImageData *imageOut = vtkImageData::GetData(outputVector);
957 this->MPIPeriodicGhostPipelinePreconditioning(imageIn, imageOut);
959 imageOut->ShallowCopy(imageIn);
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
virtual int RequestInformation(vtkInformation *ttkNotUsed(request), vtkInformationVector **ttkNotUsed(inputVectors), vtkInformationVector *ttkNotUsed(outputVector))
ttk::Triangulation * GetTriangulation(vtkDataSet *dataSet)
virtual int RequestUpdateExtent(vtkInformation *ttkNotUsed(request), vtkInformationVector **ttkNotUsed(inputVectors), vtkInformationVector *ttkNotUsed(outputVector))
TTK VTK-filter that generates an outside ghost layer for periodic implicit grids when used in a distr...
int FillOutputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
int FillInputPortInformation(int port, vtkInformation *info) override
ttkPeriodicGhostsGeneration()
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
RegularGridTriangulation is an abstract subclass of ttk::AbstractTriangulation that exposes a common ...
COMMON_EXPORTS int MPIsize_
COMMON_EXPORTS int MPIrank_
int SimplexId
Identifier type for simplices of any dimension.
T end(std::pair< T, T > &p)
T begin(std::pair< T, T > &p)
vtkStandardNewMacro(ttkPeriodicGhostsGeneration)