]> SALOME platform Git repositories - modules/paravis.git/commitdiff
Salome HOME
Addition of GhostCellsGenerator filter to avoid artefacts linked to // visualizations.
authorAnthony Geay <anthony.geay@edf.fr>
Mon, 4 Jan 2016 07:31:30 +0000 (08:31 +0100)
committerAnthony Geay <anthony.geay@edf.fr>
Mon, 4 Jan 2016 07:31:30 +0000 (08:31 +0100)
src/Plugins/CMakeLists.txt
src/Plugins/GhostCellsGenerator/CMakeLists.txt [new file with mode: 0644]
src/Plugins/GhostCellsGenerator/GhostCellsGenerator.xml [new file with mode: 0644]
src/Plugins/GhostCellsGenerator/vtkPUnstructuredGridGhostCellsGenerator.cxx [new file with mode: 0644]
src/Plugins/GhostCellsGenerator/vtkPUnstructuredGridGhostCellsGenerator.h [new file with mode: 0644]
src/Plugins/GhostCellsGenerator/vtkPVUnstructuredGridGhostCellsGenerator.cxx [new file with mode: 0644]
src/Plugins/GhostCellsGenerator/vtkPVUnstructuredGridGhostCellsGenerator.h [new file with mode: 0644]

index ff1b52b3cda603031de308ddad5c125cd2e818fe..8fca10f7339a49190f06a97a311146a4155a4f83 100755 (executable)
@@ -23,6 +23,7 @@ SET(_subdirs
   MEDReader
 #  TableReader
   ElevationSurface
+  GhostCellsGenerator
   ScaleVector
   EllipseBuilder
   DifferenceTimesteps
diff --git a/src/Plugins/GhostCellsGenerator/CMakeLists.txt b/src/Plugins/GhostCellsGenerator/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d66a945
--- /dev/null
@@ -0,0 +1,23 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+
+PROJECT(GhostCellsGenerator)
+
+FIND_PACKAGE(ParaView REQUIRED)
+INCLUDE(${PARAVIEW_USE_FILE})
+
+IF(PARAVIEW_USE_MPI)
+# Necessary while this class is not in VTK
+  SET(SOURCES vtkPUnstructuredGridGhostCellsGenerator.cxx)
+ENDIF(PARAVIEW_USE_MPI)
+
+ADD_PARAVIEW_PLUGIN(GhostCellsGenerator "1.0"
+  SERVER_MANAGER_SOURCES vtkPVUnstructuredGridGhostCellsGenerator.cxx
+  SERVER_MANAGER_XML GhostCellsGenerator.xml
+  SOURCES ${SOURCES}
+  REQUIRED_ON_SERVER)
+
+INSTALL( TARGETS GhostCellsGenerator 
+  RUNTIME DESTINATION lib/paraview
+  LIBRARY DESTINATION lib/paraview
+  ARCHIVE DESTINATION lib/paraview
+  )
diff --git a/src/Plugins/GhostCellsGenerator/GhostCellsGenerator.xml b/src/Plugins/GhostCellsGenerator/GhostCellsGenerator.xml
new file mode 100644 (file)
index 0000000..f6990b5
--- /dev/null
@@ -0,0 +1,44 @@
+<ServerManagerConfiguration>
+  <ProxyGroup name="filters">
+    <SourceProxy class="vtkPVUnstructuredGridGhostCellsGenerator"
+                 label="Generate Ghost Cells"
+                 name="GhostCellGenerator">
+      <Documentation long_help="Generate ghost cells for unstructured grids. Global point ids array is required.">
+      </Documentation>
+      <InputProperty command="SetInputConnection"
+                     name="Input">
+        <ProxyGroupDomain name="groups">
+          <Group name="sources" />
+          <Group name="filters" />
+        </ProxyGroupDomain>
+        <DataTypeDomain name="input_type">
+          <DataType value="vtkUnstructuredGrid" />
+          <DataType value="vtkCompositeDataSet" />
+        </DataTypeDomain>
+        <Documentation>This property specifies the input to the ghost cells generator.</Documentation>
+      </InputProperty>
+      <IntVectorProperty command="SetUseGlobalPointIds"
+                         default_values="1"
+                         name="UseGlobalIds"
+                         number_of_elements="1"
+                         panel_visibility="default">
+        <Documentation>Specify if the filter must take benefit of global point ids if they exist or if
+          point coordinates should be used instead.</Documentation>
+        <BooleanDomain name="bool" />
+      </IntVectorProperty>
+      <StringVectorProperty command="SetGlobalPointIdsArrayName"
+                            default_values="GlobalNodeIds"
+                            name="GlobalPointIdsArrayName"
+                            number_of_elements="1"
+                            panel_visibility="default">
+        <Documentation>This property provides a name for the input array
+        containing the global point ids if the GlobalIds array of the point data if not set.</Documentation>
+        <Hints>
+          <PropertyWidgetDecorator type="ShowWidgetDecorator">
+            <Property name="UseGlobalIds" function="boolean" />
+          </PropertyWidgetDecorator>
+        </Hints>
+      </StringVectorProperty>
+    </SourceProxy>
+  </ProxyGroup>
+</ServerManagerConfiguration>
diff --git a/src/Plugins/GhostCellsGenerator/vtkPUnstructuredGridGhostCellsGenerator.cxx b/src/Plugins/GhostCellsGenerator/vtkPUnstructuredGridGhostCellsGenerator.cxx
new file mode 100644 (file)
index 0000000..7cfcf9e
--- /dev/null
@@ -0,0 +1,581 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkPUnstructuredGridGhostCellsGenerator.cxx
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#include "vtkPUnstructuredGridGhostCellsGenerator.h"
+
+#include "vtkCellArray.h"
+#include "vtkCharArray.h"
+#include "vtkDataSetSurfaceFilter.h"
+#include "vtkExtractCells.h"
+#include "vtkIdList.h"
+#include "vtkIdTypeArray.h"
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkMergeCells.h"
+#include "vtkMergePoints.h"
+#include "vtkMPICommunicator.h"
+#include "vtkMultiProcessController.h"
+#include "vtkNew.h"
+#include "vtkObjectFactory.h"
+#include "vtkPointData.h"
+#include "vtkPoints.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkUnstructuredGrid.h"
+
+#include <map>
+#include <set>
+#include <vector>
+
+//----------------------------------------------------------------------------
+// Helpers
+namespace
+{
+template<class T>
+bool AllGatherV(vtkMultiProcessController* controller,
+                const T* localV,
+                vtkIdType localSize,
+                std::vector<T>& globalV,
+                std::vector<vtkIdType>& sizes,
+                std::vector<vtkIdType>& offsets)
+{
+  int nbOfRanks = controller->GetNumberOfProcesses();
+  sizes.resize(nbOfRanks);
+  int ret = controller->AllGather(&localSize, &sizes[0], 1);
+  if (ret == 0)
+    {
+    vtkErrorWithObjectMacro(controller, << "Communication error!");
+    return false;
+    }
+  vtkIdType count = 0;
+  offsets.resize(nbOfRanks);
+  for (int i = 0; i < nbOfRanks; i++)
+    {
+    offsets[i] = count;
+    count += sizes[i];
+    }
+  globalV.resize(count);
+  if (count > 0)
+    {
+    controller->AllGatherV(localSize > 0 ? localV : 0,
+      &globalV[0], localSize, &sizes[0], &offsets[0]);
+    }
+  return true;
+}
+}
+
+//----------------------------------------------------------------------------
+// Internal data structures
+
+// Class to hold asynchronous communication information
+class CommDataInfo
+{
+public:
+  CommDataInfo() : SendLen(-1), RecvLen(-1), CommStep(0)
+  {
+    this->SendBuffer = vtkCharArray::New();
+    this->RecvBuffer = vtkCharArray::New();
+  }
+
+  CommDataInfo(const CommDataInfo& c)
+  {
+    *this = c;
+    if (this->SendBuffer) { this->SendBuffer->Register(0); }
+    if (this->RecvBuffer) { this->RecvBuffer->Register(0); }
+  }
+
+  ~CommDataInfo()
+  {
+    if (this->SendBuffer) { this->SendBuffer->Delete(); }
+    if (this->RecvBuffer) { this->RecvBuffer->Delete(); }
+  }
+
+  vtkMPICommunicator::Request SendReqs[2];
+  vtkMPICommunicator::Request RecvReqs[2];
+  vtkCharArray *SendBuffer;
+  vtkCharArray *RecvBuffer;
+  vtkIdType SendLen;
+  vtkIdType RecvLen;
+  int CommStep;
+};
+
+// Communication arrays
+struct vtkPUnstructuredGridGhostCellsGenerator::vtkInternals
+{
+  // For global ids
+  std::map<vtkIdType, vtkIdType> GlobalToLocalPointIdMap;
+  std::vector<vtkIdType> AllGlobalIdsOfSurfacePoints;
+
+  // For point coordinates
+  vtkNew<vtkMergePoints> LocalPoints;
+  std::vector<vtkIdType> LocalPointsMap;
+  std::vector<double> AllPointsOfSurfacePoints;
+
+  std::vector<vtkIdType> AllSizes;
+  std::vector<vtkIdType> AllOffsets;
+  std::map<int, std::set<vtkIdType> > NeighborRanksCells;
+  std::map<int, CommDataInfo> CommData;
+  vtkUnstructuredGridBase* Input;
+
+  vtkDataArray* InputGlobalPointIds;
+  bool UseGlobalPointIds;
+};
+
+static const int UGGCG_SIZE_EXCHANGE_TAG = 9000;
+static const int UGGCG_DATA_EXCHANGE_TAG = 9001;
+static const char* UGGCG_GLOBAL_POINT_IDS = "GlobalNodeIds";
+
+//----------------------------------------------------------------------------
+
+vtkStandardNewMacro(vtkPUnstructuredGridGhostCellsGenerator)
+vtkSetObjectImplementationMacro(
+  vtkPUnstructuredGridGhostCellsGenerator, Controller, vtkMultiProcessController);
+
+//----------------------------------------------------------------------------
+vtkPUnstructuredGridGhostCellsGenerator::vtkPUnstructuredGridGhostCellsGenerator()
+{
+  this->Controller = NULL;
+  this->SetController(vtkMultiProcessController::GetGlobalController());
+
+  this->Internals = NULL;
+  this->GlobalPointIdsArrayName = NULL;
+  this->UseGlobalPointIds = true;
+  this->SetGlobalPointIdsArrayName(UGGCG_GLOBAL_POINT_IDS);
+}
+
+//----------------------------------------------------------------------------
+vtkPUnstructuredGridGhostCellsGenerator::~vtkPUnstructuredGridGhostCellsGenerator()
+{
+  this->SetController(NULL);
+  this->SetGlobalPointIdsArrayName(NULL);
+
+  delete this->Internals;
+  this->Internals = 0;
+}
+
+//-----------------------------------------------------------------------------
+void vtkPUnstructuredGridGhostCellsGenerator::PrintSelf(ostream& os, vtkIndent indent)
+{
+  Superclass::PrintSelf(os, indent);
+}
+
+//-----------------------------------------------------------------------------
+int vtkPUnstructuredGridGhostCellsGenerator::RequestData(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **inputVector,
+  vtkInformationVector *outputVector)
+{
+  // get the info objects
+  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  // get the input and output. Input may just have the UnstructuredGridBase
+  // interface, but output should be an unstructured grid.
+  vtkUnstructuredGridBase *input = vtkUnstructuredGridBase::SafeDownCast(
+    inInfo->Get(vtkDataObject::DATA_OBJECT()));
+  vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
+    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+
+  int ghostLevels = 1;
+  //ghostLevels = outInfo->Get(
+  //  vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
+
+  if (!this->Controller)
+    {
+    this->Controller = vtkMultiProcessController::GetGlobalController();
+    }
+  output->Reset();
+
+  this->NumRanks = this->Controller ? this->Controller->GetNumberOfProcesses() : 1;
+  this->RankId = this->Controller ? this->Controller->GetLocalProcessId() : 0;
+  if (ghostLevels == 0 || !this->Controller || this->NumRanks == 1)
+    {
+    // Ghost levels are not requested. Nothing to do but pass the dataset.
+    if (this->RankId == 0)
+      {
+      vtkWarningMacro(<< "Ghost cells not requested or not needed.");
+      }
+    output->ShallowCopy(input);
+    return 1;
+    }
+
+  delete this->Internals;
+  this->Internals = new vtkPUnstructuredGridGhostCellsGenerator::vtkInternals();
+  this->Internals->Input = input;
+
+  vtkPointData *inputPD = input->GetPointData();
+  this->Internals->InputGlobalPointIds = inputPD->GetGlobalIds();
+
+  if (!this->Internals->InputGlobalPointIds)
+    {
+    this->Internals->InputGlobalPointIds =
+      inputPD->GetArray(this->GlobalPointIdsArrayName);
+    inputPD->SetGlobalIds(this->Internals->InputGlobalPointIds);
+    }
+
+  if (!this->UseGlobalPointIds)
+    {
+    this->Internals->InputGlobalPointIds = NULL;
+    }
+
+  this->ExtractAndReduceSurfacePoints();
+  this->UpdateProgress(0.3);
+
+  this->ComputeSharedPoints();
+  this->UpdateProgress(0.6);
+
+  this->ExtractAndSendGhostCells();
+  this->UpdateProgress(0.8);
+
+  this->ReceiveAndMergeGhostCells(output);
+  this->UpdateProgress(1.0);
+
+  output->GetInformation()->Set(vtkDataObject::DATA_NUMBER_OF_GHOST_LEVELS(), 1);
+
+  this->Controller->Barrier();
+
+  delete this->Internals;
+  this->Internals = 0;
+
+  return 1;
+}
+
+//-----------------------------------------------------------------------------
+// Step 1: Extract surface geometry and all reduce global ids of surface points
+void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndReduceSurfacePoints()
+{
+  // Extract boundary cells and points with the surface filter
+  vtkNew<vtkDataSetSurfaceFilter> surfaceFilter;
+  surfaceFilter->SetInputData(this->Internals->Input);
+  surfaceFilter->PassThroughPointIdsOn();
+  surfaceFilter->Update();
+
+  vtkPolyData* surface = surfaceFilter->GetOutput();
+  vtkIdType nbSurfacePoints = surface->GetNumberOfPoints();
+  vtkCellArray* surfaceCells = surface->GetPolys();
+  surfaceCells->InitTraversal();
+  vtkIdType npts, *pts;
+
+  vtkIdTypeArray* surfaceOriginalPointIds = vtkIdTypeArray::SafeDownCast(
+    surface->GetPointData()->GetArray(surfaceFilter->GetOriginalPointIdsName()));
+
+  if (this->Internals->InputGlobalPointIds)
+    {
+    std::vector<vtkIdType> globalIdsOfSurfacePoints;
+    globalIdsOfSurfacePoints.reserve(nbSurfacePoints);
+
+    // Browse surface cells and save global and local ids of cell points
+    while (surfaceCells->GetNextCell(npts, pts))
+      {
+      for (vtkIdType i = 0; i < npts; i++)
+        {
+        vtkIdType origPtId = surfaceOriginalPointIds->GetValue(pts[i]);
+        vtkIdType globalPtId = static_cast<vtkIdType>(
+          this->Internals->InputGlobalPointIds->GetTuple1(origPtId));
+
+        if (this->Internals->GlobalToLocalPointIdMap.find(globalPtId) ==
+          this->Internals->GlobalToLocalPointIdMap.end())
+          {
+          this->Internals->GlobalToLocalPointIdMap[globalPtId] = origPtId;
+          globalIdsOfSurfacePoints.push_back(globalPtId);
+          }
+        }
+      }
+
+    // Now reduce surface point global ids on ALL ranks
+    ::AllGatherV(this->Controller, &globalIdsOfSurfacePoints[0],
+      globalIdsOfSurfacePoints.size(),
+      this->Internals->AllGlobalIdsOfSurfacePoints,
+      this->Internals->AllSizes, this->Internals->AllOffsets);
+    }
+  else
+    {
+    // We can't use global ids, so we will process point coordinates instead
+    vtkPoints* inputPoints = this->Internals->Input->GetPoints();
+    vtkNew<vtkPoints> surfacePoints;
+    surfacePoints->SetDataTypeToDouble();
+    surfacePoints->Allocate(nbSurfacePoints);
+    this->Internals->LocalPoints->InitPointInsertion(
+      surfacePoints.Get(), surface->GetPoints()->GetBounds());
+    this->Internals->LocalPointsMap.reserve(nbSurfacePoints);
+
+    // Browse surface cells and push point coordinates to the locator
+    while (surfaceCells->GetNextCell(npts, pts))
+      {
+      for (vtkIdType i = 0; i < npts; i++)
+        {
+        vtkIdType origPtId = surfaceOriginalPointIds->GetValue(pts[i]);
+        double p[3];
+        inputPoints->GetPoint(origPtId, p);
+        vtkIdType sid;
+        if (this->Internals->LocalPoints->InsertUniquePoint(p, sid))
+          {
+          // New point, save the id of the original grid point id associated
+          // to this surface point
+          if (static_cast<vtkIdType>(this->Internals->LocalPointsMap.size()) <= sid)
+            {
+            this->Internals->LocalPointsMap.resize(sid + 1);
+            }
+          this->Internals->LocalPointsMap[sid] = origPtId;
+          }
+        }
+      }
+
+    // Now reduce surface point coordinates on ALL ranks
+    ::AllGatherV(this->Controller,
+      (double*)surfacePoints->GetVoidPointer(0),
+      surfacePoints->GetNumberOfPoints() * 3,
+      this->Internals->AllPointsOfSurfacePoints,
+      this->Internals->AllSizes, this->Internals->AllOffsets);
+    }
+}
+
+//---------------------------------------------------------------------------
+// Step 2: browse global ids/point coordinates of other ranks and check if some
+// are duplicated locally.
+// For each neighbor rank, save the ids of the cells adjacent to the surface
+// points shared, those cells are the ghost cells we will send them.
+void vtkPUnstructuredGridGhostCellsGenerator::ComputeSharedPoints()
+{
+  vtkNew<vtkIdList> cellIdsList;
+  for (int i = 0; i < this->NumRanks; i++)
+    {
+    if (i == this->RankId)
+      {
+      continue;
+      }
+    for (vtkIdType j = 0, idx = this->Internals->AllOffsets[i];
+         j < this->Internals->AllSizes[i]; j++, idx++)
+      {
+      vtkIdType localPointId = -1;
+      if (this->Internals->InputGlobalPointIds)
+        {
+        // Check if this point exists locally from its global ids, if so
+        // get its local id.
+        vtkIdType gid = this->Internals->AllGlobalIdsOfSurfacePoints[idx];
+        std::map<vtkIdType, vtkIdType>::iterator iter =
+          this->Internals->GlobalToLocalPointIdMap.find(gid);
+        if (iter != this->Internals->GlobalToLocalPointIdMap.end())
+          {
+          localPointId = iter->second;
+          }
+        }
+      else
+        {
+        // Check if this point exists locally from its coordinates, if so
+        // get its local id.
+        double *p = &this->Internals->AllPointsOfSurfacePoints[idx];
+        localPointId = this->Internals->LocalPoints->IsInsertedPoint(p);
+
+        if (localPointId != -1)
+          {
+          localPointId = this->Internals->LocalPointsMap[localPointId];
+          }
+        idx += 2; // jump to next coordinates
+        j += 2;
+        }
+
+      if (localPointId != -1)
+        {
+        // Current rank also has a copy of this global point
+        cellIdsList->Reset();
+        // Get the cells connected to this point
+        this->Internals->Input->GetPointCells(localPointId, cellIdsList.Get());
+        vtkIdType nbIds = cellIdsList->GetNumberOfIds();
+        // 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));
+          }
+        }
+      }
+    }
+
+  // Release memory of all reduced arrays
+  this->Internals->AllGlobalIdsOfSurfacePoints.resize(0);
+  this->Internals->AllPointsOfSurfacePoints.resize(0);
+  this->Internals->AllSizes.resize(0);
+  this->Internals->AllOffsets.resize(0);
+  // Now we know our neighbors and which points we have in common and the
+  // ghost cells to share.
+}
+
+//-----------------------------------------------------------------------------
+// Step 3: extract and send the ghost cells to the neighbor ranks
+void vtkPUnstructuredGridGhostCellsGenerator::ExtractAndSendGhostCells()
+{
+  vtkNew<vtkIdList> cellIdsList;
+  vtkNew<vtkExtractCells> extractCells;
+  extractCells->SetInputData(this->Internals->Input);
+  std::map<int, std::set<vtkIdType> >::iterator iter =
+    this->Internals->NeighborRanksCells.begin();
+
+  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)
+    {
+    int toRank = iter->first;
+    std::set<vtkIdType>& cellsToShare = iter->second;
+    cellIdsList->SetNumberOfIds(cellsToShare.size());
+    std::set<vtkIdType>::iterator sIter = cellsToShare.begin();
+    for (vtkIdType i = 0; sIter != cellsToShare.end(); ++sIter, i++)
+      {
+      cellIdsList->SetId(i, *sIter);
+      }
+    extractCells->SetCellList(cellIdsList.Get());
+    extractCells->Update();
+    vtkUnstructuredGrid* extractGrid = extractCells->GetOutput();
+
+    // Send the extracted grid to the neighbor rank asynchronously
+    CommDataInfo& c = this->Internals->CommData[toRank];
+    if (vtkCommunicator::MarshalDataObject(extractGrid, c.SendBuffer))
+      {
+      c.SendLen = c.SendBuffer->GetNumberOfTuples();
+      // Send data length
+      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]);
+      }
+    }
+}
+
+//-----------------------------------------------------------------------------
+// Step 4: receive the ghost cells from the neighbor ranks and merge them
+// to the local grid.
+void vtkPUnstructuredGridGhostCellsGenerator::ReceiveAndMergeGhostCells(
+  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();
+
+  vtkMPICommunicator* com =
+    vtkMPICommunicator::SafeDownCast(this->Controller->GetCommunicator());
+
+  // Browse all neighbor ranks and receive the mesh that contains cells
+  int nbNeighbors = static_cast<int>(this->Internals->NeighborRanksCells.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)
+    {
+    vtkIdType fromRank = iter->first;
+    CommDataInfo& c = this->Internals->CommData[fromRank];
+    com->NoBlockReceive(
+      &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
+  int counter = 0;
+  while (counter != nbNeighbors)
+    {
+    for (iter = this->Internals->NeighborRanksCells.begin();
+      iter != this->Internals->NeighborRanksCells.end(); ++iter)
+      {
+      vtkIdType fromRank = iter->first;
+      CommDataInfo& c = this->Internals->CommData[fromRank];
+      if (!c.RecvReqs[0].Test() || c.CommStep != 0)
+        {
+        continue;
+        }
+      c.CommStep = 1;
+      c.RecvBuffer->SetNumberOfValues(c.RecvLen);
+      com->NoBlockReceive(
+        (char*)c.RecvBuffer->GetVoidPointer(0), c.RecvLen, fromRank,
+        UGGCG_DATA_EXCHANGE_TAG, c.RecvReqs[1]);
+      counter++;
+      }
+    }
+
+  // Browse all neighbor ranks and receive the mesh that contains cells
+  // that are ghost cells for current rank.
+  counter = 0;
+  while (counter != nbNeighbors)
+    {
+    for (iter = this->Internals->NeighborRanksCells.begin();
+    iter != this->Internals->NeighborRanksCells.end(); ++iter)
+      {
+      vtkIdType fromRank = iter->first;
+      CommDataInfo& c = this->Internals->CommData[fromRank];
+
+      if (!c.RecvReqs[1].Test() || c.CommStep != 1)
+        {
+        continue;
+        }
+
+      c.CommStep = 2;
+      vtkUnstructuredGrid* grid = vtkUnstructuredGrid::New();
+      vtkCommunicator::UnMarshalDataObject(c.RecvBuffer, grid);
+      c.RecvBuffer->Delete();
+      c.RecvBuffer = NULL;
+
+      // Flag the received grid elements as ghosts
+      grid->AllocatePointGhostArray();
+      grid->AllocateCellGhostArray();
+      grid->GetPointGhostArray()->FillComponent(0, 1);
+      grid->GetCellGhostArray()->FillComponent(0, 1);
+
+      // Make sure the global point ids array is tagged accordingly
+      if (this->Internals->InputGlobalPointIds &&
+          !grid->GetPointData()->GetGlobalIds())
+        {
+        grid->GetPointData()->SetGlobalIds(grid->GetPointData()->GetArray(
+          this->Internals->InputGlobalPointIds->GetName()));
+        }
+
+      totalNbCells += grid->GetNumberOfCells();
+      totalNbPoints += grid->GetNumberOfPoints();
+
+      neighborGrids.push_back(grid);
+
+      counter++;
+      }
+    }
+
+  // Shallow copy the input grid and initialize the ghost arrays
+  vtkNew<vtkUnstructuredGrid> inputCopy;
+  inputCopy->ShallowCopy(this->Internals->Input);
+  inputCopy->AllocatePointGhostArray();
+  inputCopy->AllocateCellGhostArray();
+
+  // MergeCells merge input + grids that contains ghost cells to the output grid
+  vtkNew<vtkMergeCells> mergeCells;
+  mergeCells->SetUnstructuredGrid(output);
+  mergeCells->SetTotalNumberOfCells(totalNbCells);
+  mergeCells->SetTotalNumberOfPoints(totalNbPoints);
+  mergeCells->SetTotalNumberOfDataSets(
+    1 + static_cast<int>(this->Internals->NeighborRanksCells.size()));
+  mergeCells->SetUseGlobalIds(this->Internals->InputGlobalPointIds != 0 ? 1 : 0);
+  mergeCells->SetPointMergeTolerance(0.0);
+
+  // Merge input grid first
+  mergeCells->MergeDataSet(inputCopy.Get());
+
+  // Then merge ghost grid from neighbor rank
+  for (std::size_t i = 0; i < neighborGrids.size(); i++)
+    {
+    mergeCells->MergeDataSet(neighborGrids[i]);
+    neighborGrids[i]->Delete();
+    }
+
+  // Finalize the merged output
+  mergeCells->Finish();
+}
diff --git a/src/Plugins/GhostCellsGenerator/vtkPUnstructuredGridGhostCellsGenerator.h b/src/Plugins/GhostCellsGenerator/vtkPUnstructuredGridGhostCellsGenerator.h
new file mode 100644 (file)
index 0000000..8102d82
--- /dev/null
@@ -0,0 +1,104 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkPUnstructuredGridGhostCellsGenerator.h
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+// .NAME vtkPUnstructuredGridGhostCellsGenerator - Builds ghost cells for a
+//  distributed unstructured grid dataset.
+//
+// .SECTION Description
+// This filter generate ghost cells for distributed a unstructured grid in
+// parallel - using MPI asynchronous communcations.
+// The filter can take benefit of the input grid point global ids to perform.
+//
+// .SECTION Caveats
+//  <ul>
+//    <li> A step of 'all reduce' (each processor send/receive data to/from
+//         all other processors.
+//    <li> The code currently assumes one grid per rank. </li>
+//    <li> PointData and CellData must match across partitions/processes. </li>
+//  </ul>
+//
+// .SECTION See Also
+// vtkDistributedDataFilter vtkPUnstructuredGridGhostDataGenerator
+//
+// .SECTION Thanks
+// This filter has been developed by Joachim Pouderoux, Kitware SAS 2015.
+
+#ifndef vtkPUnstructuredGridGhostCellsGenerator_h
+#define vtkPUnstructuredGridGhostCellsGenerator_h
+
+#include "vtkUnstructuredGridAlgorithm.h"
+
+class vtkMultiProcessController;
+class vtkUnstructuredGrid;
+
+class vtkPUnstructuredGridGhostCellsGenerator:
+  public vtkUnstructuredGridAlgorithm
+{
+  vtkTypeMacro(vtkPUnstructuredGridGhostCellsGenerator, vtkUnstructuredGridAlgorithm);
+
+public:
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  static vtkPUnstructuredGridGhostCellsGenerator *New();
+
+  // Description:
+  // Set/Get the MPI multi process controller object.
+  void SetController(vtkMultiProcessController *c);
+  vtkGetObjectMacro(Controller, vtkMultiProcessController);
+
+  // Description:
+  // Specify if the filter must take benefit of global point ids if they exist.
+  // If false, point coordinates are used. Default is TRUE.
+  vtkSetMacro(UseGlobalPointIds, bool);
+  vtkGetMacro(UseGlobalPointIds, bool);
+  vtkBooleanMacro(UseGlobalPointIds, bool);
+
+  // Description:
+  // Specify the name of the global point ids data array if the GlobalIds
+  // attribute array is not set. Default is "GlobalNodeIds".
+  vtkSetStringMacro(GlobalPointIdsArrayName);
+  vtkGetStringMacro(GlobalPointIdsArrayName);
+
+protected:
+  vtkPUnstructuredGridGhostCellsGenerator();
+  ~vtkPUnstructuredGridGhostCellsGenerator();
+
+  virtual int RequestData(vtkInformation *, vtkInformationVector **,
+    vtkInformationVector *);
+
+  void ExtractAndReduceSurfacePoints();
+
+  void ComputeSharedPoints();
+
+  void ExtractAndSendGhostCells();
+
+  void ReceiveAndMergeGhostCells(vtkUnstructuredGrid*);
+
+  vtkMultiProcessController *Controller;
+
+  int NumRanks;
+  int RankId;
+  char* GlobalPointIdsArrayName;
+  bool UseGlobalPointIds;
+
+private:
+  struct vtkInternals;
+  vtkInternals* Internals;
+
+  vtkPUnstructuredGridGhostCellsGenerator(const vtkPUnstructuredGridGhostCellsGenerator&); // Not implemented
+  void operator=(const vtkPUnstructuredGridGhostCellsGenerator&); // Not implemented
+};
+
+#endif
diff --git a/src/Plugins/GhostCellsGenerator/vtkPVUnstructuredGridGhostCellsGenerator.cxx b/src/Plugins/GhostCellsGenerator/vtkPVUnstructuredGridGhostCellsGenerator.cxx
new file mode 100644 (file)
index 0000000..b47aad6
--- /dev/null
@@ -0,0 +1,91 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkPVUnstructuredGridGhostCellsGenerator.cxx
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+#include "vtkPVUnstructuredGridGhostCellsGenerator.h"
+#include "vtkPVConfig.h" // need ParaView defines before MPI stuff
+
+#include "vtkInformation.h"
+#include "vtkInformationVector.h"
+#include "vtkMultiProcessController.h"
+#include "vtkNew.h"
+#include "vtkObjectFactory.h"
+#include "vtkStreamingDemandDrivenPipeline.h"
+#include "vtkUnstructuredGrid.h"
+
+#ifdef PARAVIEW_USE_MPI
+#  include "vtkPUnstructuredGridGhostCellsGenerator.h"
+#endif
+
+static const char* PVUGGCG_GLOBAL_POINT_IDS = "GlobalNodeIds";
+
+//----------------------------------------------------------------------------
+
+vtkStandardNewMacro(vtkPVUnstructuredGridGhostCellsGenerator)
+vtkSetObjectImplementationMacro(
+  vtkPVUnstructuredGridGhostCellsGenerator, Controller, vtkMultiProcessController);
+
+//----------------------------------------------------------------------------
+vtkPVUnstructuredGridGhostCellsGenerator::vtkPVUnstructuredGridGhostCellsGenerator()
+{
+  this->Controller = NULL;
+  this->SetController(vtkMultiProcessController::GetGlobalController());
+
+  this->GlobalPointIdsArrayName = NULL;
+  this->UseGlobalPointIds = true;
+  this->SetGlobalPointIdsArrayName(PVUGGCG_GLOBAL_POINT_IDS);
+}
+
+//----------------------------------------------------------------------------
+vtkPVUnstructuredGridGhostCellsGenerator::~vtkPVUnstructuredGridGhostCellsGenerator()
+{
+  this->SetController(NULL);
+  this->SetGlobalPointIdsArrayName(NULL);
+}
+
+//-----------------------------------------------------------------------------
+void vtkPVUnstructuredGridGhostCellsGenerator::PrintSelf(ostream& os, vtkIndent indent)
+{
+  Superclass::PrintSelf(os, indent);
+}
+
+//-----------------------------------------------------------------------------
+int vtkPVUnstructuredGridGhostCellsGenerator::RequestData(
+  vtkInformation *vtkNotUsed(request),
+  vtkInformationVector **inputVector,
+  vtkInformationVector *outputVector)
+{
+  // get the info objects
+  vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
+  vtkInformation *outInfo = outputVector->GetInformationObject(0);
+
+  // get the input and output. Input may just have the UnstructuredGridBase
+  // interface, but output should be an unstructured grid.
+  vtkUnstructuredGridBase *input = vtkUnstructuredGridBase::SafeDownCast(
+    inInfo->Get(vtkDataObject::DATA_OBJECT()));
+  vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(
+    outInfo->Get(vtkDataObject::DATA_OBJECT()));
+#ifdef PARAVIEW_USE_MPI
+  vtkNew<vtkPUnstructuredGridGhostCellsGenerator> ghostGenerator;
+  ghostGenerator->SetInputData(input);
+  ghostGenerator->SetController(this->Controller);
+  ghostGenerator->SetUseGlobalPointIds(this->UseGlobalPointIds);
+  ghostGenerator->SetGlobalPointIdsArrayName(this->GlobalPointIdsArrayName);
+  ghostGenerator->Update();
+  output->ShallowCopy(ghostGenerator->GetOutput());
+#else
+  output->ShallowCopy(input);
+#endif
+  return 1;
+}
diff --git a/src/Plugins/GhostCellsGenerator/vtkPVUnstructuredGridGhostCellsGenerator.h b/src/Plugins/GhostCellsGenerator/vtkPVUnstructuredGridGhostCellsGenerator.h
new file mode 100644 (file)
index 0000000..9ad1b20
--- /dev/null
@@ -0,0 +1,91 @@
+/*=========================================================================
+
+  Program:   Visualization Toolkit
+  Module:    vtkPVUnstructuredGridGhostCellsGenerator.h
+
+  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
+  All rights reserved.
+  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
+
+     This software is distributed WITHOUT ANY WARRANTY; without even
+     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+     PURPOSE.  See the above copyright notice for more information.
+
+=========================================================================*/
+
+// .NAME vtkPVUnstructuredGridGhostCellsGenerator - Builds ghost cells for a
+//  distributed unstructured grid dataset.
+//
+// .SECTION Description
+// This filter generate ghost cells for distributed a unstructured grid in
+// parallel - using MPI asynchronous communcations.
+// The filter can take benefit of the input grid point global ids to perform.
+//
+// .SECTION Caveats
+//  <ul>
+//    <li> A step of 'all reduce' (each processor send/receive data to/from
+//         all other processors.
+//    <li> The code currently assumes one grid per rank. </li>
+//    <li> PointData and CellData must match across partitions/processes. </li>
+//  </ul>
+//
+// .SECTION See Also
+// vtkDistributedDataFilter vtkPUnstructuredGridGhostDataGenerator
+//
+// .SECTION Thanks
+// This filter has been developed by Joachim Pouderoux, Kitware SAS 2015.
+
+#ifndef vtkPVUnstructuredGridGhostCellsGenerator_h
+#define vtkPVUnstructuredGridGhostCellsGenerator_h
+
+#include "vtkUnstructuredGridAlgorithm.h"
+
+class vtkMultiProcessController;
+class vtkUnstructuredGrid;
+
+class vtkPVUnstructuredGridGhostCellsGenerator:
+  public vtkUnstructuredGridAlgorithm
+{
+  vtkTypeMacro(vtkPVUnstructuredGridGhostCellsGenerator, vtkUnstructuredGridAlgorithm);
+
+public:
+  void PrintSelf(ostream& os, vtkIndent indent);
+
+  static vtkPVUnstructuredGridGhostCellsGenerator *New();
+
+  // Description:
+  // Set/Get the MPI multi process controller object.
+  void SetController(vtkMultiProcessController *c);
+  vtkGetObjectMacro(Controller, vtkMultiProcessController);
+
+  // Description:
+  // Specify if the filter must take benefit of global point ids if they exist.
+  // If false, point coordinates are used. Default is TRUE.
+  vtkSetMacro(UseGlobalPointIds, bool);
+  vtkGetMacro(UseGlobalPointIds, bool);
+  vtkBooleanMacro(UseGlobalPointIds, bool);
+
+  // Description:
+  // Specify the name of the global point ids data array if the GlobalIds
+  // attribute array is not set. Default is "GlobalNodeIds".
+  vtkSetStringMacro(GlobalPointIdsArrayName);
+  vtkGetStringMacro(GlobalPointIdsArrayName);
+
+protected:
+  vtkPVUnstructuredGridGhostCellsGenerator();
+  ~vtkPVUnstructuredGridGhostCellsGenerator();
+
+  virtual int RequestData(vtkInformation *, vtkInformationVector **,
+    vtkInformationVector *);
+
+  vtkMultiProcessController *Controller;
+  char* GlobalPointIdsArrayName;
+  bool UseGlobalPointIds;
+
+private:
+
+  vtkPVUnstructuredGridGhostCellsGenerator(const vtkPVUnstructuredGridGhostCellsGenerator&); // Not implemented
+  void operator=(const vtkPVUnstructuredGridGhostCellsGenerator&); // Not implemented
+};
+
+#endif