VTK-m  2.0
MeshStructureFreudenthal2D.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_augmented_meshtypes_MeshStructureFreudenthal2D_h
54 #define vtk_m_worklet_contourtree_augmented_meshtypes_MeshStructureFreudenthal2D_h
55 
56 #include <vtkm/Pair.h>
57 #include <vtkm/Types.h>
58 #include <vtkm/cont/ArrayHandle.h>
62 
63 
64 namespace vtkm
65 {
66 namespace worklet
67 {
68 namespace contourtree_augmented
69 {
70 
71 // Worklet for computing the sort indices from the sort order
73 {
74 public:
77  m2d_freudenthal::EdgeBoundaryDetectionMasksType::ReadPortalType;
78 
79  // Default constucture. Needed for the CUDA built to work
82  : data_set_mesh::MeshStructure2D()
83  , GetMax(false)
84  , NumIncidentEdges(m2d_freudenthal::N_INCIDENT_EDGES)
85  {
86  }
87 
88  // Main constructor used in the code
90  vtkm::Id2 meshSize,
91  vtkm::Int32 nincident_edges,
92  bool getmax,
93  const IdArrayType& sortIndices,
94  const IdArrayType& SortOrder,
95  const m2d_freudenthal::EdgeBoundaryDetectionMasksType& EdgeBoundaryDetectionMasksIn,
97  vtkm::cont::Token& token)
98  : data_set_mesh::MeshStructure2D(meshSize)
99  , GetMax(getmax)
100  , NumIncidentEdges(nincident_edges)
101  {
102  this->SortIndicesPortal = sortIndices.PrepareForInput(device, token);
103  this->SortOrderPortal = SortOrder.PrepareForInput(device, token);
105  EdgeBoundaryDetectionMasksIn.PrepareForInput(device, token);
106  }
107 
108  VTKM_EXEC
109  vtkm::Id GetMaxNumberOfNeighbours() const { return m2d_freudenthal::N_INCIDENT_EDGES; }
110 
111  VTKM_EXEC
112  inline vtkm::Id GetNeighbourIndex(vtkm::Id sortIndex, vtkm::Id edgeNo) const
113  { // GetNeighbourIndex
114  vtkm::Id meshIndex = this->SortOrderPortal.Get(sortIndex);
115  switch (edgeNo)
116  {
117  case 0:
118  return this->SortIndicesPortal.Get(meshIndex + 1); // [1] , [0] + 1
119  case 1:
120  return this->SortIndicesPortal.Get(meshIndex + this->MeshSize[0] + 1); // [1] + 1, [0] + 1
121  case 2:
122  return this->SortIndicesPortal.Get(meshIndex + this->MeshSize[0]); // [1] + 1, [0]
123  case 3:
124  return this->SortIndicesPortal.Get(meshIndex - 1); // [1] , [0] - 1
125  case 4:
126  return this->SortIndicesPortal.Get(meshIndex - this->MeshSize[0] - 1); // [1] - 1, [0] - 1
127  case 5:
128  return this->SortIndicesPortal.Get(meshIndex - this->MeshSize[0]); // [1] - 1, [0]
129  default:
130  return -1; // TODO How to generate a meaningful error message from a device (in particular when using CUDA?)
131  }
132  } // GetNeighbourIndex
133 
134 // Disable conversion warnings for Add, Subtract, Multiply, Divide on GCC only.
135 // GCC creates false positive warnings for signed/unsigned char* operations.
136 // This occurs because the values are implicitly casted up to int's for the
137 // operation, and than casted back down to char's when return.
138 // This causes a false positive warning, even when the values is within
139 // the value types range
140 #if (defined(VTKM_GCC) || defined(VTKM_CLANG))
141 #pragma GCC diagnostic push
142 #pragma GCC diagnostic ignored "-Wconversion"
143 #endif // gcc || clang
144 
145  // sets outgoing paths for saddles
146  VTKM_EXEC
147  inline vtkm::Id GetExtremalNeighbour(vtkm::Id sortIndex) const
148  { // GetExtremalNeighbour()
149  using namespace m2d_freudenthal;
150  // convert to a mesh index
151  vtkm::Id meshIndex = SortOrderPortal.Get(sortIndex);
152 
153  // get the row and column
154  vtkm::Id2 pos = this->VertexPos(meshIndex);
155  vtkm::Int8 boundaryConfig = ((pos[0] == 0) ? LeftBit : 0) |
156  ((pos[0] == this->MeshSize[0] - 1) ? RightBit : 0) | ((pos[1] == 0) ? TopBit : 0) |
157  ((pos[1] == this->MeshSize[1] - 1) ? BottomBit : 0);
158 
159  // in what follows, the boundary conditions always reset wasAscent
160  for (vtkm::Id edgeNo = 0; edgeNo < this->NumIncidentEdges; edgeNo++)
161  { // per edge
162  // ignore if at edge of data
163  if (!(boundaryConfig & EdgeBoundaryDetectionMasksPortal.Get(edgeNo)))
164  {
165  // calculate neighbour's ID and sort order
166  vtkm::Id nbrSortIndex = GetNeighbourIndex(sortIndex, edgeNo);
167 
168  // if it's not a valid destination, ignore it
169  if (GetMax ? (nbrSortIndex > sortIndex) : (nbrSortIndex < sortIndex))
170  {
171  // and save the destination
172  return nbrSortIndex;
173  }
174  }
175  } // per edge
176  return sortIndex | TERMINAL_ELEMENT;
177  } // GetExtremalNeighbour()
178 
179 
180  // NOTE/FIXME: The following also iterates over all values and could be combined with GetExtremalNeighbour(). However, the
181  // results are needed at different places and splitting the two functions leads to a cleaner design
182  VTKM_EXEC
184  vtkm::Id sortIndex,
185  bool getMaxComponents) const
186  { // GetNeighbourComponentsMaskAndDegree()
187  using namespace m2d_freudenthal;
188  // get data portals
189  // convert to a mesh index
190  vtkm::Id meshIndex = SortOrderPortal.Get(sortIndex);
191 
192  // get the row and column
193  vtkm::Id2 pos = this->VertexPos(meshIndex);
194  vtkm::Int8 boundaryConfig = ((pos[0] == 0) ? LeftBit : 0) |
195  ((pos[0] == this->MeshSize[0] - 1) ? RightBit : 0) | ((pos[1] == 0) ? TopBit : 0) |
196  ((pos[1] == this->MeshSize[1] - 1) ? BottomBit : 0);
197 
198  // and initialise the mask
199  vtkm::Id neighbourhoodMask = 0;
200  // in what follows, the boundary conditions always reset wasAscent
201  for (vtkm::Id edgeNo = 0; edgeNo < N_INCIDENT_EDGES; edgeNo++)
202  { // per edge
203  // ignore if at edge of data
204  if (!(boundaryConfig & EdgeBoundaryDetectionMasksPortal.Get(edgeNo)))
205  {
206  // calculate neighbour's ID and sort order
207  vtkm::Id nbrSortIndex = GetNeighbourIndex(sortIndex, edgeNo);
208 
209  // if it's not a valid destination, ignore it
210  if (getMaxComponents ? (nbrSortIndex > sortIndex) : (nbrSortIndex < sortIndex))
211  {
212  // now set the flag in the neighbourhoodMask
213  neighbourhoodMask |= vtkm::Id{ 1 } << edgeNo;
214  }
215  }
216  } // per edge
217 
218  // we now know which edges are outbound, so we count to get the outdegree
219  vtkm::Id outDegree = 0;
220  vtkm::Id neighbourComponentMask = 0;
221  // special case for local minimum
222  if (neighbourhoodMask == 0x3F)
223  {
224  outDegree = 1;
225  }
226  else
227  { // not a local minimum
228  if ((neighbourhoodMask & 0x30) == 0x20)
229  {
230  ++outDegree;
231  neighbourComponentMask |= vtkm::Id{ 1 } << 5;
232  }
233  if ((neighbourhoodMask & 0x18) == 0x10)
234  {
235  ++outDegree;
236  neighbourComponentMask |= vtkm::Id{ 1 } << 4;
237  }
238  if ((neighbourhoodMask & 0x0C) == 0x08)
239  {
240  ++outDegree;
241  neighbourComponentMask |= vtkm::Id{ 1 } << 3;
242  }
243  if ((neighbourhoodMask & 0x06) == 0x04)
244  {
245  ++outDegree;
246  neighbourComponentMask |= vtkm::Id{ 1 } << 2;
247  }
248  if ((neighbourhoodMask & 0x03) == 0x02)
249  {
250  ++outDegree;
251  neighbourComponentMask |= vtkm::Id{ 1 } << 1;
252  }
253  if ((neighbourhoodMask & 0x21) == 0x01)
254  {
255  ++outDegree;
256  neighbourComponentMask |= vtkm::Id{ 1 } << 0;
257  }
258  } // not a local minimum
259  vtkm::Pair<vtkm::Id, vtkm::Id> re(neighbourComponentMask, outDegree);
260  return re;
261  } // GetNeighbourComponentsMaskAndDegree()
262 
263 #if (defined(VTKM_GCC) || defined(VTKM_CLANG))
264 #pragma GCC diagnostic pop
265 #endif // gcc || clang
266 
267 private:
271  bool GetMax;
273 
274 }; // ExecutionObjec_MeshStructure_3Dt
275 
276 } // namespace contourtree_augmented
277 } // namespace worklet
278 } // namespace vtkm
279 
280 #endif
vtkm::cont::ArrayHandle< vtkm::Id >
ArrayHandle.h
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::SortIndicesPortal
SortIndicesPortalType SortIndicesPortal
Definition: MeshStructureFreudenthal2D.h:268
Types.h
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
vtkm::worklet::contourtree_augmented::m2d_freudenthal::EdgeBoundaryDetectionMasksType
typename vtkm::cont::ArrayHandle< vtkm::Int8 > EdgeBoundaryDetectionMasksType
Definition: filter/scalar_topology/worklet/contourtree_augmented/meshtypes/freudenthal_2D/Types.h:68
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
Pair.h
N_INCIDENT_EDGES
#define N_INCIDENT_EDGES
Definition: Mesh2D_DEM_Triangulation_Macros.h:75
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::MeshStructureFreudenthal2D
VTKM_EXEC_CONT MeshStructureFreudenthal2D()
Definition: MeshStructureFreudenthal2D.h:81
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::EdgeBoundaryDetectionMasksPortalType
m2d_freudenthal::EdgeBoundaryDetectionMasksType::ReadPortalType EdgeBoundaryDetectionMasksPortalType
Definition: MeshStructureFreudenthal2D.h:77
vtkm::worklet::contourtree_augmented::TERMINAL_ELEMENT
constexpr vtkm::Id TERMINAL_ELEMENT
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:74
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::EdgeBoundaryDetectionMasksPortal
EdgeBoundaryDetectionMasksPortalType EdgeBoundaryDetectionMasksPortal
Definition: MeshStructureFreudenthal2D.h:270
vtkm::worklet::contourtree_augmented::data_set_mesh::MeshStructure2D
Definition: MeshStructure2D.h:69
vtkm::worklet::contourtree_augmented::data_set_mesh::MeshStructure2D::VertexPos
VTKM_EXEC vtkm::Id2 VertexPos(vtkm::Id v) const
Get the (x,y) position of the vertex based on its index.
Definition: MeshStructure2D.h:90
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
MeshStructure2D.h
vtkm::cont::Token
A token to hold the scope of an ArrayHandle or other object.
Definition: Token.h:35
vtkm::worklet::contourtree_augmented::data_set_mesh::MeshStructure2D::MeshStructure2D
VTKM_EXEC_CONT MeshStructure2D()
Definition: MeshStructure2D.h:73
vtkm::Int8
int8_t Int8
Definition: Types.h:156
Types.h
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::GetNeighbourComponentsMaskAndDegree
VTKM_EXEC vtkm::Pair< vtkm::Id, vtkm::Id > GetNeighbourComponentsMaskAndDegree(vtkm::Id sortIndex, bool getMaxComponents) const
Definition: MeshStructureFreudenthal2D.h:183
Types.h
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::GetMaxNumberOfNeighbours
VTKM_EXEC vtkm::Id GetMaxNumberOfNeighbours() const
Definition: MeshStructureFreudenthal2D.h:109
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D
Definition: MeshStructureFreudenthal2D.h:72
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::GetExtremalNeighbour
VTKM_EXEC vtkm::Id GetExtremalNeighbour(vtkm::Id sortIndex) const
Definition: MeshStructureFreudenthal2D.h:147
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::MeshStructureFreudenthal2D
MeshStructureFreudenthal2D(vtkm::Id2 meshSize, vtkm::Int32 nincident_edges, bool getmax, const IdArrayType &sortIndices, const IdArrayType &SortOrder, const m2d_freudenthal::EdgeBoundaryDetectionMasksType &EdgeBoundaryDetectionMasksIn, vtkm::cont::DeviceAdapterId device, vtkm::cont::Token &token)
Definition: MeshStructureFreudenthal2D.h:89
vtkm::cont::DeviceAdapterId
Definition: DeviceAdapterTag.h:52
vtkm::Vec< vtkm::Id, 2 >
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::NumIncidentEdges
vtkm::Id NumIncidentEdges
Definition: MeshStructureFreudenthal2D.h:272
vtkm::Int32
int32_t Int32
Definition: Types.h:160
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::SortIndicesPortalType
IdArrayType::ReadPortalType SortIndicesPortalType
Definition: MeshStructureFreudenthal2D.h:75
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::GetNeighbourIndex
VTKM_EXEC vtkm::Id GetNeighbourIndex(vtkm::Id sortIndex, vtkm::Id edgeNo) const
Definition: MeshStructureFreudenthal2D.h:112
vtkm::worklet::contourtree_augmented::data_set_mesh::MeshStructure2D::MeshSize
vtkm::Id2 MeshSize
Definition: MeshStructure2D.h:126
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::SortOrderPortal
SortIndicesPortalType SortOrderPortal
Definition: MeshStructureFreudenthal2D.h:269
vtkm::Pair
A vtkm::Pair is essentially the same as an STL pair object except that the methods (constructors and ...
Definition: Pair.h:29
vtkm::worklet::contourtree_augmented::MeshStructureFreudenthal2D::GetMax
bool GetMax
Definition: MeshStructureFreudenthal2D.h:271