comac_desk_app/ThirdpartyLibs/Libs/windows-x86_64/vtk/include/vtkDIYGhostUtilities.h

1018 lines
36 KiB
C
Raw Normal View History

2024-11-21 11:50:43 +08:00
/*=========================================================================
Program: Visualization Toolkit
Module: vtkDIYGhostUtilities.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.
=========================================================================*/
/**
* @class vtkDIYGhostUtilities
* @brief Utilities to produce ghost cells between a collection of data sets of same type.
*
* vtkDIYGhostUtilities is a set of utilities which produce ghost cells between
* a collection of data sets of same type, using DIY.
*
* Ghosts are computed from scratch, even if parts of the input already own ghosts. In such
* instance, ghosts are treated as if they didn't exist in the input.
*
* Mixed types in the input `vtkCompositeDataSet` are supported, in the sense that ghost cells are
* only exchanged between blocks of same type. Similarly, ghosts are exchanged between blocks that
* connect.
*
* Blocks connect with different criteria depending on their types:
*
* - `vtkImageData`: Blocks connect if they share face / edge / corner, if they share same
* dimension (1D / 2D / 3D), and if they have same orientation matrix and same spacing.
* - `vtkRectilinearGrid`: Blocks connect if the x, y, and z coordinate arrays match at their
* interfaces.
* - `vtkStructuredGrid`: Blocks connect if external faces of the grids are mangled together,
* regardless of relative inner orientation. In other words, if grid 1 is spanned by (i1, j1, k1)
* indexing, and grid 2 is spanned by (i2, j2, k2) indexing, if on one face, (j1, k1) connects
* with (-i2, -j2), those 2 grids are connected and will exchange ghosts. Two grids partially
* fitting are discarded. In order for 2 grids to fit, one corner from one face of one grid needs
* to be an existing point in one face of the second grid. Additionally, every points from this
* corner on both grids need to match until the opposite corner (opposite w.r.t. each dimension)
* is reached, and this opposite corner of the grid junction needs to be a corner of either grid.
* - `vtkUnstructuredGrid`: Blocks connect if the external surface of neighboring grids match.
* To do so, only points are looked at. If at least one point matches a point in a neighboring
* grid, then they are connected. If there are no point global ids in the input, the 3D position
* of the points is used to determine if grids match, up to floating point precision in the
* coordinates. Note that integer coordinates can be used with this pipeline. If global ids are
* present in the input point data, then the pipeline will only look at matching global ids, and
* ignore point positions.
* - `vtkPolyData`: Blocks connect if the boundary edges of neighboring poly data match. The filter
* behaves the same way it does with `vtkUnstructuredGrid`. Point positions are used to match
* points if point global ids are not present, and point global ids are used instead if they are
* present.
*
* Points at the interface between 2 partitions are edited depending on the ownership of the point
* after the ghost points are generated. One can keep track of which process owns a non-ghost copy
* of the point if an array associating each point with its process id is available in the input.
*
* @note Currently, only `vtkImageData`, `vtkRectilinearGrid`, `vtkStructuredGrid`,
* `vtkUnstructuredGrid` and `vtkPolyData` are
* implemented. Unless there is determining structural data added to subclasses of those classes,
* this filter should work well on subclasses of supported types.
*
* @warning This warning only applies for `vtkUnstructuredGrid` and `vtkPolyData` inputs. If
* there are duplicate points in the outer shell of an input partition, then this filter cannot
* decide on how to connect the cells properly when generating ghosts. The same phenomenon occurs
* when the outer shell of the partition has 2 points with the same global id. In such
* circumstances, use the `vtkStaticCleanUnstructuredGrid`
* or `vtkStaticCleanPolyData` filter first in order to have a clean input.
*/
#ifndef vtkDIYGhostUtilities_h
#define vtkDIYGhostUtilities_h
#include "vtkBoundingBox.h" // For ComputeLinkMap
#include "vtkDIYExplicitAssigner.h" // For DIY assigner
#include "vtkDIYUtilities.h" // For Block
#include "vtkObject.h"
#include "vtkParallelDIYModule.h" // For export macros
#include "vtkQuaternion.h" // For vtkImageData
#include "vtkSmartPointer.h" // For vtkSmartPointer
#include <array> // For VectorType and ExtentType
#include <map> // For BlockMapType
#include <set> // For Link
#include <vector> // For LinkMap
// clang-format off
#include "vtk_diy2.h" // Third party include
#include VTK_DIY2(diy/assigner.hpp)
#include VTK_DIY2(diy/master.hpp)
#include VTK_DIY2(diy/partners/all-reduce.hpp)
// clang-format on
class vtkAbstractPointLocator;
class vtkAlgorithm;
class vtkCellArray;
class vtkDataArray;
class vtkDataSet;
class vtkFieldData;
class vtkIdList;
class vtkIdTypeArray;
class vtkImageData;
class vtkMatrix3x3;
class vtkMultiProcessController;
class vtkPoints;
class vtkPointSet;
class vtkPolyData;
class vtkRectilinearGrid;
class vtkStructuredGrid;
class vtkUnsignedCharArray;
class vtkUnstructuredGrid;
class VTKPARALLELDIY_EXPORT vtkDIYGhostUtilities : public vtkObject
{
public:
vtkTypeMacro(vtkDIYGhostUtilities, vtkObject);
void PrintSelf(ostream& os, vtkIndent indent) override;
///@{
/**
* Convenient typedefs.
*/
using VectorType = std::array<double, 3>;
using QuaternionType = vtkQuaternion<double>;
using ExtentType = std::array<int, 6>;
template <class T>
using BlockMapType = std::map<int, T>;
using Links = std::set<int>;
using LinkMap = std::vector<Links>;
///@}
/**
* This helper structure owns a typedef to the block type of `DataSetT` used with diy to generate
* ghosts. This block type is defined as DataSetTypeToBlockTypeConverter<DataSetT>::BlockType.
*/
template <class DataSetT>
struct DataSetTypeToBlockTypeConverter;
protected:
/**
* Base block structure for data sets.
*/
struct DataSetBlockStructure
{
vtkSmartPointer<vtkFieldData> GhostCellData = nullptr;
vtkSmartPointer<vtkFieldData> GhostPointData = nullptr;
};
struct DataSetInformation
{
/**
* @warning This method does not work before the link map between blocks is computed.
*/
virtual bool InputNeedsGhostsPeeledOff() const = 0;
};
/**
* Structure to inherit from for data sets having a structured grid topology.
*/
struct GridBlockStructure : public DataSetBlockStructure
{
/**
* `GridBlockStructure` constructor. It takes the extent of a neighbor block as input.
*/
GridBlockStructure(const int* extent, int dim);
/**
* Extent of neighboring block with no ghosts.
*/
ExtentType Extent = ExtentType{ 1, -1, 1, -1, 1, -1 };
/**
* Extent of neighboring block that include ghost layers, shifted to match our mapping of the
* extent in the 3D world.
*/
ExtentType ShiftedExtentWithNewGhosts;
/**
* Extent of the neighboring block, shifted to match our mapping of the extent in the 3D world.
*/
ExtentType ShiftedExtent;
ExtentType ReceivedGhostExtent = ExtentType{ 1, -1, 1, -1, 1, -1 };
/**
* Binary mask encoding the adjacency of the neighboring block w.r.t. current block.
* This mask shall be written / read using Adjacency enumeration.
*/
unsigned char AdjacencyMask;
/**
* This stores the dimension of the grid (1D, 2D, or 3D).
*/
int DataDimension;
};
/**
* Structure storing information needed by a block on it's own grid structure.
*/
struct GridInformation : public DataSetInformation
{
bool InputNeedsGhostsPeeledOff() const override { return this->Extent != this->InputExtent; }
/**
* Extent without ghost layers.
*/
ExtentType Extent = ExtentType{ 1, -1, 1, -1, 1, -1 };
/**
* Input extent without any modification.
*/
ExtentType InputExtent = ExtentType{ 1, -1, 1, -1, 1, -1 };
ExtentType ExtentGhostThickness;
};
struct ImageDataInformation : public GridInformation
{
vtkImageData* Input;
};
/**
* Block structure storing information being communicated by neighboring blocks for
* `vtkImageData`.
*/
struct ImageDataBlockStructure : public GridBlockStructure
{
///@{
/**
* Constructor taking the extent (without ghosts) of the neighboring `vtkImageData`, as well
* as well as the image's origin, spacing, and orientation.
*/
ImageDataBlockStructure(const int extent[6], int dim, const double origin[3],
const double spacing[3], const double orientationQuaternion[4]);
ImageDataBlockStructure(const int extent[6], int dim, const double origin[3],
const double spacing[3], vtkMatrix3x3* directionMatrix);
///@}
/**
* Copy constructor.
*/
ImageDataBlockStructure(vtkImageData* image, const ImageDataInformation& info);
/**
* Origin of the neighboring `vtkImageData`.
*/
VectorType Origin;
/**
* Spacing of the neighboring `vtkImageData`.
*/
VectorType Spacing;
/**
* Orientation of the neighboring `vtkImageData`.
*/
QuaternionType OrientationQuaternion;
};
struct RectilinearGridInformation : public GridInformation
{
///@{
/**
* Point coordinates without ghosts.
*/
vtkSmartPointer<vtkDataArray> XCoordinates;
vtkSmartPointer<vtkDataArray> YCoordinates;
vtkSmartPointer<vtkDataArray> ZCoordinates;
///@}
/**
* Coordinates of ghosts copied from connected neighbors.
* This array maps to extents, i.e. the first element of this array stores the coordinates of
* the left side of the grid, the second the right side of the grid, and so on.
*/
vtkSmartPointer<vtkDataArray> CoordinateGhosts[6];
vtkRectilinearGrid* Input;
};
/**
* Block structure storing information being communicated by neighboring blocks for
* `vtkRectilinearGrid`.
*/
struct RectilinearGridBlockStructure : public GridBlockStructure
{
/**
* Constructor taking the extent (without ghosts) of the neighboring `vtkRectilinearGrid`,
* as well as its point coordinates.
*/
RectilinearGridBlockStructure(const int extent[6], int dim, vtkDataArray* xCoordinates,
vtkDataArray* yCoordinates, vtkDataArray* zCoordinates);
/**
* Copy constructor.
*/
RectilinearGridBlockStructure(vtkRectilinearGrid* grid, const RectilinearGridInformation& info);
///@{
/**
* Point coordinate arrays of the rectilinear grid.
*/
vtkSmartPointer<vtkDataArray> XCoordinates;
vtkSmartPointer<vtkDataArray> YCoordinates;
vtkSmartPointer<vtkDataArray> ZCoordinates;
///@}
};
struct StructuredGridInformation : public GridInformation
{
/**
* This structure represents the set of points and their corresponding extent
* of an external face of the structured grid.
*/
struct OuterPointLayersType
{
/**
* Points of an external face.
*/
vtkSmartPointer<vtkPoints> Points;
/**
* Extent (which represents a 2D, 1D, or 0D grid), of an external face.
*/
ExtentType Extent;
};
/**
* Array of 6 external faces. Each outer point layer holds a copy of the points of the external
* face, as well as its extent. This array is indexed in the same fashion as grid extents.
*/
OuterPointLayersType OuterPointLayers[6];
/**
* Handle on input points for current block.
*/
vtkPoints* InputPoints;
vtkStructuredGrid* Input;
};
/**
* Block structure storing information being communicated by neighboring blocks for
* `vtkStructuredGrid`.
*/
struct StructuredGridBlockStructure : public GridBlockStructure
{
/**
* Constructor taking the extent (without ghosts) of the neighboring `vtkStructuredGrid`,
* as well as its point array.
*/
StructuredGridBlockStructure(const int extent[6], int dim, vtkDataArray* points[6]);
/**
* Copy constructor.
*/
StructuredGridBlockStructure(vtkStructuredGrid* grid, const StructuredGridInformation& info);
/**
* Point coordinate arrays of the structured grid.
*/
vtkSmartPointer<vtkPoints> OuterPointLayers[6];
/**
* Grid interfacing with block's grid.
* This grid is a 2D grid and can be arbritrarely oriented depending on how grids connect.
*/
struct Grid2D
{
/**
* Start point extent coordinate in the x dimension
*/
int StartX = 0;
/**
* Start point extent coordinate in the y dimension
*/
int StartY = 0;
/**
* End point extent coordinate in the x dimension
*/
int EndX = 0;
/**
* End point extent coordinate in the y dimension
*/
int EndY = 0;
/**
* Orientation of the x dimension. (Either +1 or -1)
*/
int XOrientation = 0;
/**
* Orientation of the y dimension. (Either +1 or -1)
*/
int YOrientation = 0;
/**
* Index of the extent of the current grid. This is a value between 0 and 5, describing which
* external face of the structured grid this 2D grid represents.
*/
int ExtentId = -1;
};
/**
* 2D grid interfacing 2 blocks.
*
* @note This grid can be 1D or 0D.
*/
Grid2D GridInterface;
/**
* Buffer to store received ghost points from neighboring blocks.
*/
vtkNew<vtkPoints> GhostPoints;
};
struct UnstructuredDataInformation
{
bool InputNeedsGhostsPeeledOff() const
{
return this->OutputToInputCellIdRedirectionMap != nullptr;
};
/**
* Bounding box of input.
*/
vtkBoundingBox BoundingBox;
/**
* When the input has ghosts, this map is being used to copy input cells / cell data into
* the output (with input ghosts peeled off).
*/
vtkSmartPointer<vtkIdList> OutputToInputCellIdRedirectionMap = nullptr;
///@{
/**
* When the input has ghosts, this map is being used to copy input points / point data into
* the output (with input ghosts peeled off).
*/
vtkSmartPointer<vtkIdList> InputToOutputPointIdRedirectionMap = nullptr;
vtkSmartPointer<vtkIdList> OutputToInputPointIdRedirectionMap = nullptr;
///@}
/**
* Filter that is being used to extract the surface of the input.
* The surface is used to check how the interface of the input matches the ones of its
* neighboring blocks.
*/
vtkSmartPointer<vtkAlgorithm> InterfaceExtractor;
/**
* Handle to the local point ids of the surface of the input.
* Those point ids are being used to rapidly match points of the surface to their original
* location in the input.
*/
vtkIdTypeArray* InterfacePointIds;
/**
* Handle to the points of the surface of the input.
*/
vtkDataArray* InterfacePoints;
/**
* Handle to the point ids of the input surface, if present.
*/
vtkSmartPointer<vtkIdTypeArray> InterfaceGlobalPointIds;
///@{
/*
* This is a cursor telling the amount of points / cells information,
* that has
* already been added to the output. This variable is used at the very end of the pipeline.
*/
vtkIdType CurrentMaxPointId;
vtkIdType CurrentMaxCellId;
///@}
///@{
/**
* Number of input points / cell in the input when ghosts are removed.
*/
vtkIdType NumberOfInputPoints;
vtkIdType NumberOfInputCells;
///@}
};
struct UnstructuredDataBlockStructure : public DataSetBlockStructure
{
/**
* This lists the matching point ids to the interfacing points that are exchanged with current
* neighboring block. Those ids correspond to local point ordering as indexed in the input.
*/
vtkNew<vtkIdList> MatchingReceivedPointIds;
/**
* This array describes the same points as `MatchingReceivedPointIds`, but points are ordered
* like in the current neighboring block. Point ids stored in this array map to the output.
*/
vtkNew<vtkIdList> RemappedMatchingReceivedPointIdsSortedLikeTarget;
/**
* These are the interfacing points sent by the current neighboring block. They should match
* a subset of the output of the surface filter which is in `UnstructuredDataInformation`.
*/
vtkNew<vtkPoints> InterfacingPoints;
/**
* Point global ids of the interfacing surface sent to us by corresponding block, if present.
*/
vtkSmartPointer<vtkIdTypeArray> InterfacingGlobalPointIds = nullptr;
/**
* Point global ids sent to us by neighboring block, if present. This array has the same
* ordering as `GhostPoints`.
*/
vtkSmartPointer<vtkIdTypeArray> GhostGlobalPointIds = nullptr;
/**
* Ghost points sent by the current neighboring block.
*/
vtkNew<vtkPoints> GhostPoints;
/**
* This lists the ids of the points that we own and need to send to the current neighboring
* block.
*/
vtkNew<vtkIdList> PointIdsToSend;
///@{
/**
* It can happen that a point can be sent by multiple blocks. If those points are not carefully
* tracked down, we can end up instantiating multiple times a point that should be created only
* once. This array lists the potential duplicate point ids that are being send / received for
* the current neighboring block.
*/
vtkNew<vtkIdTypeArray> SharedPointIds;
vtkSmartPointer<vtkIdTypeArray> ReceivedSharedPointIds;
///@}
/**
* This is a mapping from points that have been sent by the current neighboring block and have
* already been added in the output points, to their location in the output point array.
*/
std::map<vtkIdType, vtkIdType> RedirectionMapForDuplicatePointIds;
/**
* This lists the ids of the cells that we own and need to send to the current neighboring
* block.
*/
vtkNew<vtkIdList> CellIdsToSend;
/**
* Point data at the interface sent by our neighbor. We only receive point data from neighbors
* of lower block id than us.
*/
vtkSmartPointer<vtkFieldData> InterfacingPointData;
};
struct UnstructuredGridInformation : public UnstructuredDataInformation
{
/**
* This is a cursor telling the amount of faces information, that has
* already been added to the output. This variable is used at the very end of the pipeline.
*/
vtkIdType CurrentFacesSize = 0;
/**
* This is a cursor telling how much the output connectivity array is filled.
* This is used at the very end of the pipeline.
*/
vtkIdType CurrentConnectivitySize = 0;
vtkIdTypeArray* Faces = nullptr;
vtkIdTypeArray* FaceLocations = nullptr;
vtkUnstructuredGrid* Input;
/**
* Cell connectivity array size of the input if the ghost cells are removed.
*/
vtkIdType InputConnectivitySize = 0;
/**
* Faces array size of the input if the ghost cells are removed.
*/
vtkIdType InputFacesSize = 0;
};
struct UnstructuredGridBlockStructure : public UnstructuredDataBlockStructure
{
/**
* Topology information for cells to be exchanged.
*/
struct TopologyBufferType
{
vtkSmartPointer<vtkUnsignedCharArray> Types = nullptr;
vtkSmartPointer<vtkIdTypeArray> Faces = nullptr;
vtkSmartPointer<vtkIdTypeArray> FaceLocations = nullptr;
vtkNew<vtkCellArray> CellArray;
};
TopologyBufferType SendBuffer;
TopologyBufferType ReceiveBuffer;
///@{
/**
* Handle to the faces / connectivity size that we have to send to the neighboring block.
*/
vtkIdType FacesSize = 0;
vtkIdType ConnectivitySize = 0;
///@}
};
struct PolyDataInformation : public UnstructuredDataInformation
{
vtkPolyData* Input;
///@{
/**
* This is a cursor telling how much the corresponding output connectivity array is filled.
* This is used at the very end of the pipeline.
*/
vtkIdType CurrentPolyConnectivitySize;
vtkIdType CurrentStripConnectivitySize;
vtkIdType CurrentLineConnectivitySize;
///@}
///@{
/**
* This is a cursor telling how many cells of corresponding types have been added so far.
* This is used at the very end of the pipeline.
*/
vtkIdType CurrentMaxPolyId = 0;
vtkIdType CurrentMaxStripId = 0;
vtkIdType CurrentMaxLineId = 0;
///@}
///@{
/**
* Number of cells of respective type when the input has its ghost cells removed
*/
vtkIdType NumberOfInputVerts;
vtkIdType NumberOfInputPolys;
vtkIdType NumberOfInputStrips;
vtkIdType NumberOfInputLines;
///@}
///@{
/**
* Cell connectivity array size of the input if ghost cells are removed.
*/
vtkIdType InputVertConnectivitySize;
vtkIdType InputPolyConnectivitySize;
vtkIdType InputStripConnectivitySize;
vtkIdType InputLineConnectivitySize;
///@{
///@{
/**
* In the event that the input has ghost cells, this maps the output cells (with input ghosts
* removed) to the input cells.
*/
vtkNew<vtkIdList> OutputToInputVertCellIdRedirectionMap;
vtkNew<vtkIdList> OutputToInputLineCellIdRedirectionMap;
vtkNew<vtkIdList> OutputToInputPolyCellIdRedirectionMap;
vtkNew<vtkIdList> OutputToInputStripCellIdRedirectionMap;
///@}
};
struct PolyDataBlockStructure : public UnstructuredDataBlockStructure
{
///@{
/**
* This lists the ids of the cells that we own and need to send to the current neighboring
* block.
*/
vtkNew<vtkIdList> PolyIdsToSend;
vtkNew<vtkIdList> StripIdsToSend;
vtkNew<vtkIdList> LineIdsToSend;
///@}
struct TopologyBufferType
{
vtkNew<vtkCellArray> Polys;
vtkNew<vtkCellArray> Strips;
vtkNew<vtkCellArray> Lines;
};
TopologyBufferType SendBuffer;
TopologyBufferType ReceiveBuffer;
///@{
/**
* Handle on the number of cells to send of the corresponding type.
*/
vtkIdType NumberOfPolysToSend = 0;
vtkIdType NumberOfStripsToSend = 0;
vtkIdType NumberOfLinesToSend = 0;
///@}
///@{
/**
* Handle on the number of cells of corresponding type to be sent to the neighbor block.
*/
vtkIdType PolyConnectivitySize = 0;
vtkIdType StripConnectivitySize = 0;
vtkIdType LineConnectivitySize = 0;
///@}
};
public:
/**
* Block structure to be used for diy communication.
* This is a generic structure split into 3 main components:
* - `BlockStructureType`: This holds all information sent by another block that are necessary
* to determine whether this block is to be connected with ourself.
* - `InformationType`: This holds all information from the input necessary to allocate the
* output for this block. This can include bounds, extent, etc.
*/
template <class BlockStructureT, class InformationT>
struct Block
{
///@{
/**
* Typedef handle on block structure and block information
*/
typedef BlockStructureT BlockStructureType;
typedef InformationT InformationType;
///@}
/**
* `BlockStructures` maps a neighboring block globald id to its block structure.
*/
BlockMapType<BlockStructureType> BlockStructures;
/**
* `InformationT` holds any information from the current block that is necessary to exchange
* ghosts. This is typically used when sending ghosts to neighboring blocks.
*/
InformationType Information;
BlockMapType<vtkBoundingBox> NeighborBoundingBoxes;
vtkBoundingBox BoundingBox;
vtkSmartPointer<vtkUnsignedCharArray> GhostCellArray;
vtkSmartPointer<vtkUnsignedCharArray> GhostPointArray;
};
///@{
/**
* Block typedefs.
*/
using ImageDataBlock = Block<ImageDataBlockStructure, ImageDataInformation>;
using RectilinearGridBlock = Block<RectilinearGridBlockStructure, RectilinearGridInformation>;
using StructuredGridBlock = Block<StructuredGridBlockStructure, StructuredGridInformation>;
using UnstructuredDataBlock = Block<UnstructuredDataBlockStructure, UnstructuredDataInformation>;
using UnstructuredGridBlock = Block<UnstructuredGridBlockStructure, UnstructuredGridInformation>;
using PolyDataBlock = Block<PolyDataBlockStructure, PolyDataInformation>;
//@}
/**
* Main pipeline generating ghosts. It takes as parameters a list of `DataSetT` for the `inputs`
* and the `outputs`.
* Please see `vtkGhostCellsGenerator` for a finer description of what this method does, as it is
* being used as a backend for this filter.
*
* `outputs` need to be already allocated and be of same size as `inputs`.
*/
template <class DataSetT>
static int GenerateGhostCells(std::vector<DataSetT*>& inputsDS, std::vector<DataSetT*>& outputsDS,
int outputGhostLevels, vtkMultiProcessController* controller);
///@{
/**
* Method that can be used to avoid the compile-time overhead of the templated method
* `GenerateGhostCells`. All this method does is call `GenerateGhostCells` with the appropriate
* template parameter.
*/
static int GenerateGhostCellsImageData(std::vector<vtkImageData*>& inputs,
std::vector<vtkImageData*>& outputs, int outputGhostLevels,
vtkMultiProcessController* controller);
static int GenerateGhostCellsRectilinearGrid(std::vector<vtkRectilinearGrid*>& inputs,
std::vector<vtkRectilinearGrid*>& outputs, int outputGhostLevels,
vtkMultiProcessController* controller);
static int GenerateGhostCellsStructuredGrid(std::vector<vtkStructuredGrid*>& inputs,
std::vector<vtkStructuredGrid*>& outputs, int outputGhostLevels,
vtkMultiProcessController* controller);
static int GenerateGhostCellsPolyData(std::vector<vtkPolyData*>& inputs,
std::vector<vtkPolyData*>& outputs, int outputGhostLevels,
vtkMultiProcessController* controller);
static int GenerateGhostCellsUnstructuredGrid(std::vector<vtkUnstructuredGrid*>& inputs,
std::vector<vtkUnstructuredGrid*>& outputs, int outputGhostLevels,
vtkMultiProcessController* controller);
///@}
protected:
vtkDIYGhostUtilities();
~vtkDIYGhostUtilities() override;
/**
* Reinitializes the bits that match the input bit mask in the input array to zero.
*/
static void ReinitializeSelectedBits(vtkUnsignedCharArray* ghosts, unsigned char mask);
/**
* This method will set all ghosts points in `output` to zero. It will also
* allocate a new ghost array if none is already present.
*/
template <class DataSetT>
static void InitializeGhostPointArray(
typename DataSetTypeToBlockTypeConverter<DataSetT>::BlockType* block, DataSetT* output);
/**
* This method will set all ghosts cells in `output` to zero. It will also
* allocate a new ghost array if none is already present.
*/
template <class DataSetT>
static void InitializeGhostCellArray(
typename DataSetTypeToBlockTypeConverter<DataSetT>::BlockType* block, DataSetT* output);
///@{
/**
*
*/
static void CloneGeometricStructures(
std::vector<vtkImageData*>& inputs, std::vector<vtkImageData*>& outputs);
static void CloneGeometricStructures(
std::vector<vtkRectilinearGrid*>& inputs, std::vector<vtkRectilinearGrid*>& outputs);
static void CloneGeometricStructures(
std::vector<vtkStructuredGrid*>& inputs, std::vector<vtkStructuredGrid*>& outputs);
static void CloneGeometricStructures(
std::vector<vtkUnstructuredGrid*>& inputs, std::vector<vtkUnstructuredGrid*>& outputs);
static void CloneGeometricStructures(
std::vector<vtkPolyData*>& inputs, std::vector<vtkPolyData*>& outputs);
///@}
///@{
/**
* Method to be overloaded for each supported type of input data set.
* In this method, given `BlockType` the block type for the data set type,
* `BlockType::InformationType` is filled with all information needed from the input to create the
* output.
*/
static void InitializeBlocks(diy::Master& master, std::vector<vtkImageData*>& inputs);
static void InitializeBlocks(diy::Master& master, std::vector<vtkRectilinearGrid*>& inputs);
static void InitializeBlocks(diy::Master& master, std::vector<vtkStructuredGrid*>& inputs);
static void InitializeBlocks(diy::Master& master, std::vector<vtkUnstructuredGrid*>& inputs);
static void InitializeBlocks(diy::Master& master, std::vector<vtkPolyData*>& inputs);
///@}
/**
* This method exchanges the bounding boxes among blocks.
*/
template <class DataSetT>
static void ExchangeBoundingBoxes(
diy::Master& master, const vtkDIYExplicitAssigner& assigner, std::vector<DataSetT*>& inputs);
template <class BlockT>
static LinkMap ComputeLinkMapUsingBoundingBoxes(const diy::Master& master);
///@{
/**
* Method to be overloaded for each supported type of input data set.
* This method is called in the pipeline right after diy environment
* has been set up. It exchanges between every information needed for the data set type `DataSetT`
* in order to be able to set link connections.
*/
static void ExchangeBlockStructures(diy::Master& master, std::vector<vtkImageData*>& inputs);
static void ExchangeBlockStructures(
diy::Master& master, std::vector<vtkRectilinearGrid*>& inputs);
static void ExchangeBlockStructures(diy::Master& master, std::vector<vtkStructuredGrid*>& inputs);
static void ExchangeBlockStructures(
diy::Master& master, std::vector<vtkUnstructuredGrid*>& inputs);
static void ExchangeBlockStructures(diy::Master& master, std::vector<vtkPolyData*>& inputs);
///@}
///@{
/**
* Method to be overloaded for each supported input data set type,
* that computes the minimal link map being necessary to exchange ghosts.
* This method is called after `master` has been relinked.
*/
static LinkMap ComputeLinkMap(
const diy::Master& master, std::vector<vtkImageData*>& inputs, int outputGhostLevels);
static LinkMap ComputeLinkMap(
const diy::Master& master, std::vector<vtkRectilinearGrid*>& inputs, int outputGhostLevels);
static LinkMap ComputeLinkMap(
const diy::Master& master, std::vector<vtkStructuredGrid*>& inputs, int outputGhostLevels);
static LinkMap ComputeLinkMap(
const diy::Master& master, std::vector<vtkUnstructuredGrid*>& inputs, int outputGhostLevels);
static LinkMap ComputeLinkMap(
const diy::Master& master, std::vector<vtkPolyData*>& inputs, int outputGhostLevels);
///@}
///@{
/**
* This method enqueues ghosts between communicating blocks. One version of this method
* is implemented per supported input types. It enqueues ghosts to block of id `blockId`.
*/
static void EnqueueGhosts(const diy::Master::ProxyWithLink& cp, const diy::BlockID& blockId,
vtkImageData* input, ImageDataBlock* block);
static void EnqueueGhosts(const diy::Master::ProxyWithLink& cp, const diy::BlockID& blockId,
vtkRectilinearGrid* input, RectilinearGridBlock* block);
static void EnqueueGhosts(const diy::Master::ProxyWithLink& cp, const diy::BlockID& blockId,
vtkStructuredGrid* input, StructuredGridBlock* block);
static void EnqueueGhosts(const diy::Master::ProxyWithLink& cp, const diy::BlockID& blockId,
vtkUnstructuredGrid* input, UnstructuredGridBlock* block);
static void EnqueueGhosts(const diy::Master::ProxyWithLink& cp, const diy::BlockID& blockId,
vtkPolyData* input, PolyDataBlock* block);
///@}
///@{
/**
* This method dequeues ghosts sent between communicating blocks. One version of this method
* is implemented per supported input types. It receives data from block of id `gid` and
* stores is inside `blockStructured`.
*/
static void DequeueGhosts(
const diy::Master::ProxyWithLink& cp, int gid, ImageDataBlockStructure& blockStructure);
static void DequeueGhosts(
const diy::Master::ProxyWithLink& cp, int gid, RectilinearGridBlockStructure& blockStructure);
static void DequeueGhosts(
const diy::Master::ProxyWithLink& cp, int gid, StructuredGridBlockStructure& blockStructure);
static void DequeueGhosts(
const diy::Master::ProxyWithLink& cp, int gid, UnstructuredGridBlockStructure& blockStructure);
static void DequeueGhosts(
const diy::Master::ProxyWithLink& cp, int gid, PolyDataBlockStructure& blockStructure);
///@}
/**
* Copy the inputs into the outputs. Shallow copying is performed if possible. If not,
* a deep copy is done.
*/
template <class DataSetT>
static void CopyInputsAndAllocateGhosts(diy::Master& master, diy::Assigner& assigner,
diy::RegularAllReducePartners& partners, std::vector<DataSetT*>& inputs,
std::vector<DataSetT*>& outputs, int outputGhostLevels);
///@{
/**
* Method to be overloaded for each supported input data set type,
* This method allocates ghosts in the output. At the point of calling this method,
* ghosts should have already been exchanged (see `ExchangeGhosts`).
*/
static void DeepCopyInputAndAllocateGhosts(
ImageDataBlock* block, vtkImageData* input, vtkImageData* outputs);
static void DeepCopyInputAndAllocateGhosts(
RectilinearGridBlock* block, vtkRectilinearGrid* input, vtkRectilinearGrid* outputs);
static void DeepCopyInputAndAllocateGhosts(
StructuredGridBlock* block, vtkStructuredGrid* input, vtkStructuredGrid* outputs);
static void DeepCopyInputAndAllocateGhosts(
UnstructuredGridBlock* block, vtkUnstructuredGrid* input, vtkUnstructuredGrid* outputs);
static void DeepCopyInputAndAllocateGhosts(
PolyDataBlock* block, vtkPolyData* input, vtkPolyData* outputs);
///@}
/**
* This method exchanges ghosts between connected blocks.
*/
template <class DataSetT>
static void ExchangeGhosts(diy::Master& master, std::vector<DataSetT*>& inputs);
/**
* This methods allocate a point and cell ghost array and fills it with 0.
*/
template <class DataSetT>
static void InitializeGhostArrays(
diy::Master& master, std::vector<DataSetT*>& outputs, int outputGhostLevels);
/**
* Adds ghost arrays, which are present in blocks of `master`, to `outputs` point and / or cell
* data.
*/
template <class DataSetT>
static void AddGhostArrays(diy::Master& master, std::vector<DataSetT*>& outputs);
///@{
/**
* This method sets the ghost arrays in the output. Ghosts have to be already allocated.
*/
static void FillGhostArrays(
const diy::Master& master, std::vector<vtkImageData*>& outputs, int outputGhostLevels);
static void FillGhostArrays(
const diy::Master& master, std::vector<vtkRectilinearGrid*>& outputs, int outputGhostLevels);
static void FillGhostArrays(
const diy::Master& master, std::vector<vtkStructuredGrid*>& outputs, int outputGhostLevels);
static void FillGhostArrays(
const diy::Master& master, std::vector<vtkUnstructuredGrid*>& outputs, int outputGhostLevels);
static void FillGhostArrays(
const diy::Master& master, std::vector<vtkPolyData*>& outputs, int outputGhostLevels);
///@}
private:
vtkDIYGhostUtilities(const vtkDIYGhostUtilities&) = delete;
void operator=(const vtkDIYGhostUtilities&) = delete;
///@{
/**
* Internal method that inflates exchanged bounding boxes to better treat floating point precision
* for points that are on the boundary of the bounding box.
*
* @note This method only does something for vtkUnstructuredGrid and vtkPolyData. The vtkDataSet
* version is empty;
*/
static void InflateBoundingBoxIfNecessary(
vtkDataSet* vtkNotUsed(input), vtkBoundingBox& vtkNotUsed(bb));
static void InflateBoundingBoxIfNecessary(vtkPointSet* input, vtkBoundingBox& bb);
///@}
};
#include "vtkDIYGhostUtilities.txx" // for template implementations
#endif