VTK-m  2.0
GetHierarchicalIdsWorklet.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_tree_grafter_get_hierarchical_ids_worklet_h
54 #define vtk_m_worklet_contourtree_distributed_tree_grafter_get_hierarchical_ids_worklet_h
55 
58 
59 namespace vtkm
60 {
61 namespace worklet
62 {
63 namespace contourtree_distributed
64 {
65 namespace tree_grafter
66 {
67 
68 // Worklet for retrieving correct Ids from hierarchical tree
70 {
71 public:
72  // TODO: Need to decide for which we can use FieldIn/FieldOut instead of requiring transfer of the WholeArrayIn/Out
73  using ControlSignature = void(
74  // input (read-only) array
75  FieldIn supernodes,
76 
77  // reference (read-only) arrays
78  FieldIn supernodeGlobalId,
79  WholeArrayIn sortOrder,
80  WholeArrayIn dataValue,
81  FieldIn necessary,
82  FieldIn above,
83  FieldIn below,
84  WholeArrayIn superparents,
85  WholeArrayIn hyperparents,
86  WholeArrayIn regular2Supernode,
87  WholeArrayIn super2Hypernode,
88  // Execution object to use the FindRegularByGlobal and FindSuperArcForUnknownNode for the hierarchical tree.
89  ExecObject findRegularByGlobal,
90  ExecObject findSuperArcForUnknownNode,
91 
92  // output (write-only) arrays
93  // NOTE: not all fileds are always updated in the operator.
94  // We, therfore, need to use FieldInOut to make sure the original value (typical NO_SUCH_ELEMTENT)
95  // is not being overwritten (when just using FieldOut VTKm sets the value to 0)
96  // TODO: We could potentially avoid the need for FieldInOut by always setting hierarchicalSuperId and hierarchicalHyperId to NO_SUCH_ELEMENT at the beginning
97  FieldInOut hierarchicalRegularId,
98  FieldInOut hierarchicalSuperId,
99  FieldInOut hierarchicalHyperId,
100  FieldInOut hierarchicalSuperparent,
101  FieldInOut hierarchicalHyperparent);
102 
103  using ExecutionSignature =
104  void(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18);
105  using InputDomain = _1;
106 
107  // Default Constructor
110 
111  // TODO: Discuss with Oliver when it's a ID, when it's a portal and when it's a reference
112  template <typename InFieldPortalType,
113  typename SortOrderPortalType,
114  typename InFieldDataPortalType,
115  typename FindRegularExecType,
116  typename FindSuperExecType>
118  // const vtkm::Id& supernode, // not used
119  const vtkm::Id& oldSortId, // i.e, supernodes[supernode]
120  const vtkm::Id&
121  supernodeGlobalIdVal, // Depending on the mesh we may get a different fany array handle
122  const SortOrderPortalType&
123  sortOrder, // Depending on the mesh we may get a different fany array handle
124  const InFieldDataPortalType& dataValues,
125  const vtkm::Id& necessary,
126  const vtkm::Id& upGlobalId, // = above[supernode]
127  const vtkm::Id& dnGlobalId, // = below[supernode]
128  const InFieldPortalType& superparents,
129  const InFieldPortalType& hyperparents,
130  const InFieldPortalType& regular2Supernode,
131  const InFieldPortalType& super2Hypernode,
132  const FindRegularExecType& findRegularByGlobal,
133  const FindSuperExecType& findSuperArcForUnknownNode,
134  vtkm::Id& hierarchicalRegularId,
135  vtkm::Id& hierarchicalSuperId,
136  vtkm::Id& hierarchicalHyperId,
137  vtkm::Id& hierarchicalSuperparent,
138  vtkm::Id& hierarchicalHyperparent) const
139  { // operator ()
140 
141  // TODO: Need to check that this code is correct
142  // TODO: Discuss with Oliver how to use the FindRegularByGlobal function
143  vtkm::Id regularId = findRegularByGlobal.FindRegularByGlobal(supernodeGlobalIdVal);
144 
145  // save the regular Id
146  hierarchicalRegularId = regularId; // set return value
147 
148  // Free supernode: if it was necessary, then it's potentially an attachment point
150  // Super = NSE, Regular = NSE:
151  { // no such element regular or super
152  // not marked as necessary: cannot be an attachment point
153  if (!necessary)
154  {
155  return;
156  }
157 
158  // it was marked as necessary, but got regularised & therefore not a regular point in the parent
159  // this means we are guaranteed that we have a valid up/down neighbour pair from our BRACT construction
160  // and that the up/down neighbour pair are guaranteed to be at least regular in the hierarchical tree
161  // vtkm::Id oldSortId = supernodes.Get(supernode);
162  vtkm::Id oldRegularId = sortOrder.Get(oldSortId);
163  auto dataValue = dataValues.Get(oldRegularId);
164 
165  vtkm::Id upHierarchicalId = findRegularByGlobal.FindRegularByGlobal(upGlobalId);
166 
167  vtkm::Id dnHierarchicalId = findRegularByGlobal.FindRegularByGlobal(dnGlobalId);
168 
169  vtkm::Id superparentInHierarchy = findSuperArcForUnknownNode.FindSuperArcForUnknownNode(
170  supernodeGlobalIdVal, dataValue, upHierarchicalId, dnHierarchicalId);
171  hierarchicalSuperparent = superparentInHierarchy; // set return value
172  hierarchicalHyperparent = hyperparents.Get(superparentInHierarchy); // set return value
173  } // no such element regular or super
174  else
175  { // regular Id exists
176  // we want to know if the regular node has a superId. This is straightforward, since we have a lookup array
177  vtkm::Id supernodeId = regular2Supernode.Get(regularId);
178  vtkm::Id superparent = superparents.Get(regularId);
179 
180  // if there is no superId yet, we will need to set one up
182  { // no supernode Id: regular but not super
183  // We have a supernode in the lower level tree (which excludes boundary regular vertices from consideration)
184  // This occurred AFTER regularisation, so either:
185  // a) it was regularised, but is a boundary vertex and was therefore kept, or
186  // b) it was not regularised, but is not critical once other blocks have been considered
187  // In either case, it is now needed and must be inserted as an attachment point
188  // Note that regularised interior attachment points are dealt with later
189  // We assume as an invariant that all regular points in the hierarchical tree already have superparent correctly set
190  // This means we know which superarc it belongs to, and therefore which hyperarc, so we take that as the insertion parent
191  vtkm::Id hierSuperparent =
192  vtkm::worklet::contourtree_augmented::MaskedIndex(superparents.Get(regularId));
193  // this is logically redundant since we won't use it, but it'll make debug easier
194  hierarchicalSuperparent = hierSuperparent; // set return value
195  hierarchicalHyperparent = hyperparents.Get(hierSuperparent); // set return value
196  } // no supernode Id: regular but not super
197  else
198  { // supernode Id exists
199  // save the supernode Id
200  hierarchicalSuperId = supernodeId; // Set return value
201 
202  // we can also set the superparent & hyperparent at this point
203  hierarchicalSuperparent = superparent; // set return value
204  hierarchicalHyperparent = hyperparents.Get(supernodeId); // set return value
205 
206  // now retrieve the hypernode Id (if any) & store it (even if it is already NO_SUCH_ELEMENT)
207  hierarchicalHyperId = super2Hypernode.Get(supernodeId); // set return value
208  } // supernode Id exists
209  } // regular Id exists
210 
211  // In serial this worklet implements the following operation
212  /*
213  // down-convert to a global ID
214  // search in the hierarchy to find the regular ID
215  indexType regularID = hierTree.FindRegularByGlobal(supernodeGlobalID[supernode]);
216  hierarchicalRegularID[supernode] = regularID;
217 
218  // Free supernode: if it was necessary, then it's potentially an attachment point
219  if (noSuchElement(regularID))
220  // Super = NSE, Regular = NSE:
221  { // no such element regular or super
222  // not marked as necessary: cannot be an attachment point
223  if (!residue->isNecessary[supernode])
224  continue;
225 
226  // it was marked as necessary, but got regularised & therefore not a regular point in the parent
227  // this means we are guaranteed that we have a valid up/down neighbour pair from our BRACT construction
228  // and that the up/down neighbour pair are guaranteed to be at least regular in the hierarchical tree
229  indexType oldSortID = contourTree->supernodes[supernode];
230  indexType oldRegularID = mesh->SortOrder(oldSortID);
231  dataType dataValue = mesh->DataValue(oldRegularID);
232 
233  indexType upGlobalID = residue->above[supernode];
234  indexType upHierarchicalID = hierTree.FindRegularByGlobal(upGlobalID);
235 
236  indexType dnGlobalID = residue->below[supernode];
237  indexType dnHierarchicalID = hierTree.FindRegularByGlobal(dnGlobalID);
238 
239  indexType superparentInHierarchy = hierTree.FindSuperArcForUnknownNode(supernodeGlobalID[supernode], dataValue, upHierarchicalID, dnHierarchicalID);
240  hierarchicalSuperparent[supernode] = superparentInHierarchy;
241  hierarchicalHyperparent[supernode] = hierTree.hyperparents[superparentInHierarchy];
242  } // no such element regular or super
243  else
244  { // regular ID exists
245  // we want to know if the regular node has a superID. This is straightforward, since we have a lookup array
246  indexType supernodeID = hierTree.regular2supernode[regularID];
247  indexType superparent = hierTree.superparents[regularID];
248 
249  // if there is no superID yet, we will need to set one up
250  if (noSuchElement(supernodeID))
251  { // no supernode ID: regular but not super
252  // We have a supernode in the lower level tree (which excludes boundary regular vertices from consideration)
253  // This occurred AFTER regularisation, so either:
254  // a) it was regularised, but is a boundary vertex and was therefore kept, or
255  // b) it was not regularised, but is not critical once other blocks have been considered
256  // In either case, it is now needed and must be inserted as an attachment point
257  // Note that regularised interior attachment points are dealt with later
258  // We assume as an invariant that all regular points in the hierarchical tree already have superparent correctly set
259  // This means we know which superarc it belongs to, and therefore which hyperarc, so we take that as the insertion parent
260  indexType hierSuperparent = maskedIndex(hierTree.superparents[regularID]);
261  // this is logically redundant since we won't use it, but it'll make debug easier
262  hierarchicalSuperparent[supernode] = hierSuperparent;
263  hierarchicalHyperparent[supernode] = hierTree.hyperparents[hierSuperparent];
264  } // no supernode ID: regular but not super
265  else
266  { // supernode ID exists
267  // save the supernode ID
268  hierarchicalSuperID[supernode] = supernodeID;
269 
270  // we can also set the superparent & hyperparent at this point
271  hierarchicalSuperparent[supernode] = superparent;
272  hierarchicalHyperparent[supernode] = hierTree.hyperparents[supernodeID];
273 
274  // now retrieve the hypernode ID (if any) & store it (even if it is already NO_SUCH_ELEMENT)
275  hierarchicalHyperID[supernode] = hierTree.super2hypernode[supernodeID];
276  } // supernode ID exists
277  } // regular ID exists
278  } // per tree supernode
279  */
280  } // operator ()
281 
282 }; // BoundaryVerticiesPerSuperArcStepOneWorklet
283 
284 } // namespace tree_grafter
285 } // namespace contourtree_distributed
286 } // namespace worklet
287 } // namespace vtkm
288 
289 #endif
VTKM_EXEC
#define VTKM_EXEC
Definition: ExportMacros.h:51
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
WorkletMapField.h
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
vtkm::worklet::contourtree_distributed::tree_grafter::GetHierarchicalIdsWorklet::GetHierarchicalIdsWorklet
VTKM_EXEC_CONT GetHierarchicalIdsWorklet()
Definition: GetHierarchicalIdsWorklet.h:109
vtkm::worklet::contourtree_augmented::MaskedIndex
VTKM_EXEC_CONT vtkm::Id MaskedIndex(vtkm::Id flaggedIndex)
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:127
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::worklet::contourtree_distributed::tree_grafter::GetHierarchicalIdsWorklet::ControlSignature
void(FieldIn supernodes, FieldIn supernodeGlobalId, WholeArrayIn sortOrder, WholeArrayIn dataValue, FieldIn necessary, FieldIn above, FieldIn below, WholeArrayIn superparents, WholeArrayIn hyperparents, WholeArrayIn regular2Supernode, WholeArrayIn super2Hypernode, ExecObject findRegularByGlobal, ExecObject findSuperArcForUnknownNode, FieldInOut hierarchicalRegularId, FieldInOut hierarchicalSuperId, FieldInOut hierarchicalHyperId, FieldInOut hierarchicalSuperparent, FieldInOut hierarchicalHyperparent) ControlSignature
Definition: GetHierarchicalIdsWorklet.h:101
vtkm::worklet::contourtree_distributed::tree_grafter::GetHierarchicalIdsWorklet::operator()
VTKM_EXEC void operator()(const vtkm::Id &oldSortId, const vtkm::Id &supernodeGlobalIdVal, const SortOrderPortalType &sortOrder, const InFieldDataPortalType &dataValues, const vtkm::Id &necessary, const vtkm::Id &upGlobalId, const vtkm::Id &dnGlobalId, const InFieldPortalType &superparents, const InFieldPortalType &hyperparents, const InFieldPortalType &regular2Supernode, const InFieldPortalType &super2Hypernode, const FindRegularExecType &findRegularByGlobal, const FindSuperExecType &findSuperArcForUnknownNode, vtkm::Id &hierarchicalRegularId, vtkm::Id &hierarchicalSuperId, vtkm::Id &hierarchicalHyperId, vtkm::Id &hierarchicalSuperparent, vtkm::Id &hierarchicalHyperparent) const
Definition: GetHierarchicalIdsWorklet.h:117
vtkm::worklet::contourtree_augmented::NoSuchElement
VTKM_EXEC_CONT bool NoSuchElement(vtkm::Id flaggedIndex)
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:97
vtkm::worklet::WorkletMapField::FieldIn
A control signature tag for input fields.
Definition: WorkletMapField.h:49
Types.h
vtkm::worklet::WorkletMapField::FieldInOut
A control signature tag for input-output (in-place) fields.
Definition: WorkletMapField.h:71
vtkm::worklet::contourtree_distributed::tree_grafter::GetHierarchicalIdsWorklet
Definition: GetHierarchicalIdsWorklet.h:69
vtkm::worklet::contourtree_distributed::tree_grafter::GetHierarchicalIdsWorklet::InputDomain
_1 InputDomain
Definition: GetHierarchicalIdsWorklet.h:105
vtkm::worklet::contourtree_distributed::tree_grafter::GetHierarchicalIdsWorklet::ExecutionSignature
void(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) ExecutionSignature
Definition: GetHierarchicalIdsWorklet.h:104
vtkm::worklet::WorkletMapField
Base class for worklets that do a simple mapping of field arrays.
Definition: WorkletMapField.h:38