VTK-m  2.0
MeshBoundary3D.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 // This header contains a collection of classes used to describe the boundary
54 // of a mesh, for each main mesh type (i.e., 2D, 3D, and ContourTreeMesh).
55 // For each mesh type, there are two classes, the actual boundary desriptor
56 // class and an ExectionObject class with the PrepareForInput function that
57 // VTKm expects to generate the object for the execution environment.
58 
59 #ifndef vtk_m_worklet_contourtree_augmented_mesh_boundary_mesh_boundary_3d_h
60 #define vtk_m_worklet_contourtree_augmented_mesh_boundary_mesh_boundary_3d_h
61 
62 #include <cstdlib>
63 
66 
68 
69 namespace vtkm
70 {
71 namespace worklet
72 {
73 namespace contourtree_augmented
74 {
75 
77 {
78 public:
79  // Sort indicies types
81 
84  : MeshStructure(data_set_mesh::MeshStructure3D(vtkm::Id3{ 0, 0, 0 }))
85  {
86  }
87 
88  VTKM_CONT
90  const IdArrayType& inSortIndices,
92  vtkm::cont::Token& token)
93  : MeshStructure(data_set_mesh::MeshStructure3D(meshSize))
94  {
95  this->SortIndicesPortal = inSortIndices.PrepareForInput(device, token);
96  }
97 
99  bool LiesOnBoundary(const vtkm::Id meshIndex) const
100  {
101  const vtkm::Id3 pos = this->MeshStructure.VertexPos(meshIndex);
102  return (pos[0] == 0) || (pos[1] == 0) || (pos[2] == 0) ||
103  (pos[0] == this->MeshStructure.MeshSize[0] - 1) ||
104  (pos[1] == this->MeshStructure.MeshSize[1] - 1) ||
105  (pos[2] == this->MeshStructure.MeshSize[2] - 1);
106  }
107 
109  vtkm::Id CountLinkComponentsIn2DSlice(const vtkm::Id meshIndex, const vtkm::Id2 strides) const
110  {
111  // IMPORTANT: We assume that function is called only for *interior* vertices (i.e., neither row nor col
112  // within slice is 0 and we do not need to check for boundary cases).
113  vtkm::Id sortIndex = this->SortIndicesPortal.Get(meshIndex);
114  bool prevWasInUpperLink = false;
115  vtkm::Id numComponents = 0;
116 
117  const int N_INCIDENT_EDGES_2D = 6;
118  for (vtkm::Id edgeNo = 0; edgeNo < N_INCIDENT_EDGES_2D; edgeNo++)
119  { // per edge
120  VTKM_ASSERT(meshIndex + strides[1] + strides[0] <
121  this->SortIndicesPortal.GetNumberOfValues());
122  VTKM_ASSERT(meshIndex - strides[1] - strides[0] >= 0);
123  vtkm::Id nbrSortIndex;
124  switch (edgeNo)
125  {
126  case 0:
127  nbrSortIndex = this->SortIndicesPortal.Get(meshIndex + strides[0]);
128  break; // [1] , [0] + 1
129  case 1:
130  nbrSortIndex = this->SortIndicesPortal.Get(meshIndex + strides[1] + strides[0]);
131  break; // [1] + 1, [0] + 1
132  case 2:
133  nbrSortIndex = this->SortIndicesPortal.Get(meshIndex + strides[1]);
134  break; // [1] + 1, [0]
135  case 3:
136  nbrSortIndex = this->SortIndicesPortal.Get(meshIndex - strides[0]);
137  break; // [1] , [0] - 1
138  case 4:
139  nbrSortIndex = this->SortIndicesPortal.Get(meshIndex - strides[1] - strides[0]);
140  break; // [1] - 1, [0] - 1
141  case 5:
142  nbrSortIndex = this->SortIndicesPortal.Get(meshIndex - strides[1]);
143  break; // [1] - 1, [0]
144  default:
145  // Due to CUDA we cannot throw an exception here, which would make the most
146  // sense
147  VTKM_ASSERT(false); // Should not occur, edgeNo < N_INCIDENT_EDGES_2D = 6
148  // Initialize nbrSortIndex to something anyway to prevent compiler warning
149  // Set to the sort index of the vertex itself since there is "no" edge so
150  // that it contains a "sane" value if it should ever be reached.
151  nbrSortIndex = this->SortIndicesPortal.Get(meshIndex);
152  break;
153  }
154 
155  bool currIsInUpperLink = (nbrSortIndex > sortIndex);
156  numComponents += (edgeNo != 0 && currIsInUpperLink != prevWasInUpperLink) ? 1 : 0;
157  } // per edge
158  return numComponents;
159  }
160 
162  bool IsNecessary(vtkm::Id meshIndex) const
163  {
164  vtkm::Id sortIndex = this->SortIndicesPortal.Get(meshIndex);
165  vtkm::Id3 pos{ this->MeshStructure.VertexPos(meshIndex) };
166  vtkm::Id nPerSlice = this->MeshStructure.MeshSize[0] *
167  this->MeshStructure.MeshSize[1]; // number of vertices on a [2]-perpendicular "slice"
168 
169  // Keep only when lying on boundary
170  if ((pos[1] == 0) || (pos[0] == 0) || (pos[2] == 0) ||
171  (pos[1] == this->MeshStructure.MeshSize[1] - 1) ||
172  (pos[0] == this->MeshStructure.MeshSize[0] - 1) ||
173  (pos[2] == this->MeshStructure.MeshSize[2] - 1))
174  {
175  // Keep data on corners
176  bool atEndOfLine = (pos[0] == 0) || (pos[0] == this->MeshStructure.MeshSize[0] - 1);
177  bool atQuadCorner = (pos[1] == 0 && atEndOfLine) ||
178  (pos[1] == this->MeshStructure.MeshSize[1] - 1 && atEndOfLine);
179  if ((pos[2] == 0 && atQuadCorner) ||
180  (pos[2] == this->MeshStructure.MeshSize[2] - 1 && atQuadCorner))
181  {
182  return true;
183  }
184  else
185  {
186  // Check if vertex lies along one of the boundary edges, if so, keep
187  // local extrema
188  // Edges in [0] direction
189  if ((pos[1] == 0 && pos[2] == 0) ||
190  (pos[1] == 0 && pos[2] == this->MeshStructure.MeshSize[2] - 1) ||
191  (pos[1] == this->MeshStructure.MeshSize[1] - 1 && pos[2] == 0) ||
192  (pos[1] == this->MeshStructure.MeshSize[1] - 1 &&
193  pos[2] == this->MeshStructure.MeshSize[2] - 1))
194  {
195  VTKM_ASSERT(meshIndex >= 1);
196  vtkm::Id sp = this->SortIndicesPortal.Get(meshIndex - 1);
197  VTKM_ASSERT(meshIndex + 1 < this->SortIndicesPortal.GetNumberOfValues());
198  vtkm::Id sn = this->SortIndicesPortal.Get(meshIndex + 1);
199  return (sortIndex < sp && sortIndex < sn) || (sortIndex > sp && sortIndex > sn);
200  }
201  // Edges in [1] directtion
202  else if ((pos[0] == 0 && pos[2] == 0) ||
203  (pos[0] == 0 && pos[2] == this->MeshStructure.MeshSize[2] - 1) ||
204  (pos[0] == this->MeshStructure.MeshSize[0] - 1 && pos[2] == 0) ||
205  (pos[0] == this->MeshStructure.MeshSize[0] - 1 &&
206  pos[2] == this->MeshStructure.MeshSize[2] - 1))
207  {
208  VTKM_ASSERT(pos[1] > 0 && pos[1] < this->MeshStructure.MeshSize[1] - 1);
209  VTKM_ASSERT(meshIndex >= this->MeshStructure.MeshSize[0]);
210  vtkm::Id sp = this->SortIndicesPortal.Get(meshIndex - this->MeshStructure.MeshSize[0]);
211  VTKM_ASSERT(meshIndex + this->MeshStructure.MeshSize[0] <
212  this->SortIndicesPortal.GetNumberOfValues());
213  vtkm::Id sn = this->SortIndicesPortal.Get(meshIndex + this->MeshStructure.MeshSize[0]);
214  return (sortIndex < sp && sortIndex < sn) || (sortIndex > sp && sortIndex > sn);
215  }
216  // Edges in [2] direction
217  else if ((pos[1] == 0 && pos[0] == 0) ||
218  (pos[1] == 0 && pos[0] == this->MeshStructure.MeshSize[0] - 1) ||
219  (pos[1] == this->MeshStructure.MeshSize[1] - 1 && pos[0] == 0) ||
220  (pos[1] == this->MeshStructure.MeshSize[1] - 1 &&
221  pos[0] == this->MeshStructure.MeshSize[0] - 1))
222  {
223  VTKM_ASSERT(meshIndex >= nPerSlice);
224  vtkm::Id sp = this->SortIndicesPortal.Get(meshIndex - nPerSlice);
225  VTKM_ASSERT(meshIndex + nPerSlice < this->SortIndicesPortal.GetNumberOfValues());
226  vtkm::Id sn = this->SortIndicesPortal.Get(meshIndex + nPerSlice);
227  return (sortIndex < sp && sortIndex < sn) || (sortIndex > sp && sortIndex > sn);
228  }
229  else
230  {
231  // On a face/slice
232  if (pos[2] == 0 || pos[2] == this->MeshStructure.MeshSize[2] - 1)
233  { // On [2]-perpendicular face
234  VTKM_ASSERT(pos[0] != 0 && pos[0] != this->MeshStructure.MeshSize[0]);
235  VTKM_ASSERT(pos[1] != 0 && pos[1] != this->MeshStructure.MeshSize[1]);
236  return CountLinkComponentsIn2DSlice(meshIndex,
237  vtkm::Id2(1, this->MeshStructure.MeshSize[0])) != 2;
238  }
239  else if (pos[1] == 0 || pos[1] == this->MeshStructure.MeshSize[1] - 1)
240  { // On [1]-perpendicular face
241  VTKM_ASSERT(pos[0] != 0 && pos[0] != this->MeshStructure.MeshSize[0]);
242  VTKM_ASSERT(pos[2] != 0 && pos[2] != this->MeshStructure.MeshSize[2]);
243  return CountLinkComponentsIn2DSlice(meshIndex, vtkm::Id2(1, nPerSlice)) != 2;
244  }
245  else
246  { // On [0]-perpendicular face
247  VTKM_ASSERT(pos[0] == 0 || pos[0] == this->MeshStructure.MeshSize[0] - 1);
248  VTKM_ASSERT(pos[1] != 0 && pos[1] != this->MeshStructure.MeshSize[1]);
249  VTKM_ASSERT(pos[2] != 0 && pos[2] != this->MeshStructure.MeshSize[2]);
251  meshIndex, vtkm::Id2(nPerSlice, this->MeshStructure.MeshSize[0])) != 2;
252  }
253  }
254  }
255  }
256  else
257  {
258  return false;
259  }
260  }
261 
264 
265 protected:
266  // 3D Mesh size parameters
269 };
270 
271 
273 {
274 public:
276  MeshBoundary3DExec(vtkm::Id3 meshSize, const IdArrayType& inSortIndices)
277  : MeshSize(meshSize)
278  , SortIndices(inSortIndices)
279  {
280  }
281 
283  vtkm::cont::Token& token) const
284  {
285  return MeshBoundary3D(this->MeshSize, this->SortIndices, device, token);
286  }
287 
288 protected:
289  // 3D Mesh size parameters
292 };
293 
294 
295 } // namespace contourtree_augmented
296 } // worklet
297 } // vtkm
298 
299 #endif
vtkm::worklet::contourtree_augmented::MeshBoundary3DExec
Definition: MeshBoundary3D.h:272
vtkm::cont::ArrayHandle< vtkm::Id >
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
vtkm::worklet::contourtree_augmented::MeshBoundary3D::IsNecessary
VTKM_EXEC_CONT bool IsNecessary(vtkm::Id meshIndex) const
Definition: MeshBoundary3D.h:162
vtkm::cont::ArrayHandle::PrepareForInput
VTKM_CONT ReadPortalType PrepareForInput(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Prepares this array to be used as an input to an operation in the execution environment.
Definition: ArrayHandle.h:574
vtkm::worklet::contourtree_augmented::MeshBoundary3D::SortIndicesPortalType
IdArrayType::ReadPortalType SortIndicesPortalType
Definition: MeshBoundary3D.h:80
vtkm::worklet::contourtree_augmented::MeshBoundary3DExec::SortIndices
const IdArrayType & SortIndices
Definition: MeshBoundary3D.h:291
vtkm::worklet::contourtree_augmented::MeshBoundary3D
Definition: MeshBoundary3D.h:76
vtkm::cont::ArrayHandle< vtkm::Id >::ReadPortalType
typename StorageType::ReadPortalType ReadPortalType
Definition: ArrayHandle.h:294
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::worklet::contourtree_augmented::data_set_mesh::MeshStructure3D::VertexPos
VTKM_EXEC vtkm::Id3 VertexPos(vtkm::Id v) const
Definition: MeshStructure3D.h:91
vtkm::worklet::contourtree_augmented::MeshBoundary3D::MeshStructure
data_set_mesh::MeshStructure3D MeshStructure
Definition: MeshBoundary3D.h:267
vtkm::worklet::contourtree_augmented::MeshBoundary3D::MeshBoundary3D
VTKM_EXEC_CONT MeshBoundary3D()
Definition: MeshBoundary3D.h:83
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
vtkm::worklet::contourtree_augmented::MeshBoundary3DExec::MeshBoundary3DExec
VTKM_EXEC_CONT MeshBoundary3DExec(vtkm::Id3 meshSize, const IdArrayType &inSortIndices)
Definition: MeshBoundary3D.h:276
vtkm::worklet::contourtree_augmented::MeshBoundary3DExec::PrepareForExecution
VTKM_CONT MeshBoundary3D PrepareForExecution(vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token) const
Definition: MeshBoundary3D.h:282
Types.h
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::worklet::contourtree_augmented::MeshBoundary3D::SortIndicesPortal
SortIndicesPortalType SortIndicesPortal
Definition: MeshBoundary3D.h:268
vtkm::worklet::contourtree_augmented::data_set_mesh::MeshStructure3D::MeshSize
vtkm::Id3 MeshSize
Definition: MeshStructure3D.h:137
vtkm::worklet::contourtree_augmented::MeshBoundary3D::CountLinkComponentsIn2DSlice
VTKM_EXEC_CONT vtkm::Id CountLinkComponentsIn2DSlice(const vtkm::Id meshIndex, const vtkm::Id2 strides) const
Definition: MeshBoundary3D.h:109
vtkm::cont::ExecutionObjectBase
Base ExecutionObjectBase for execution objects to inherit from so that you can use an arbitrary objec...
Definition: ExecutionObjectBase.h:31
vtkm::cont::DeviceAdapterId
Definition: DeviceAdapterTag.h:52
vtkm::Vec< vtkm::Id, 3 >
vtkm::worklet::contourtree_augmented::MeshBoundary3D::LiesOnBoundary
VTKM_EXEC_CONT bool LiesOnBoundary(const vtkm::Id meshIndex) const
Definition: MeshBoundary3D.h:99
vtkm::worklet::contourtree_augmented::data_set_mesh::MeshStructure3D
Definition: MeshStructure3D.h:68
MeshStructure3D.h
vtkm::worklet::contourtree_augmented::MeshBoundary3D::GetMeshStructure
const VTKM_EXEC_CONT data_set_mesh::MeshStructure3D & GetMeshStructure() const
Definition: MeshBoundary3D.h:263
vtkm::worklet::contourtree_augmented::MeshBoundary3DExec::MeshSize
vtkm::Id3 MeshSize
Definition: MeshBoundary3D.h:290
ExecutionObjectBase.h
vtkm::worklet::contourtree_augmented::MeshBoundary3D::MeshBoundary3D
VTKM_CONT MeshBoundary3D(vtkm::Id3 meshSize, const IdArrayType &inSortIndices, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token)
Definition: MeshBoundary3D.h:89