Commit 524ba39d authored by Chuck Atkins's avatar Chuck Atkins Committed by Kitware Robot
Browse files

Merge topic 'multiple-ghostcell-layers'

e8c9e0af

 Updated vtkPUnstructuredGridGhostCellsGenerator
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Reviewed-by: default avatarJoachim Pouderoux <joachim.pouderoux@kitware.com>
Merge-request: !1107
parents ffd7a24f e8c9e0af
......@@ -145,83 +145,94 @@ int TestPUnstructuredGridGhostCellsGenerator(int argc, char* argv[])
ghostGenerator->Modified();
// Check ghost cells generated with and without the global point ids
// for several ghost layer levels
int maxGhostLevel = 2;
vtkUnstructuredGrid* outGrids[2];
for(int step = 0; step < 2; ++step)
for(int ghostLevel = 1; ghostLevel <= maxGhostLevel; ++ghostLevel)
{
ghostGenerator->SetUseGlobalPointIds(step == 0 ? 1 : 0);
vtkNew<vtkTimerLog> timer;
timer->StartTimer();
ghostGenerator->UpdatePiece(rankId, nbRanks, 1);
timer->StopTimer();
// Save the grid for further analyze
outGrids[step] = ghostGenerator->GetOutput();
outGrids[step]->Register(0);
double ellapsed = timer->GetElapsedTime();
// get some performance statistics
double minGhostUpdateTime = 0.0;
double maxGhostUpdateTime = 0.0;
double avgGhostUpdateTime = 0.0;
controller->Reduce(&ellapsed, &minGhostUpdateTime, 1, vtkCommunicator::MIN_OP, 0);
controller->Reduce(&ellapsed, &maxGhostUpdateTime, 1, vtkCommunicator::MAX_OP, 0);
controller->Reduce(&ellapsed, &avgGhostUpdateTime, 1, vtkCommunicator::SUM_OP, 0);
avgGhostUpdateTime /= static_cast<double>(nbRanks);
vtkMPIUtilities::Printf(controller.Get(),
"-- Ellapsed Time: min=%f, avg=%f, max=%f\n",
minGhostUpdateTime, avgGhostUpdateTime, maxGhostUpdateTime);
}
vtkIdType initialNbOfCells = initialGrid->GetNumberOfCells();
if (outGrids[0]->GetNumberOfCells() != outGrids[1]->GetNumberOfCells())
{
vtkMPIUtilities::Printf(controller.Get(),
"Grids obtained with and without global ids do not have the same number of cells!\n");
ret = EXIT_FAILURE;
}
for (int step = 0; step < 2; ++step)
{
vtkUnsignedCharArray* ghosts = vtkUnsignedCharArray::SafeDownCast(
outGrids[step]->GetCellGhostArray());
if (initialNbOfCells >= outGrids[step]->GetNumberOfCells())
for(int step = 0; step < 2; ++step)
{
ghostGenerator->SetUseGlobalPointIds(step == 0 ? 1 : 0);
vtkNew<vtkTimerLog> timer;
timer->StartTimer();
ghostGenerator->UpdatePiece(rankId, nbRanks, ghostLevel);
timer->StopTimer();
// Save the grid for further analysis
outGrids[step] = ghostGenerator->GetOutput();
outGrids[step]->Register(0);
double elapsed = timer->GetElapsedTime();
// get some performance statistics
double minGhostUpdateTime = 0.0;
double maxGhostUpdateTime = 0.0;
double avgGhostUpdateTime = 0.0;
controller->Reduce(&elapsed, &minGhostUpdateTime, 1, vtkCommunicator::MIN_OP, 0);
controller->Reduce(&elapsed, &maxGhostUpdateTime, 1, vtkCommunicator::MAX_OP, 0);
controller->Reduce(&elapsed, &avgGhostUpdateTime, 1, vtkCommunicator::SUM_OP, 0);
avgGhostUpdateTime /= static_cast<double>(nbRanks);
vtkMPIUtilities::Printf(controller.Get(),
"Obtained grids has less or as many cells as the input grid!\n");
ret = EXIT_FAILURE;
"-- Ghost Level: %i Elapsed Time: min=%f, avg=%f, max=%f\n",
ghostLevel, minGhostUpdateTime, avgGhostUpdateTime, maxGhostUpdateTime);
}
if (!ghosts)
vtkIdType initialNbOfCells = initialGrid->GetNumberOfCells();
if (outGrids[0]->GetNumberOfCells() != outGrids[1]->GetNumberOfCells())
{
vtkMPIUtilities::Printf(controller.Get(),
"Ghost cells array not found at step %d!\n", step);
"Grids obtained with and without global ids for ghost level %i do not have the same number of cells!\n",
ghostLevel);
ret = EXIT_FAILURE;
continue;
}
for (vtkIdType i = 0; i < ghosts->GetNumberOfTuples(); ++i)
for (int step = 0; step < 2; ++step)
{
unsigned char val = ghosts->GetValue(i);
if (i < initialNbOfCells && val != 0)
vtkUnsignedCharArray* ghosts = vtkUnsignedCharArray::SafeDownCast(
outGrids[step]->GetCellGhostArray());
if (initialNbOfCells >= outGrids[step]->GetNumberOfCells())
{
vtkMPIUtilities::Printf(controller.Get(),
"Cell %d is not supposed to be a ghost cell but it is!\n", i);
"Obtained grids for ghost level %i has less or as many cells as the input grid!\n",
ghostLevel);
ret = EXIT_FAILURE;
break;
}
if (i >= initialNbOfCells && val != 1)
if (!ghosts)
{
vtkMPIUtilities::Printf(controller.Get(),
"Cell %d is supposed to be a ghost cell but it's not!\n", i);
"Ghost cells array not found at ghost level %i, step %d!\n",
ghostLevel, step);
ret = EXIT_FAILURE;
break;
continue;
}
for (vtkIdType i = 0; i < ghosts->GetNumberOfTuples(); ++i)
{
unsigned char val = ghosts->GetValue(i);
if (i < initialNbOfCells && val != 0)
{
vtkMPIUtilities::Printf(controller.Get(),
"Ghost Level %i Cell %d is not supposed to be a ghost cell but it is!\n",
ghostLevel, i);
ret = EXIT_FAILURE;
break;
}
if (i >= initialNbOfCells && val != 1)
{
vtkMPIUtilities::Printf(controller.Get(),
"Ghost Level %i Cell %d is supposed to be a ghost cell but it's not!\n",
ghostLevel, i);
ret = EXIT_FAILURE;
break;
}
}
}
outGrids[0]->Delete();
outGrids[1]->Delete();
}
outGrids[0]->Delete();
outGrids[1]->Delete();
controller->Finalize();
return ret;
......
......@@ -33,10 +33,11 @@
#include "vtkPoints.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkUnstructuredGrid.h"
#include "vtkCellData.h"
#include <vector>
#include <map>
#include <set>
#include <vector>
//----------------------------------------------------------------------------
// Helpers
......@@ -124,17 +125,28 @@ struct vtkPUnstructuredGridGhostCellsGenerator::vtkInternals
std::vector<vtkIdType> AllSizes;
std::vector<vtkIdType> AllOffsets;
std::map<int, std::set<vtkIdType> > NeighborRanksCells;
std::map<int, CommDataInfo> CommData;
vtkUnstructuredGridBase* Input;
vtkSmartPointer <vtkUnstructuredGrid> CurGrid;
vtkDataArray* InputGlobalPointIds;
bool UseGlobalPointIds;
// cells that need to be sent to a given proc
std::map<int, std::set<vtkIdType> > CellsToSend;
// cells that have been sent to a given proc over the entire time
std::map<int, std::set<vtkIdType> > SentCells;
// cells that were sent to a proc during the last round,
// a "round" is receiving one layer of ghost cells
std::map<int, std::set<vtkIdType> > SentCellsLastRound;
};
static const int UGGCG_SIZE_EXCHANGE_TAG = 9000;
static const int UGGCG_DATA_EXCHANGE_TAG = 9001;
static const char* UGGCG_GLOBAL_POINT_IDS = "GlobalNodeIds";
static const char* UGGCG_GLOBAL_CELL_IDS = "GlobalNodeIds";
//----------------------------------------------------------------------------
......@@ -149,10 +161,15 @@ vtkPUnstructuredGridGhostCellsGenerator::vtkPUnstructuredGridGhostCellsGenerator
this->SetController(vtkMultiProcessController::GetGlobalController());
this->Internals = NULL;
this->UseGlobalPointIds = true;
this->BuildIfRequired = true;
this->UseGlobalPointIds = true;
this->GlobalPointIdsArrayName = NULL;
this->SetGlobalPointIdsArrayName(UGGCG_GLOBAL_POINT_IDS);
this->HasGlobalCellIds = false;
this->GlobalCellIdsArrayName = NULL;
this->SetGlobalCellIdsArrayName(UGGCG_GLOBAL_CELL_IDS);
}
//----------------------------------------------------------------------------
......@@ -160,6 +177,7 @@ vtkPUnstructuredGridGhostCellsGenerator::~vtkPUnstructuredGridGhostCellsGenerato
{
this->SetController(NULL);
this->SetGlobalPointIdsArrayName(NULL);
this->SetGlobalCellIdsArrayName(NULL);
delete this->Internals;
this->Internals = 0;
......@@ -172,6 +190,8 @@ void vtkPUnstructuredGridGhostCellsGenerator::PrintSelf(ostream& os, vtkIndent i
os << indent << "UseGlobalPointIds:" << UseGlobalPointIds << endl;
os << indent << "GlobalPointIdsArrayName:" << GlobalPointIdsArrayName << endl;
os << indent << "HasGlobalCellIds:" << HasGlobalCellIds << endl;
os << indent << "GlobalCellIdsArrayName:" << GlobalCellIdsArrayName << endl;
os << indent << "BuildIfRequired:" << BuildIfRequired << endl;
}
......@@ -212,10 +232,10 @@ int vtkPUnstructuredGridGhostCellsGenerator::RequestData(
this->NumRanks = this->Controller ? this->Controller->GetNumberOfProcesses() : 1;
this->RankId = this->Controller ? this->Controller->GetLocalProcessId() : 0;
int ghostLevels = this->BuildIfRequired ? outInfo->Get(
int maxGhostLevel = this->BuildIfRequired ? outInfo->Get(
vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS()) : 1;
if (ghostLevels == 0 || !this->Controller || this->NumRanks == 1)
if (maxGhostLevel == 0 || !this->Controller || this->NumRanks == 1)
{
vtkDebugMacro(<< "Ghost levels are not requested. Nothing more to do.");
output->ShallowCopy(input);
......@@ -228,7 +248,7 @@ int vtkPUnstructuredGridGhostCellsGenerator::RequestData(
vtkPointData *inputPD = input->GetPointData();
this->Internals->InputGlobalPointIds = inputPD->GetGlobalIds();
vtkUnstructuredGridBase* inputGridCopy = NULL;
vtkUnstructuredGridBase *inputGridCopy = NULL;
if (!this->Internals->InputGlobalPointIds)
{
......@@ -252,19 +272,72 @@ int vtkPUnstructuredGridGhostCellsGenerator::RequestData(
{
this->Internals->InputGlobalPointIds = NULL;
}
this->ExtractAndReduceSurfacePoints();
this->UpdateProgress(0.3);
this->ComputeSharedPoints();
this->UpdateProgress(0.6);
// ensure that global cell ids array is there if specified.
// only need global cell ids when more than one ghost layer is needed
if (maxGhostLevel > 1)
{
if (this->HasGlobalCellIds)
{
vtkCellData *inputCD = input->GetCellData();
if (!inputCD->GetGlobalIds())
{
vtkDataArray *globalCellIdsArray = inputCD->GetArray(
this->GlobalCellIdsArrayName);
if (globalCellIdsArray == NULL)
{
this->SetHasGlobalCellIds(false);
}
else
{
inputCD->SetGlobalIds(globalCellIdsArray);
}
}
else
{
// make sure GlobalCellIdsArrayName is correct
this->SetGlobalCellIdsArrayName(inputCD->GetGlobalIds()->GetName());
}
}
// ensure that everyone has the same value of HasGlobalCellIds
int hasGlobalCellIds = this->HasGlobalCellIds != 0 ? 1 : 0;
int allHasGlobalCellIds;
this->Controller->AllReduce(&hasGlobalCellIds, &allHasGlobalCellIds, 1,
vtkCommunicator::MIN_OP);
if (!allHasGlobalCellIds)
{
this->HasGlobalCellIds = false;
}
}
// add global cell ids if necessary
if (!this->HasGlobalCellIds && maxGhostLevel > 1)
{
this->AddGlobalCellIds();
}
// obtain first level of ghost cells
this->Internals->CurGrid = vtkSmartPointer<vtkUnstructuredGrid>::New();
this->GetFirstGhostLayer(maxGhostLevel, this->Internals->CurGrid);
this->ExtractAndSendGhostCells();
this->UpdateProgress(0.8);
// add additional ghost layers one at a time
for (int i=1; i<maxGhostLevel; i++)
{
this->Controller->Barrier();
this->AddGhostLayer(i+1, maxGhostLevel);
}
this->ReceiveAndMergeGhostCells(output);
this->UpdateProgress(1.0);
// remove global cell ids if they were added internally
if (!this->HasGlobalCellIds && maxGhostLevel > 1)
{
this->RemoveGlobalCellIds();
}
output->GetInformation()->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 1);
// set the output
output->ShallowCopy(this->Internals->CurGrid);
output->GetInformation()->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(),
maxGhostLevel);
this->Controller->Barrier();
......@@ -278,6 +351,30 @@ int vtkPUnstructuredGridGhostCellsGenerator::RequestData(
return 1;
}
//-----------------------------------------------------------------------------
//Get the first layer of ghost cells
void vtkPUnstructuredGridGhostCellsGenerator::GetFirstGhostLayer(
int maxGhostLevel, vtkUnstructuredGrid *output)
{
this->ExtractAndReduceSurfacePoints();
this->UpdateProgress(1.0 / (3.0 * maxGhostLevel));
this->ComputeSharedPoints();
this->UpdateProgress(2.0 / (3.0 * maxGhostLevel));
this->ExtractAndSendGhostCells(this->Internals->Input);
this->UpdateProgress(2.5 / (3.0 * maxGhostLevel));
// Shallow copy the input grid and initialize the ghost arrays
vtkNew<vtkUnstructuredGrid> inputCopy;
inputCopy->ShallowCopy(this->Internals->Input);
inputCopy->AllocatePointGhostArray();
inputCopy->AllocateCellGhostArray();
this->ReceiveAndMergeGhostCells(maxGhostLevel, inputCopy.Get(), output);
this->UpdateProgress(3.0 / (3.0 * maxGhostLevel));
}
//-----------------------------------------------------------------------------
// Step 1: Extract surface geometry and all reduce global ids of surface points
void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndReduceSurfacePoints()
......@@ -288,13 +385,13 @@ void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndReduceSurfacePoints()
surfaceFilter->PassThroughPointIdsOn();
surfaceFilter->Update();
vtkPolyData* surface = surfaceFilter->GetOutput();
vtkPolyData *surface = surfaceFilter->GetOutput();
vtkIdType nbSurfacePoints = surface->GetNumberOfPoints();
vtkCellArray* surfaceCells = surface->GetPolys();
vtkCellArray *surfaceCells = surface->GetPolys();
surfaceCells->InitTraversal();
vtkIdType npts, *pts;
vtkIdTypeArray* surfaceOriginalPointIds = vtkIdTypeArray::SafeDownCast(
vtkIdTypeArray *surfaceOriginalPointIds = vtkIdTypeArray::SafeDownCast(
surface->GetPointData()->GetArray(surfaceFilter->GetOriginalPointIdsName()));
if (this->Internals->InputGlobalPointIds)
......@@ -329,7 +426,7 @@ void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndReduceSurfacePoints()
else
{
// We can't use global ids, so we will process point coordinates instead
vtkPoints* inputPoints = this->Internals->Input->GetPoints();
vtkPoints *inputPoints = this->Internals->Input->GetPoints();
vtkNew<vtkPoints> surfacePoints;
surfacePoints->SetDataTypeToDouble();
surfacePoints->Allocate(nbSurfacePoints);
......@@ -428,7 +525,9 @@ void vtkPUnstructuredGridGhostCellsGenerator::ComputeSharedPoints()
// Add those cells to the list of cells to send to this rank
for (vtkIdType k = 0; k < nbIds; k++)
{
this->Internals->NeighborRanksCells[i].insert(cellIdsList->GetId(k));
this->Internals->CellsToSend[i].insert(cellIdsList->GetId(k));
this->Internals->SentCellsLastRound[i].insert(cellIdsList->GetId(k));
this->Internals->SentCells[i].insert(cellIdsList->GetId(k));
}
}
}
......@@ -445,19 +544,18 @@ void vtkPUnstructuredGridGhostCellsGenerator::ComputeSharedPoints()
//-----------------------------------------------------------------------------
// Step 3: extract and send the ghost cells to the neighbor ranks
void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndSendGhostCells()
void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndSendGhostCells(
vtkUnstructuredGridBase* input)
{
vtkNew<vtkIdList> cellIdsList;
vtkNew<vtkExtractCells> extractCells;
extractCells->SetInputData(this->Internals->Input);
std::map<int, std::set<vtkIdType> >::iterator iter =
this->Internals->NeighborRanksCells.begin();
extractCells->SetInputData(input);
vtkMPICommunicator* com =
vtkMPICommunicator *com =
vtkMPICommunicator::SafeDownCast(this->Controller->GetCommunicator());
// Browse all neighbor ranks and extract the cells connected to the points we share
for (; iter != this->Internals->NeighborRanksCells.end(); ++iter)
std::map<int, std::set<vtkIdType> >::iterator iter = this->Internals->CellsToSend.begin();
for (; iter != this->Internals->CellsToSend.end(); ++iter)
{
int toRank = iter->first;
std::set<vtkIdType>& cellsToShare = iter->second;
......@@ -469,7 +567,7 @@ void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndSendGhostCells()
}
extractCells->SetCellList(cellIdsList.Get());
extractCells->Update();
vtkUnstructuredGrid* extractGrid = extractCells->GetOutput();
vtkUnstructuredGrid *extractGrid = extractCells->GetOutput();
// Send the extracted grid to the neighbor rank asynchronously
CommDataInfo& c = this->Internals->CommData[toRank];
......@@ -477,37 +575,48 @@ void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndSendGhostCells()
{
c.SendLen = c.SendBuffer->GetNumberOfTuples();
// Send data length
com->NoBlockSend(&c.SendLen, 1, toRank, UGGCG_SIZE_EXCHANGE_TAG, c.SendReqs[0]);
com->NoBlockSend(&c.SendLen, 1, toRank, UGGCG_SIZE_EXCHANGE_TAG,
c.SendReqs[0]);
// Send raw data
com->NoBlockSend((char*)c.SendBuffer->GetVoidPointer(0), c.SendLen, toRank,
UGGCG_DATA_EXCHANGE_TAG, c.SendReqs[1]);
com->NoBlockSend((char*)c.SendBuffer->GetVoidPointer(0), c.SendLen,
toRank, UGGCG_DATA_EXCHANGE_TAG, c.SendReqs[1]);
}
}
}
//-----------------------------------------------------------------------------
// Step 4: receive the ghost cells from the neighbor ranks and merge them
// Step 4: Receive the ghost cells from the neighbor ranks and merge them
// to the local grid.
// Argument output should be an empty unstructured grid.
void vtkPUnstructuredGridGhostCellsGenerator::ReceiveAndMergeGhostCells(
int maxGhostLevel, vtkUnstructuredGridBase *curGrid,
vtkUnstructuredGrid *output)
{
// We need to compute a rough estimation of the total number of cells and
// points for vtkMergeCells
vtkIdType totalNbCells = this->Internals->Input->GetNumberOfCells();
vtkIdType totalNbPoints = this->Internals->Input->GetNumberOfPoints();
// reset CommStep
std::map<int, CommDataInfo >::iterator comIter =
this->Internals->CommData.begin();
for (; comIter != this->Internals->CommData.end(); ++comIter)
{
comIter->second.CommStep = 0;
}
vtkMPICommunicator* com =
vtkMPICommunicator *com =
vtkMPICommunicator::SafeDownCast(this->Controller->GetCommunicator());
// We need to compute a rough estimation of the total number of cells and
// points for vtkMergeCells
vtkIdType totalNbCells = curGrid->GetNumberOfCells();
vtkIdType totalNbPoints = curGrid->GetNumberOfPoints();
// Browse all neighbor ranks and receive the mesh that contains cells
int nbNeighbors = static_cast<int>(this->Internals->NeighborRanksCells.size());
int nbNeighbors = static_cast<int>(this->Internals->CellsToSend.size());
std::vector<vtkUnstructuredGridBase*> neighborGrids;
neighborGrids.reserve(nbNeighbors);
// First create requests to receive the size of the mesh to receive
std::map<int, std::set<vtkIdType> >::iterator iter;
for (iter = this->Internals->NeighborRanksCells.begin();
iter != this->Internals->NeighborRanksCells.end(); ++iter)
std::map<int, std::set<vtkIdType> >::iterator iter = this->Internals->CellsToSend.begin();
for (; iter != this->Internals->CellsToSend.end(); ++iter)
{
vtkIdType fromRank = iter->first;
CommDataInfo& c = this->Internals->CommData[fromRank];
......@@ -515,12 +624,13 @@ void vtkPUnstructuredGridGhostCellsGenerator::ReceiveAndMergeGhostCells(
&c.RecvLen, 1, fromRank, UGGCG_SIZE_EXCHANGE_TAG, c.RecvReqs[0]);
}
// Then, once the data length is received, create requests to receive the mesh data
// Then, once the data length is received, create requests to receive the
// mesh data
int counter = 0;
while (counter != nbNeighbors)
{
for (iter = this->Internals->NeighborRanksCells.begin();
iter != this->Internals->NeighborRanksCells.end(); ++iter)
iter = this->Internals->CellsToSend.begin();
for (; iter != this->Internals->CellsToSend.end(); ++iter)
{
vtkIdType fromRank = iter->first;
CommDataInfo& c = this->Internals->CommData[fromRank];
......@@ -542,8 +652,8 @@ void vtkPUnstructuredGridGhostCellsGenerator::ReceiveAndMergeGhostCells(
counter = 0;
while (counter != nbNeighbors)
{
for (iter = this->Internals->NeighborRanksCells.begin();
iter != this->Internals->NeighborRanksCells.end(); ++iter)
iter = this->Internals->CellsToSend.begin();
for (; iter != this->Internals->CellsToSend.end(); ++iter)
{
vtkIdType fromRank = iter->first;
CommDataInfo& c = this->Internals->CommData[fromRank];
......@@ -554,14 +664,21 @@ void vtkPUnstructuredGridGhostCellsGenerator::ReceiveAndMergeGhostCells(
}
c.CommStep = 2;
vtkUnstructuredGrid* grid = vtkUnstructuredGrid::New();
vtkUnstructuredGrid *grid = vtkUnstructuredGrid::New();
vtkCommunicator::UnMarshalDataObject(c.RecvBuffer, grid);
// delete RecvBuffer, and allocate empty arrays
// just in case they are used again.
c.RecvBuffer->Delete();
c.RecvBuffer = NULL;
c.RecvBuffer = vtkCharArray::New();
if (!grid->HasAnyGhostCells())
{
grid->AllocatePointGhostArray();
grid->AllocateCellGhostArray();
}
// Flag the received grid elements as ghosts
grid->AllocatePointGhostArray();
grid->AllocateCellGhostArray();
grid->GetPointGhostArray()->FillComponent(0, 1);
grid->GetCellGhostArray()->FillComponent(0, 1);
......@@ -573,6 +690,17 @@ void vtkPUnstructuredGridGhostCellsGenerator::ReceiveAndMergeGhostCells(
this->Internals->InputGlobalPointIds->GetName()));
}
// Checking maxGhostLevel to see if global cell ids are needed.
// If so, make sure the global cell ids array is tagged accordingly
if (maxGhostLevel > 1)
{
if (!grid->GetCellData()->GetGlobalIds())
{
grid->GetCellData()->SetGlobalIds(grid->GetCellData()->GetArray(
this->GlobalCellIdsArrayName));
}
}
totalNbCells += grid->GetNumberOfCells();
totalNbPoints += grid->GetNumberOfPoints();
......@@ -582,32 +710,27 @@ void vtkPUnstructuredGridGhostCellsGenerator::ReceiveAndMergeGhostCells(
}
}
// Shallow copy the input grid and initialize the ghost arrays
vtkNew<vtkUnstructuredGrid> inputCopy;
inputCopy->ShallowCopy(this->Internals->Input);
inputCopy->AllocatePointGhostArray();
inputCopy->AllocateCellGhostArray();
if (totalNbCells == 0)
{
output->ShallowCopy(inputCopy.Get());