VTK-m  2.0
ComputeRegularStructure_LocateSuperarcs.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_contourtree_maker_inc_compute_regular_structure_locate_superarcs_h
54 #define vtk_m_worklet_contourtree_augmented_contourtree_maker_inc_compute_regular_structure_locate_superarcs_h
55 
58 
59 namespace vtkm
60 {
61 namespace worklet
62 {
63 namespace contourtree_augmented
64 {
65 namespace contourtree_maker_inc
66 {
67 
68 // Worklet for the second step of ContourTreeMaker::ComputeRegularStructure ---
69 // for all remaining (regular) nodes, locate the superarc to which they belong
71 {
72 public:
73  typedef void ControlSignature(WholeArrayInOut contourTreeSuperparents, // (input/output)
74  WholeArrayIn contourTreeWhenTransferred, // (input)
75  WholeArrayIn contourTreeHyperparents, // (input)
76  WholeArrayIn contourTreeHyperarcs, // (input)
77  WholeArrayIn contourTreeHypernodes, // (input)
78  WholeArrayIn contourTreeSupernodes, // (input)
79  FieldIn meshExtremaPeaks, // (input)
80  FieldIn meshExtremaPits); // (input)
81 
82  typedef void ExecutionSignature(_1, InputIndex, _2, _3, _4, _5, _6, _7, _8);
83  using InputDomain = _1;
84 
85  vtkm::Id NumHypernodes; // contourTree.Hypernodes.GetNumberOfValues()
86  vtkm::Id NumSupernodes; // contourTree.Supernodes.GetNumberOfValues()
87 
88  // Default Constructor
91  : NumHypernodes(numHypernodes)
92  , NumSupernodes(numSupernodes)
93  {
94  }
95 
96  template <typename InOutFieldPortalType, typename InFieldPortalType>
97  VTKM_EXEC void operator()(const InOutFieldPortalType& contourTreeSuperparentsPortal,
98  const vtkm::Id node,
99  const InFieldPortalType& contourTreeWhenTransferredPortal,
100  const InFieldPortalType& contourTreeHyperparentsPortal,
101  const InFieldPortalType& contourTreeHyperarcsPortal,
102  const InFieldPortalType& contourTreeHypernodesPortal,
103  const InFieldPortalType& contourTreeSupernodesPortal,
104  vtkm::Id top,
105  vtkm::Id bottom) const
106  {
107  // per node
108  // if the superparent is already set, it's a supernode, so skip it.
109  if (NoSuchElement(contourTreeSuperparentsPortal.Get(node)))
110  { // regular nodes only
111  // we will need to prune top and bottom until one of them prunes past the node
112  // these are the regular IDs of supernodes, so their superparents are already set
113  vtkm::Id topSuperparent = contourTreeSuperparentsPortal.Get(MaskedIndex(top));
114  vtkm::Id bottomSuperparent = contourTreeSuperparentsPortal.Get(MaskedIndex(bottom));
115  // and we can also find out when they transferred
116  vtkm::Id topWhen = contourTreeWhenTransferredPortal.Get(topSuperparent);
117  vtkm::Id bottomWhen = contourTreeWhenTransferredPortal.Get(bottomSuperparent);
118  // and their hyperparent
119  vtkm::Id topHyperparent = contourTreeHyperparentsPortal.Get(topSuperparent);
120  vtkm::Id bottomHyperparent = contourTreeHyperparentsPortal.Get(bottomSuperparent);
121  // our goal is to work out the true hyperparent of the node
122  vtkm::Id hyperparent = (vtkm::Id)NO_SUCH_ELEMENT;
123 
124  // now we loop until one of them goes past the vertex
125  // the invariant here is that the first direction to prune past the vertex prunes it
126  while (NoSuchElement(hyperparent))
127  { // loop to find pruner
128  // we test the one that prunes first
129  if (MaskedIndex(topWhen) < MaskedIndex(bottomWhen))
130  { // top pruned first
131  // we prune down to the bottom of the hyperarc in either case, by updating the top superparent
132  topSuperparent = contourTreeHyperarcsPortal.Get(MaskedIndex(topHyperparent));
133  top = contourTreeSupernodesPortal.Get(MaskedIndex(topSuperparent));
134 
135  topWhen = contourTreeWhenTransferredPortal.Get(MaskedIndex(topSuperparent));
136  // test to see if we've passed the node
137  if (top < node)
138  { // just pruned past
139  hyperparent = topHyperparent;
140  } // just pruned past
141  // == is not possible, since node is regular
142  else // top < node
143  { // not pruned past
144  topHyperparent = contourTreeHyperparentsPortal.Get(MaskedIndex(topSuperparent));
145  } // not pruned past
146  } // top pruned first
147  else if (MaskedIndex(topWhen) > MaskedIndex(bottomWhen))
148  { // bottom pruned first
149  // we prune up to the top of the hyperarc in either case, by updating the bottom superparent
150  bottomSuperparent = contourTreeHyperarcsPortal.Get(MaskedIndex(bottomHyperparent));
151  bottom = contourTreeSupernodesPortal.Get(MaskedIndex(bottomSuperparent));
152  bottomWhen = contourTreeWhenTransferredPortal.Get(MaskedIndex(bottomSuperparent));
153  // test to see if we've passed the node
154  if (bottom > node)
155  { // just pruned past
156  hyperparent = bottomHyperparent;
157  } // just pruned past
158  // == is not possible, since node is regular
159  else // bottom > node
160  { // not pruned past
161  bottomHyperparent = contourTreeHyperparentsPortal.Get(MaskedIndex(bottomSuperparent));
162  } // not pruned past
163  } // bottom pruned first
164  else
165  { // both prune simultaneously
166  // this can happen when both top & bottom prune in the same pass because they belong to the same hyperarc
167  // but this means that they must have the same hyperparent, so we know the correct hyperparent & can check whether it ascends
168  hyperparent = bottomHyperparent;
169  } // both prune simultaneously
170  } // loop to find pruner
171  // we have now set the hyperparent correctly, so we retrieve it's hyperarc to find whether it ascends or descends
172  if (IsAscending(contourTreeHyperarcsPortal.Get(hyperparent)))
173  { // ascending hyperarc
174  // the supernodes on the hyperarc are in sorted low-high order
175  vtkm::Id lowSupernode = contourTreeHypernodesPortal.Get(hyperparent);
176  vtkm::Id highSupernode;
177  // if it's at the right hand end, take the last supernode in the array
178  if (MaskedIndex(hyperparent) == NumHypernodes - 1)
179  highSupernode = NumSupernodes - 1;
180  // otherwise, take the supernode just before the next hypernode
181  else
182  highSupernode = contourTreeHypernodesPortal.Get(MaskedIndex(hyperparent) + 1) - 1;
183  // now, the high supernode may be lower than the element, because the node belongs
184  // between it and the high end of the hyperarc
185  if (contourTreeSupernodesPortal.Get(highSupernode) < node)
186  contourTreeSuperparentsPortal.Set(node, highSupernode);
187  // otherwise, we do a binary search of the superarcs
188  else
189  { // node between high & low
190  // keep going until we span exactly
191  while (highSupernode - lowSupernode > 1)
192  { // binary search
193  // find the midway supernode
194  vtkm::Id midSupernode = (lowSupernode + highSupernode) / 2;
195  // test against the node
196  if (contourTreeSupernodesPortal.Get(midSupernode) > node)
197  highSupernode = midSupernode;
198  // == can't happen since node is regular
199  else
200  lowSupernode = midSupernode;
201  } // binary search
202 
203  // now we can use the low node as the superparent
204  contourTreeSuperparentsPortal.Set(node, lowSupernode);
205  } // node between high & low
206  } // ascending hyperarc
207  else
208  { // descending hyperarc
209  // the supernodes on the hyperarc are in sorted high-low order
210  vtkm::Id highSupernode = contourTreeHypernodesPortal.Get(hyperparent);
211  vtkm::Id lowSupernode;
212  // if it's at the right hand end, take the last supernode in the array
213  if (MaskedIndex(hyperparent) == NumHypernodes - 1)
214  { // last hyperarc
215  lowSupernode = NumSupernodes - 1;
216  } // last hyperarc
217  // otherwise, take the supernode just before the next hypernode
218  else
219  { // other hyperarc
220  lowSupernode = contourTreeHypernodesPortal.Get(MaskedIndex(hyperparent) + 1) - 1;
221  } // other hyperarc
222  // now, the low supernode may be higher than the element, because the node belongs
223  // between it and the low end of the hyperarc
224  if (contourTreeSupernodesPortal.Get(lowSupernode) > node)
225  contourTreeSuperparentsPortal.Set(node, lowSupernode);
226  // otherwise, we do a binary search of the superarcs
227  else
228  { // node between low & high
229  // keep going until we span exactly
230  while (lowSupernode - highSupernode > 1)
231  { // binary search
232  // find the midway supernode
233  vtkm::Id midSupernode = (highSupernode + lowSupernode) / 2;
234  // test against the node
235  if (contourTreeSupernodesPortal.Get(midSupernode) > node)
236  highSupernode = midSupernode;
237  // == can't happen since node is regular
238  else
239  lowSupernode = midSupernode;
240  } // binary search
241  // now we can use the high node as the superparent
242  contourTreeSuperparentsPortal.Set(node, highSupernode);
243  } // node between low & high
244  } // descending hyperarc
245  } // regular nodes only
246  /*
247  // In serial this worklet implements the following operation
248  for (indexType node = 0; node < contourTree.Arcs.size(); node++)
249  { // per node
250  // if the superparent is already set, it's a supernode, so skip it.
251  if (NoSuchElement(contourTree.superparents[node]))
252  { // regular nodes only
253  // we will need to prune top and bottom until one of them prunes past the node
254  indexType top = meshExtrema.Peaks[node];
255  indexType bottom = meshExtrema.Pits[node];
256  // these are the regular IDs of supernodes, so their superparents are already set
257  indexType topSuperparent = contourTree.Superparents[top];
258  indexType bottomSuperparent = contourTree.Superparents[bottom];
259  // and we can also find out when they transferred
260  indexType topWhen = contourTree.WhenTransferred[topSuperparent];
261  indexType bottomWhen = contourTree.WhenTransferred[bottomSuperparent];
262  // and their hyperparent
263  indexType topHyperparent = contourTree.hyperparents[topSuperparent];
264  indexType bottomHyperparent = contourTree.hyperparents[bottomSuperparent];
265 
266  // our goal is to work out the true hyperparent of the node
267  indexType hyperparent = NO_SUCH_ELEMENT;
268 
269  // now we loop until one of them goes past the vertex
270  // the invariant here is that the first direction to prune past the vertex prunes it
271  while (NoSuchElement(hyperparent))
272  { // loop to find pruner
273 
274  // we test the one that prunes first
275  if (MaskedIndex(topWhen) < MaskedIndex(bottomWhen))
276  { // top pruned first
277  // we prune down to the bottom of the hyperarc in either case, by updating the top superparent
278  topSuperparent = contourTree.hyperarcs[MaskedIndex(topHyperparent)];
279  top = contourTree.Supernodes[MaskedIndex(topSuperparent)];
280 
281  topWhen = contourTree.WhenTransferred[MaskedIndex(topSuperparent)];
282  // test to see if we've passed the node
283  if (top < node)
284  { // just pruned past
285  hyperparent = topHyperparent;
286  } // just pruned past
287  // == is not possible, since node is regular
288  else // top < node
289  { // not pruned past
290  topHyperparent = contourTree.hyperparents[MaskedIndex(topSuperparent)];
291  } // not pruned past
292  } // top pruned first
293  else if (MaskedIndex(topWhen) > MaskedIndex(bottomWhen))
294  { // bottom pruned first
295  // we prune up to the top of the hyperarc in either case, by updating the bottom superparent
296  bottomSuperparent = contourTree.hyperarcs[MaskedIndex(bottomHyperparent)];
297  bottom = contourTree.Supernodes[MaskedIndex(bottomSuperparent)];
298  bottomWhen = contourTree.WhenTransferred[MaskedIndex(bottomSuperparent)];
299  // test to see if we've passed the node
300  if (bottom > node)
301  { // just pruned past
302  hyperparent = bottomHyperparent;
303  } // just pruned past
304  // == is not possible, since node is regular
305  else // bottom > node
306  { // not pruned past
307  bottomHyperparent = contourTree.hyperparents[MaskedIndex(bottomSuperparent)];
308  } // not pruned past
309  } // bottom pruned first
310  else
311  { // both prune simultaneously
312  // this can happen when both top & bottom prune in the same pass because they belong to the same hyperarc
313  // but this means that they must have the same hyperparent, so we know the correct hyperparent & can check whether it ascends
314  hyperparent = bottomHyperparent;
315  } // both prune simultaneously
316  } // loop to find pruner
317 
318 
319  // we have now set the hyperparent correctly, so we retrieve it's hyperarc to find whether it ascends or descends
320  if (IsAscending(contourTree.hyperarcs[hyperparent]))
321  { // ascending hyperarc
322  // the supernodes on the hyperarc are in sorted low-high order
323  indexType lowSupernode = contourTree.Hypernodes[hyperparent];
324  indexType highSupernode;
325  // if it's at the right hand end, take the last supernode in the array
326  if (MaskedIndex(hyperparent) == contourTree.Hypernodes.size() - 1)
327  highSupernode = contourTree.Supernodes.size() - 1;
328  // otherwise, take the supernode just before the next hypernode
329  else
330  highSupernode = contourTree.Hypernodes[MaskedIndex(hyperparent) + 1] - 1;
331  // now, the high supernode may be lower than the element, because the node belongs
332  // between it and the high end of the hyperarc
333  if (contourTree.Supernodes[highSupernode] < node)
334  contourTree.Superparents[node] = highSupernode;
335  // otherwise, we do a binary search of the superarcs
336  else
337  { // node between high & low
338  // keep going until we span exactly
339  while (highSupernode - lowSupernode > 1)
340  { // binary search
341  // find the midway supernode
342  indexType midSupernode = (lowSupernode + highSupernode) / 2;
343  // test against the node
344  if (contourTree.Supernodes[midSupernode] > node)
345  highSupernode = midSupernode;
346  // == can't happen since node is regular
347  else
348  lowSupernode = midSupernode;
349  } // binary search
350  // now we can use the low node as the superparent
351  contourTree.Superparents[node] = lowSupernode;
352  } // node between high & low
353  } // ascending hyperarc
354  else
355  { // descending hyperarc
356  // the supernodes on the hyperarc are in sorted high-low order
357  indexType highSupernode = contourTree.Hypernodes[hyperparent];
358  indexType lowSupernode;
359  // if it's at the right hand end, take the last supernode in the array
360  if (MaskedIndex(hyperparent) == contourTree.Hypernodes.size() - 1)
361  { // last hyperarc
362  lowSupernode = contourTree.Supernodes.size() - 1;
363  } // last hyperarc
364  // otherwise, take the supernode just before the next hypernode
365  else
366  { // other hyperarc
367  lowSupernode = contourTree.Hypernodes[MaskedIndex(hyperparent) + 1] - 1;
368  } // other hyperarc
369  // now, the low supernode may be higher than the element, because the node belongs
370  // between it and the low end of the hyperarc
371  if (contourTree.Supernodes[lowSupernode] > node)
372  contourTree.Superparents[node] = lowSupernode;
373  // otherwise, we do a binary search of the superarcs
374  else
375  { // node between low & high
376  // keep going until we span exactly
377  while (lowSupernode - highSupernode > 1)
378  { // binary search
379  // find the midway supernode
380  indexType midSupernode = (highSupernode + lowSupernode) / 2;
381  // test against the node
382  if (contourTree.Supernodes[midSupernode] > node)
383  highSupernode = midSupernode;
384  // == can't happen since node is regular
385  else
386  lowSupernode = midSupernode;
387  } // binary search
388  // now we can use the high node as the superparent
389  contourTree.Superparents[node] = highSupernode;
390  } // node between low & high
391  } // descending hyperarc
392  } // regular nodes only
393  } // per node
394  */
395  }
396 
397 }; // ComputeRegularStructure_LocateSuperarcs.h
398 
399 
400 
401 // TODO This algorithm looks to be a 3d/2d volume algorithm that is iterating 'points' and concerned about being on the 'boundary'. This would be better suited as WorkletMapPointNeighborhood as it can provide the boundary condition logic for you.
402 
403 // Worklet for the second step of template <class Mesh> void ContourTreeMaker::ComputeRegularStructure ---
404 // for all remaining (regular) nodes on the boundary, locate the superarc to which they belong
406 {
407 public:
408  typedef void ControlSignature(WholeArrayInOut contourTreeSuperparents, // (input/output)
409  WholeArrayIn contourTreeWhenTransferred, // (input)
410  WholeArrayIn contourTreeHyperparents, // (input)
411  WholeArrayIn contourTreeHyperarcs, // (input)
412  WholeArrayIn contourTreeHypernodes, // (input)
413  WholeArrayIn contourTreeSupernodes, // (input)
414  FieldIn meshExtremaPeaks, // (input)
415  FieldIn meshExtremaPits, // (input)
416  FieldIn sortOrder, // (input)
417  ExecObject meshBoundary); // (input)
418 
419  typedef void ExecutionSignature(_1, InputIndex, _2, _3, _4, _5, _6, _7, _8, _9, _10);
420  using InputDomain = _1;
421 
422  vtkm::Id NumHypernodes; // contourTree.Hypernodes.GetNumberOfValues()
423  vtkm::Id NumSupernodes; // contourTree.Supernodes.GetNumberOfValues()
424 
425  // Default Constructor
428  : NumHypernodes(numHypernodes)
429  , NumSupernodes(numSupernodes)
430  {
431  }
432 
433  template <typename InOutFieldPortalType, typename InFieldPortalType, typename MeshBoundaryType>
434  VTKM_EXEC void operator()(const InOutFieldPortalType& contourTreeSuperparentsPortal,
435  const vtkm::Id node,
436  const InFieldPortalType& contourTreeWhenTransferredPortal,
437  const InFieldPortalType& contourTreeHyperparentsPortal,
438  const InFieldPortalType& contourTreeHyperarcsPortal,
439  const InFieldPortalType& contourTreeHypernodesPortal,
440  const InFieldPortalType& contourTreeSupernodesPortal,
441  vtkm::Id top,
442  vtkm::Id bottom,
443  vtkm::Id sortOrder,
444  const MeshBoundaryType& meshBoundary) const
445  {
446  // per node
447  // if the superparent is already set, it's a supernode, so skip it.
448  if (NoSuchElement(contourTreeSuperparentsPortal.Get(node)) &&
449  meshBoundary.LiesOnBoundary(sortOrder))
450  { // regular nodes only
451  // we will need to prune top and bottom until one of them prunes past the node
452  // these are the regular IDs of supernodes, so their superparents are already set
453  vtkm::Id topSuperparent = contourTreeSuperparentsPortal.Get(MaskedIndex(top));
454  vtkm::Id bottomSuperparent = contourTreeSuperparentsPortal.Get(MaskedIndex(bottom));
455  // and we can also find out when they transferred
456  vtkm::Id topWhen = contourTreeWhenTransferredPortal.Get(topSuperparent);
457  vtkm::Id bottomWhen = contourTreeWhenTransferredPortal.Get(bottomSuperparent);
458  // and their hyperparent
459  vtkm::Id topHyperparent = contourTreeHyperparentsPortal.Get(topSuperparent);
460  vtkm::Id bottomHyperparent = contourTreeHyperparentsPortal.Get(bottomSuperparent);
461  // our goal is to work out the true hyperparent of the node
462  vtkm::Id hyperparent = (vtkm::Id)NO_SUCH_ELEMENT;
463 
464  // now we loop until one of them goes past the vertex
465  // the invariant here is that the first direction to prune past the vertex prunes it
466  while (NoSuchElement(hyperparent))
467  { // loop to find pruner
468  // we test the one that prunes first
469  if (MaskedIndex(topWhen) < MaskedIndex(bottomWhen))
470  { // top pruned first
471  // we prune down to the bottom of the hyperarc in either case, by updating the top superparent
472  topSuperparent = contourTreeHyperarcsPortal.Get(MaskedIndex(topHyperparent));
473  top = contourTreeSupernodesPortal.Get(MaskedIndex(topSuperparent));
474 
475  topWhen = contourTreeWhenTransferredPortal.Get(MaskedIndex(topSuperparent));
476  // test to see if we've passed the node
477  if (top < node)
478  { // just pruned past
479  hyperparent = topHyperparent;
480  } // just pruned past
481  // == is not possible, since node is regular
482  else // top < node
483  { // not pruned past
484  topHyperparent = contourTreeHyperparentsPortal.Get(MaskedIndex(topSuperparent));
485  } // not pruned past
486  } // top pruned first
487  else if (MaskedIndex(topWhen) > MaskedIndex(bottomWhen))
488  { // bottom pruned first
489  // we prune up to the top of the hyperarc in either case, by updating the bottom superparent
490  bottomSuperparent = contourTreeHyperarcsPortal.Get(MaskedIndex(bottomHyperparent));
491  bottom = contourTreeSupernodesPortal.Get(MaskedIndex(bottomSuperparent));
492  bottomWhen = contourTreeWhenTransferredPortal.Get(MaskedIndex(bottomSuperparent));
493  // test to see if we've passed the node
494  if (bottom > node)
495  { // just pruned past
496  hyperparent = bottomHyperparent;
497  } // just pruned past
498  // == is not possible, since node is regular
499  else // bottom > node
500  { // not pruned past
501  bottomHyperparent = contourTreeHyperparentsPortal.Get(MaskedIndex(bottomSuperparent));
502  } // not pruned past
503  } // bottom pruned first
504  else
505  { // both prune simultaneously
506  // this can happen when both top & bottom prune in the same pass because they belong to the same hyperarc
507  // but this means that they must have the same hyperparent, so we know the correct hyperparent & can check whether it ascends
508  hyperparent = bottomHyperparent;
509  } // both prune simultaneously
510  } // loop to find pruner
511  // we have now set the hyperparent correctly, so we retrieve it's hyperarc to find whether it ascends or descends
512  if (IsAscending(contourTreeHyperarcsPortal.Get(hyperparent)))
513  { // ascending hyperarc
514  // the supernodes on the hyperarc are in sorted low-high order
515  vtkm::Id lowSupernode = contourTreeHypernodesPortal.Get(hyperparent);
516  vtkm::Id highSupernode;
517  // if it's at the right hand end, take the last supernode in the array
518  if (MaskedIndex(hyperparent) == NumHypernodes - 1)
519  highSupernode = NumSupernodes - 1;
520  // otherwise, take the supernode just before the next hypernode
521  else
522  highSupernode = contourTreeHypernodesPortal.Get(MaskedIndex(hyperparent) + 1) - 1;
523  // now, the high supernode may be lower than the element, because the node belongs
524  // between it and the high end of the hyperarc
525  if (contourTreeSupernodesPortal.Get(highSupernode) < node)
526  contourTreeSuperparentsPortal.Set(node, highSupernode);
527  // otherwise, we do a binary search of the superarcs
528  else
529  { // node between high & low
530  // keep going until we span exactly
531  while (highSupernode - lowSupernode > 1)
532  { // binary search
533  // find the midway supernode
534  vtkm::Id midSupernode = (lowSupernode + highSupernode) / 2;
535  // test against the node
536  if (contourTreeSupernodesPortal.Get(midSupernode) > node)
537  highSupernode = midSupernode;
538  // == can't happen since node is regular
539  else
540  lowSupernode = midSupernode;
541  } // binary search
542 
543  // now we can use the low node as the superparent
544  contourTreeSuperparentsPortal.Set(node, lowSupernode);
545  } // node between high & low
546  } // ascending hyperarc
547  else
548  { // descending hyperarc
549  // the supernodes on the hyperarc are in sorted high-low order
550  vtkm::Id highSupernode = contourTreeHypernodesPortal.Get(hyperparent);
551  vtkm::Id lowSupernode;
552  // if it's at the right hand end, take the last supernode in the array
553  if (MaskedIndex(hyperparent) == NumHypernodes - 1)
554  { // last hyperarc
555  lowSupernode = NumSupernodes - 1;
556  } // last hyperarc
557  // otherwise, take the supernode just before the next hypernode
558  else
559  { // other hyperarc
560  lowSupernode = contourTreeHypernodesPortal.Get(MaskedIndex(hyperparent) + 1) - 1;
561  } // other hyperarc
562  // now, the low supernode may be higher than the element, because the node belongs
563  // between it and the low end of the hyperarc
564  if (contourTreeSupernodesPortal.Get(lowSupernode) > node)
565  contourTreeSuperparentsPortal.Set(node, lowSupernode);
566  // otherwise, we do a binary search of the superarcs
567  else
568  { // node between low & high
569  // keep going until we span exactly
570  while (lowSupernode - highSupernode > 1)
571  { // binary search
572  // find the midway supernode
573  vtkm::Id midSupernode = (highSupernode + lowSupernode) / 2;
574  // test against the node
575  if (contourTreeSupernodesPortal.Get(midSupernode) > node)
576  highSupernode = midSupernode;
577  // == can't happen since node is regular
578  else
579  lowSupernode = midSupernode;
580  } // binary search
581  // now we can use the high node as the superparent
582  contourTreeSuperparentsPortal.Set(node, highSupernode);
583  } // node between low & high
584  } // descending hyperarc
585  } // regular nodes only
586  /*
587  // In serial this worklet implements the following operation
588  for (indexType node = 0; node < contourTree.Arcs.size(); node++)
589  { // per node
590  // if the superparent is already set, it's a supernode, so skip it.
591  if (NoSuchElement(contourTree.Superparents[node]) && mesh.liesOnBoundary(node))
592  { // regular nodes only
593  // we will need to prune top and bottom until one of them prunes past the node
594  indexType top = meshExtrema.Peaks[node];
595  indexType bottom = meshExtrema.Pits[node];
596  // these are the regular IDs of supernodes, so their superparents are already set
597  indexType topSuperparent = contourTree.Superparents[top];
598  indexType bottomSuperparent = contourTree.Superparents[bottom];
599  // and we can also find out when they transferred
600  indexType topWhen = contourTree.WhenTransferred[topSuperparent];
601  indexType bottomWhen = contourTree.WhenTransferred[bottomSuperparent];
602  // and their hyperparent
603  indexType topHyperparent = contourTree.hyperparents[topSuperparent];
604  indexType bottomHyperparent = contourTree.hyperparents[bottomSuperparent];
605 
606  // our goal is to work out the true hyperparent of the node
607  indexType hyperparent = NO_SUCH_ELEMENT;
608 
609  // now we loop until one of them goes past the vertex
610  // the invariant here is that the first direction to prune past the vertex prunes it
611  while (NoSuchElement(hyperparent))
612  { // loop to find pruner
613 
614  // we test the one that prunes first
615  if (MaskedIndex(topWhen) < MaskedIndex(bottomWhen))
616  { // top pruned first
617  // we prune down to the bottom of the hyperarc in either case, by updating the top superparent
618  topSuperparent = contourTree.hyperarcs[MaskedIndex(topHyperparent)];
619  top = contourTree.Supernodes[MaskedIndex(topSuperparent)];
620 
621  topWhen = contourTree.WhenTransferred[MaskedIndex(topSuperparent)];
622  // test to see if we've passed the node
623  if (top < node)
624  { // just pruned past
625  hyperparent = topHyperparent;
626  } // just pruned past
627  // == is not possible, since node is regular
628  else // top < node
629  { // not pruned past
630  topHyperparent = contourTree.hyperparents[MaskedIndex(topSuperparent)];
631  } // not pruned past
632  } // top pruned first
633  else if (MaskedIndex(topWhen) > MaskedIndex(bottomWhen))
634  { // bottom pruned first
635  // we prune up to the top of the hyperarc in either case, by updating the bottom superparent
636  bottomSuperparent = contourTree.hyperarcs[MaskedIndex(bottomHyperparent)];
637  bottom = contourTree.Supernodes[MaskedIndex(bottomSuperparent)];
638  bottomWhen = contourTree.WhenTransferred[MaskedIndex(bottomSuperparent)];
639  // test to see if we've passed the node
640  if (bottom > node)
641  { // just pruned past
642  hyperparent = bottomHyperparent;
643  } // just pruned past
644  // == is not possible, since node is regular
645  else // bottom > node
646  { // not pruned past
647  bottomHyperparent = contourTree.hyperparents[MaskedIndex(bottomSuperparent)];
648  } // not pruned past
649  } // bottom pruned first
650  else
651  { // both prune simultaneously
652  // this can happen when both top & bottom prune in the same pass because they belong to the same hyperarc
653  // but this means that they must have the same hyperparent, so we know the correct hyperparent & can check whether it ascends
654  hyperparent = bottomHyperparent;
655  } // both prune simultaneously
656  } // loop to find pruner
657 
658 
659  // we have now set the hyperparent correctly, so we retrieve it's hyperarc to find whether it ascends or descends
660  if (IsAscending(contourTree.hyperarcs[hyperparent]))
661  { // ascending hyperarc
662  // the supernodes on the hyperarc are in sorted low-high order
663  indexType lowSupernode = contourTree.Hypernodes[hyperparent];
664  indexType highSupernode;
665  // if it's at the right hand end, take the last supernode in the array
666  if (MaskedIndex(hyperparent) == contourTree.Hypernodes.size() - 1)
667  highSupernode = contourTree.Supernodes.size() - 1;
668  // otherwise, take the supernode just before the next hypernode
669  else
670  highSupernode = contourTree.Hypernodes[MaskedIndex(hyperparent) + 1] - 1;
671  // now, the high supernode may be lower than the element, because the node belongs
672  // between it and the high end of the hyperarc
673  if (contourTree.Supernodes[highSupernode] < node)
674  contourTree.Superparents[node] = highSupernode;
675  // otherwise, we do a binary search of the superarcs
676  else
677  { // node between high & low
678  // keep going until we span exactly
679  while (highSupernode - lowSupernode > 1)
680  { // binary search
681  // find the midway supernode
682  indexType midSupernode = (lowSupernode + highSupernode) / 2;
683  // test against the node
684  if (contourTree.Supernodes[midSupernode] > node)
685  highSupernode = midSupernode;
686  // == can't happen since node is regular
687  else
688  lowSupernode = midSupernode;
689  } // binary search
690  // now we can use the low node as the superparent
691  contourTree.Superparents[node] = lowSupernode;
692  } // node between high & low
693  } // ascending hyperarc
694  else
695  { // descending hyperarc
696  // the Supernodes on the hyperarc are in sorted high-low order
697  indexType highSupernode = contourTree.Hypernodes[hyperparent];
698  indexType lowSupernode;
699  // if it's at the right hand end, take the last supernode in the array
700  if (MaskedIndex(hyperparent) == contourTree.Hypernodes.size() - 1)
701  { // last hyperarc
702  lowSupernode = contourTree.Supernodes.size() - 1;
703  } // last hyperarc
704  // otherwise, take the supernode just before the next hypernode
705  else
706  { // other hyperarc
707  lowSupernode = contourTree.Hypernodes[MaskedIndex(hyperparent) + 1] - 1;
708  } // other hyperarc
709  // now, the low supernode may be higher than the element, because the node belongs
710  // between it and the low end of the hyperarc
711  if (contourTree.Supernodes[lowSupernode] > node)
712  contourTree.Superparents[node] = lowSupernode;
713  // otherwise, we do a binary search of the superarcs
714  else
715  { // node between low & high
716  // keep going until we span exactly
717  while (lowSupernode - highSupernode > 1)
718  { // binary search
719  // find the midway supernode
720  indexType midSupernode = (highSupernode + lowSupernode) / 2;
721  // test against the node
722  if (contourTree.Supernodes[midSupernode] > node)
723  highSupernode = midSupernode;
724  // == can't happen since node is regular
725  else
726  lowSupernode = midSupernode;
727  } // binary search
728  // now we can use the high node as the superparent
729  contourTree.Superparents[node] = highSupernode;
730  } // node between low & high
731  } // descending hyperarc
732  } // regular nodes only
733  } // per node
734  */
735  }
736 
737 }; // ComputeRegularStructure_LocateSuperarcsOnBoundary.h
738 
739 } // namespace contourtree_maker_inc
740 } // namespace contourtree_augmented
741 } // namespace worklet
742 } // namespace vtkm
743 
744 #endif
vtkm::worklet::contourtree_augmented::IsAscending
VTKM_EXEC_CONT bool IsAscending(vtkm::Id flaggedIndex)
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:121
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcsOnBoundary::NumSupernodes
vtkm::Id NumSupernodes
Definition: ComputeRegularStructure_LocateSuperarcs.h:423
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_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcs
Definition: ComputeRegularStructure_LocateSuperarcs.h:70
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcs::InputDomain
_1 InputDomain
Definition: ComputeRegularStructure_LocateSuperarcs.h:83
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcs::operator()
VTKM_EXEC void operator()(const InOutFieldPortalType &contourTreeSuperparentsPortal, const vtkm::Id node, const InFieldPortalType &contourTreeWhenTransferredPortal, const InFieldPortalType &contourTreeHyperparentsPortal, const InFieldPortalType &contourTreeHyperarcsPortal, const InFieldPortalType &contourTreeHypernodesPortal, const InFieldPortalType &contourTreeSupernodesPortal, vtkm::Id top, vtkm::Id bottom) const
Definition: ComputeRegularStructure_LocateSuperarcs.h:97
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_augmented::NoSuchElement
VTKM_EXEC_CONT bool NoSuchElement(vtkm::Id flaggedIndex)
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:97
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcs::ComputeRegularStructure_LocateSuperarcs
VTKM_EXEC_CONT ComputeRegularStructure_LocateSuperarcs(vtkm::Id numHypernodes, vtkm::Id numSupernodes)
Definition: ComputeRegularStructure_LocateSuperarcs.h:90
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcsOnBoundary::ControlSignature
void ControlSignature(WholeArrayInOut contourTreeSuperparents, WholeArrayIn contourTreeWhenTransferred, WholeArrayIn contourTreeHyperparents, WholeArrayIn contourTreeHyperarcs, WholeArrayIn contourTreeHypernodes, WholeArrayIn contourTreeSupernodes, FieldIn meshExtremaPeaks, FieldIn meshExtremaPits, FieldIn sortOrder, ExecObject meshBoundary)
Definition: ComputeRegularStructure_LocateSuperarcs.h:408
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcs::NumHypernodes
vtkm::Id NumHypernodes
Definition: ComputeRegularStructure_LocateSuperarcs.h:85
vtkm::worklet::WorkletMapField::FieldIn
A control signature tag for input fields.
Definition: WorkletMapField.h:49
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcsOnBoundary::ExecutionSignature
void ExecutionSignature(_1, InputIndex, _2, _3, _4, _5, _6, _7, _8, _9, _10)
Definition: ComputeRegularStructure_LocateSuperarcs.h:419
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcs::ExecutionSignature
void ExecutionSignature(_1, InputIndex, _2, _3, _4, _5, _6, _7, _8)
Definition: ComputeRegularStructure_LocateSuperarcs.h:82
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcs::NumSupernodes
vtkm::Id NumSupernodes
Definition: ComputeRegularStructure_LocateSuperarcs.h:86
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcsOnBoundary::NumHypernodes
vtkm::Id NumHypernodes
Definition: ComputeRegularStructure_LocateSuperarcs.h:422
Types.h
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcsOnBoundary::InputDomain
_1 InputDomain
Definition: ComputeRegularStructure_LocateSuperarcs.h:420
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcsOnBoundary::operator()
VTKM_EXEC void operator()(const InOutFieldPortalType &contourTreeSuperparentsPortal, const vtkm::Id node, const InFieldPortalType &contourTreeWhenTransferredPortal, const InFieldPortalType &contourTreeHyperparentsPortal, const InFieldPortalType &contourTreeHyperarcsPortal, const InFieldPortalType &contourTreeHypernodesPortal, const InFieldPortalType &contourTreeSupernodesPortal, vtkm::Id top, vtkm::Id bottom, vtkm::Id sortOrder, const MeshBoundaryType &meshBoundary) const
Definition: ComputeRegularStructure_LocateSuperarcs.h:434
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcsOnBoundary::ComputeRegularStructure_LocateSuperarcsOnBoundary
VTKM_EXEC_CONT ComputeRegularStructure_LocateSuperarcsOnBoundary(vtkm::Id numHypernodes, vtkm::Id numSupernodes)
Definition: ComputeRegularStructure_LocateSuperarcs.h:427
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcsOnBoundary
Definition: ComputeRegularStructure_LocateSuperarcs.h:405
vtkm::worklet::contourtree_augmented::contourtree_maker_inc::ComputeRegularStructure_LocateSuperarcs::ControlSignature
void ControlSignature(WholeArrayInOut contourTreeSuperparents, WholeArrayIn contourTreeWhenTransferred, WholeArrayIn contourTreeHyperparents, WholeArrayIn contourTreeHyperarcs, WholeArrayIn contourTreeHypernodes, WholeArrayIn contourTreeSupernodes, FieldIn meshExtremaPeaks, FieldIn meshExtremaPits)
Definition: ComputeRegularStructure_LocateSuperarcs.h:73
vtkm::exec::arg::InputIndex
The ExecutionSignature tag to use to get the input index.
Definition: InputIndex.h:42
vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT
constexpr vtkm::Id NO_SUCH_ELEMENT
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:73
vtkm::worklet::WorkletMapField
Base class for worklets that do a simple mapping of field arrays.
Definition: WorkletMapField.h:38