VTK-m  2.0
MergeBlockFunctor.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 // Copyright (c) 2018, The Regents of the University of California, through
11 // Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
12 // from the U.S. Dept. of Energy). All rights reserved.
13 //
14 // Redistribution and use in source and binary forms, with or without modification,
15 // are permitted provided that the following conditions are met:
16 //
17 // (1) Redistributions of source code must retain the above copyright notice, this
18 // list of conditions and the following disclaimer.
19 //
20 // (2) Redistributions in binary form must reproduce the above copyright notice,
21 // this list of conditions and the following disclaimer in the documentation
22 // and/or other materials provided with the distribution.
23 //
24 // (3) Neither the name of the University of California, Lawrence Berkeley National
25 // Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
26 // used to endorse or promote products derived from this software without
27 // specific prior written permission.
28 //
29 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
30 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
31 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
32 // IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33 // INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
36 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
37 // OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
38 // OF THE POSSIBILITY OF SUCH DAMAGE.
39 //
40 //=============================================================================
41 //
42 // This code is an extension of the algorithm presented in the paper:
43 // Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
44 // Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
45 // Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
46 // (LDAV), October 2016, Baltimore, Maryland.
47 //
48 // The PPP2 algorithm and software were jointly developed by
49 // Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
50 // Oliver Ruebel (LBNL)
51 //==============================================================================
52 
53 #ifndef vtk_m_worklet_contourtree_distributed_mergeblockfunctor_h
54 #define vtk_m_worklet_contourtree_distributed_mergeblockfunctor_h
55 
56 #include <vtkm/Types.h>
59 
60 // clang-format off
61 VTKM_THIRDPARTY_PRE_INCLUDE
62 #include <vtkm/thirdparty/diy/diy.h>
63 VTKM_THIRDPARTY_POST_INCLUDE
64 // clang-format on
65 
66 namespace vtkm
67 {
68 namespace worklet
69 {
70 namespace contourtree_distributed
71 {
72 
73 // Functor used by DIY reduce the merge data blocks in parallel
74 template <typename FieldType>
77  const vtkmdiy::ReduceProxy& rp, // communication proxy
78  const vtkmdiy::RegularMergePartners& partners // partners of the current block
79 )
80 { //MergeBlockFunctor
81  (void)partners; // Avoid unused parameter warning
82 
83  const auto selfid = rp.gid();
84 
85  // TODO This should be changed so that we have the ContourTree itself as the block and then the
86  // ContourTreeMesh would still be used for exchange. In this case we would need to compute
87  // the ContourTreeMesh at the beginning of the function for the current block every time
88  // but then we would not need to compute those meshes when we initialize vtkmdiy
89  // and we don't need to have the special case for rank 0.
90 
91  // Here we do the deque first before the send due to the way the iteration is handled in DIY, i.e., in each iteration
92  // A block needs to first collect the data from its neighours and then send the combined block to its neighbours
93  // for the next iteration.
94  // 1. dequeue the block and compute the new contour tree and contour tree mesh for the block if we have the hight GID
95  std::vector<int> incoming;
96  rp.incoming(incoming);
97  for (const int ingid : incoming)
98  {
99  if (ingid != selfid)
100  {
102  rp.dequeue(ingid, recvblock);
103 
104  // Construct the two contour tree mesh by assignign the block data
106  contourTreeMeshIn.NumVertices = recvblock.NumVertices;
107  contourTreeMeshIn.SortOrder = vtkm::cont::ArrayHandleIndex(contourTreeMeshIn.NumVertices);
108  contourTreeMeshIn.SortIndices = vtkm::cont::ArrayHandleIndex(contourTreeMeshIn.NumVertices);
109  contourTreeMeshIn.SortedValues = recvblock.SortedValue;
110  contourTreeMeshIn.GlobalMeshIndex = recvblock.GlobalMeshIndex;
111  contourTreeMeshIn.NeighborConnectivity = recvblock.NeighborConnectivity;
112  contourTreeMeshIn.NeighborOffsets = recvblock.NeighborOffsets;
113  contourTreeMeshIn.MaxNeighbors = recvblock.MaxNeighbors;
114 
116  contourTreeMeshOut.NumVertices = block->NumVertices;
117  contourTreeMeshOut.SortOrder = vtkm::cont::ArrayHandleIndex(contourTreeMeshOut.NumVertices);
118  contourTreeMeshOut.SortIndices = vtkm::cont::ArrayHandleIndex(contourTreeMeshOut.NumVertices);
119  contourTreeMeshOut.SortedValues = block->SortedValue;
120  contourTreeMeshOut.GlobalMeshIndex = block->GlobalMeshIndex;
121  contourTreeMeshOut.NeighborConnectivity = block->NeighborConnectivity;
122  contourTreeMeshOut.NeighborOffsets = block->NeighborOffsets;
123  contourTreeMeshOut.MaxNeighbors = block->MaxNeighbors;
124  // Merge the two contour tree meshes
125  contourTreeMeshOut.MergeWith(contourTreeMeshIn);
126 
127  // Compute the origin and size of the new block
128  vtkm::Id3 globalSize = block->GlobalSize;
129  vtkm::Id3 currBlockOrigin;
130  currBlockOrigin[0] = std::min(recvblock.BlockOrigin[0], block->BlockOrigin[0]);
131  currBlockOrigin[1] = std::min(recvblock.BlockOrigin[1], block->BlockOrigin[1]);
132  currBlockOrigin[2] = std::min(recvblock.BlockOrigin[2], block->BlockOrigin[2]);
133  vtkm::Id3 currBlockMaxIndex; // Needed only to compute the block size
134  currBlockMaxIndex[0] = std::max(recvblock.BlockOrigin[0] + recvblock.BlockSize[0],
135  block->BlockOrigin[0] + block->BlockSize[0]);
136  currBlockMaxIndex[1] = std::max(recvblock.BlockOrigin[1] + recvblock.BlockSize[1],
137  block->BlockOrigin[1] + block->BlockSize[1]);
138  currBlockMaxIndex[2] = std::max(recvblock.BlockOrigin[2] + recvblock.BlockSize[2],
139  block->BlockOrigin[2] + block->BlockSize[2]);
140  vtkm::Id3 currBlockSize;
141  currBlockSize[0] = currBlockMaxIndex[0] - currBlockOrigin[0];
142  currBlockSize[1] = currBlockMaxIndex[1] - currBlockOrigin[1];
143  currBlockSize[2] = currBlockMaxIndex[2] - currBlockOrigin[2];
144 
145  // On rank 0 we compute the contour tree at the end when the merge is done, so we don't need to do it here
146  if (selfid == 0)
147  {
148  // Save the data from our block for the next iteration
149  block->NumVertices = contourTreeMeshOut.NumVertices;
150  block->SortedValue = contourTreeMeshOut.SortedValues;
151  block->GlobalMeshIndex = contourTreeMeshOut.GlobalMeshIndex;
152  block->NeighborConnectivity = contourTreeMeshOut.NeighborConnectivity;
153  block->NeighborOffsets = contourTreeMeshOut.NeighborOffsets;
154  block->MaxNeighbors = contourTreeMeshOut.MaxNeighbors;
155  block->BlockOrigin = currBlockOrigin;
156  block->BlockSize = currBlockSize;
157  block->GlobalSize = globalSize;
158  }
159  else // If we are a block that will continue to be merged then we need compute the contour tree here
160  {
161  // Compute the contour tree from our merged mesh
162  vtkm::Id currNumIterations;
167  vtkm::Id3 maxIdx(currBlockOrigin[0] + currBlockSize[0] - 1,
168  currBlockOrigin[1] + currBlockSize[1] - 1,
169  currBlockOrigin[2] + currBlockSize[2] - 1);
170  auto meshBoundaryExecObj =
171  contourTreeMeshOut.GetMeshBoundaryExecutionObject(globalSize, currBlockOrigin, maxIdx);
172  worklet.Run(
173  contourTreeMeshOut.SortedValues, // Unused param. Provide something to keep the API happy
174  contourTreeMeshOut,
175  currContourTree,
176  currSortOrder,
177  currNumIterations,
179  meshBoundaryExecObj);
181  if (block->ComputeRegularStructure == 1)
182  {
183  // If we have the fully augmented contour tree
185  currContourTree.Arcs, contourTreeMeshOut);
186  }
187  else if (block->ComputeRegularStructure == 2)
188  {
189  // If we have the partially augmented (e.g., boundary augmented) contour tree
191  currContourTree.Augmentnodes, currContourTree.Augmentarcs, contourTreeMeshOut);
192  }
193  else
194  {
195  // We should not be able to get here
197  "Parallel contour tree requires at least parial boundary augmentation");
198  }
199 
200  // Copy the data from newContourTreeMesh into block
201  block->NumVertices = newContourTreeMesh->NumVertices;
202  block->SortedValue = newContourTreeMesh->SortedValues;
203  block->GlobalMeshIndex = newContourTreeMesh->GlobalMeshIndex;
204  block->NeighborConnectivity = newContourTreeMesh->NeighborConnectivity;
205  block->NeighborOffsets = newContourTreeMesh->NeighborOffsets;
206  block->MaxNeighbors = newContourTreeMesh->MaxNeighbors;
207  block->BlockOrigin = currBlockOrigin;
208  block->BlockSize = currBlockSize;
209  block->GlobalSize = globalSize;
210 
211  // VTKm keeps track of the arrays for us, so we can savely delete the ContourTreeMesh
212  // as all data has been transferred into our data block
213  delete newContourTreeMesh;
214  }
215  }
216  }
217  // Send our current block (which is either our original block or the one we just combined from the ones we received) to our next neighbour.
218  // Once a rank has send his block (either in its orignal or merged form) it is done with the reduce
219  for (int cc = 0; cc < rp.out_link().size(); ++cc)
220  {
221  auto target = rp.out_link().target(cc);
222  if (target.gid != selfid)
223  {
224  rp.enqueue(target, *block);
225  }
226  }
227 } //end MergeBlockFunctor
228 
229 } // namespace contourtree_distributed
230 } // namespace worklet
231 } // namespace vtkm
232 
233 #endif
vtkm::worklet::contourtree_augmented::ContourTreeMesh::GlobalMeshIndex
IdArrayType GlobalMeshIndex
Definition: ContourTreeMesh.h:200
vtkm::cont::ArrayHandle< vtkm::Id >
vtkm::worklet::contourtree_distributed::ContourTreeBlockData
Definition: ContourTreeBlockData.h:73
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::NeighborOffsets
vtkm::worklet::contourtree_augmented::IdArrayType NeighborOffsets
Definition: ContourTreeBlockData.h:83
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::GlobalMeshIndex
vtkm::worklet::contourtree_augmented::IdArrayType GlobalMeshIndex
Definition: ContourTreeBlockData.h:81
Types.h
vtkm::worklet::contourtree_augmented::ContourTree
Definition: augmented/ContourTree.h:106
vtkm::worklet::contourtree_augmented::ContourTreeMesh::MergeWith
void MergeWith(ContourTreeMesh< FieldType > &other, vtkm::cont::LogLevel TreeLogLevel=vtkm::cont::LogLevel::Perf, std::string timingsMessage="")
Definition: ContourTreeMesh.h:612
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::MaxNeighbors
vtkm::Id MaxNeighbors
Definition: ContourTreeBlockData.h:84
vtkm::cont::ErrorFilterExecution
This class is primarily intended to filters to throw in the control environment to indicate an execut...
Definition: ErrorFilterExecution.h:27
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::NumVertices
vtkm::Id NumVertices
Definition: ContourTreeBlockData.h:79
vtkm::worklet::contourtree_augmented::ContourTreeMesh
Definition: ContourTreeMesh.h:129
vtkm::worklet::contourtree_augmented::ContourTreeMesh::SortIndices
vtkm::cont::ArrayHandleIndex SortIndices
Definition: ContourTreeMesh.h:198
vtkm::worklet::contourtree_augmented::ContourTreeMesh::MaxNeighbors
vtkm::Id MaxNeighbors
Definition: ContourTreeMesh.h:212
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::worklet::contourtree_augmented::ContourTreeMesh::NeighborConnectivity
IdArrayType NeighborConnectivity
Definition: ContourTreeMesh.h:207
vtkm::worklet::contourtree_augmented::ContourTree::Augmentarcs
IdArrayType Augmentarcs
Definition: augmented/ContourTree.h:133
vtkm::worklet::contourtree_augmented::ContourTreeMesh::NumVertices
vtkm::Id NumVertices
Definition: ContourTreeMesh.h:196
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::NeighborConnectivity
vtkm::worklet::contourtree_augmented::IdArrayType NeighborConnectivity
Definition: ContourTreeBlockData.h:82
ArrayHandleIndex.h
vtkm::worklet::contourtree_augmented::ContourTreeMesh::SortedValues
vtkm::cont::ArrayHandle< FieldType > SortedValues
Definition: ContourTreeMesh.h:199
Types.h
vtkm::worklet::contourtree_augmented::ContourTreeMesh::GetMeshBoundaryExecutionObject
MeshBoundaryContourTreeMeshExec GetMeshBoundaryExecutionObject(vtkm::Id3 globalSize, vtkm::Id3 minIdx, vtkm::Id3 maxIdx) const
Definition: ContourTreeMesh.h:1039
vtkm::worklet::contourtree_distributed::MergeBlockFunctor
void MergeBlockFunctor(vtkm::worklet::contourtree_distributed::ContourTreeBlockData< FieldType > *block, const vtkmdiy::ReduceProxy &rp, const vtkmdiy::RegularMergePartners &partners)
Definition: MergeBlockFunctor.h:75
vtkm::worklet::ContourTreeAugmented
Compute the contour tree for 2d and 3d uniform grids and arbitrary topology graphs.
Definition: worklet/ContourTreeUniformAugmented.h:89
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::BlockSize
vtkm::Id3 BlockSize
Definition: ContourTreeBlockData.h:88
vtkm::Vec< vtkm::Id, 3 >
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::ComputeRegularStructure
unsigned int ComputeRegularStructure
Definition: ContourTreeBlockData.h:90
vtkm::worklet::contourtree_augmented::ContourTreeMesh::SortOrder
vtkm::cont::ArrayHandleIndex SortOrder
Definition: ContourTreeMesh.h:197
vtkm::worklet::contourtree_augmented::ContourTree::Arcs
IdArrayType Arcs
Definition: augmented/ContourTree.h:115
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::SortedValue
vtkm::cont::ArrayHandle< FieldType > SortedValue
Definition: ContourTreeBlockData.h:80
vtkm::worklet::ContourTreeAugmented::Run
void Run(const vtkm::cont::ArrayHandle< FieldType, StorageType > fieldArray, MeshType &mesh, contourtree_augmented::ContourTree &contourTree, contourtree_augmented::IdArrayType &sortOrder, vtkm::Id &nIterations, unsigned int computeRegularStructure, const MeshBoundaryMeshExecType &meshBoundary)
Definition: worklet/ContourTreeUniformAugmented.h:127
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::BlockOrigin
vtkm::Id3 BlockOrigin
Definition: ContourTreeBlockData.h:87
vtkm::worklet::contourtree_augmented::ContourTreeMesh::NeighborOffsets
IdArrayType NeighborOffsets
Definition: ContourTreeMesh.h:210
vtkm::worklet::contourtree_distributed::ContourTreeBlockData::GlobalSize
vtkm::Id3 GlobalSize
Definition: ContourTreeBlockData.h:89
vtkm::cont::ArrayHandleIndex
An implicit array handle containing the its own indices.
Definition: ArrayHandleIndex.h:54
vtkm::worklet::contourtree_augmented::ContourTree::Augmentnodes
IdArrayType Augmentnodes
Definition: augmented/ContourTree.h:132