VTK-m  2.0
ContourTree.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) 2016, Los Alamos National Security, LLC
11 // All rights reserved.
12 //
13 // Copyright 2016. Los Alamos National Security, LLC.
14 // This software was produced under U.S. Government contract DE-AC52-06NA25396
15 // for Los Alamos National Laboratory (LANL), which is operated by
16 // Los Alamos National Security, LLC for the U.S. Department of Energy.
17 // The U.S. Government has rights to use, reproduce, and distribute this
18 // software. NEITHER THE GOVERNMENT NOR LOS ALAMOS NATIONAL SECURITY, LLC
19 // MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LIABILITY FOR THE
20 // USE OF THIS SOFTWARE. If software is modified to produce derivative works,
21 // such modified software should be clearly marked, so as not to confuse it
22 // with the version available from LANL.
23 //
24 // Additionally, redistribution and use in source and binary forms, with or
25 // without modification, are permitted provided that the following conditions
26 // are met:
27 //
28 // 1. Redistributions of source code must retain the above copyright notice,
29 // this list of conditions and the following disclaimer.
30 // 2. Redistributions in binary form must reproduce the above copyright notice,
31 // this list of conditions and the following disclaimer in the documentation
32 // and/or other materials provided with the distribution.
33 // 3. Neither the name of Los Alamos National Security, LLC, Los Alamos
34 // National Laboratory, LANL, the U.S. Government, nor the names of its
35 // contributors may be used to endorse or promote products derived from
36 // this software without specific prior written permission.
37 //
38 // THIS SOFTWARE IS PROVIDED BY LOS ALAMOS NATIONAL SECURITY, LLC AND
39 // CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
40 // BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
41 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS
42 // NATIONAL SECURITY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
43 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
44 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
45 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
46 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
47 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
48 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
49 //============================================================================
50 
51 // This code is based on the algorithm presented in the paper:
52 // “Parallel Peak Pruning for Scalable SMP Contour Tree Computation.”
53 // Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
54 // Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
55 // (LDAV), October 2016, Baltimore, Maryland.
56 
57 //=======================================================================================
58 //
59 // COMMENTS:
60 //
61 //
62 // i.e. based on PeakPitPruningCriticalSerial
63 //
64 // Under the old merge approach, we had an essentially breadth-first queue for transferring
65 // leaves from the merge trees to the contour tree.
66 //
67 // Most of these leaves are completely independent of each other, and can (on principle)
68 // be processed simultaneously. However, the interior of the tree is dependent on them
69 // having been dealt with already. This version, therefore, will make multiple passes,
70 // in each pass pruning all maxima then all minima, interspersed with updating the merge
71 // and split trees. To understand this, consider what happens in the merge algorithm when
72 // a maximum is added:
73 //
74 // 1. The vertex v is removed from the queue: it has one join neighbour, w
75 // 2. Edge (v,w) is removed from the join tree, along with vertex v
76 // 3. Edge (v,w) is added to the contour tree, with v, w if necessary
77 // 4. Vertex v is removed from the split tree, bridging edges past it if necessary
78 // 5. Vertex w is added to the queue iff it is now a leaf
79 //
80 // To parallelise this:
81 // For all vertices v
82 // Set contourArc[v] = NO_VERTEX_ASSIGNED
83 // Set nContourArcs = 0;
84 // While (nContourArcs) > 0 // might be one, or something else - base case isn't clear
85 // a. Use reduction to compute updegree from join tree, downdegree from split tree
86 // b. For each vertex v
87 // // omit previously processed vertices
88 // if (contourArc[v] == NO_VERTEX_ASSIGNED)
89 // continue;
90 // // Test for extremality
91 // i. If ((updegree[v] == 0) && (downdegree[v] == 1))
92 // { // Maximum
93 // contourArc[v] = joinArc[v];
94 // } // Maximum
95 // ii. Else if ((updegree[v] = 1) && (downdegree[v] == 0))
96 // { // Minimum
97 // contourArc[v] = splitArc[v];
98 // } // Minimum
99 // c. For (log n iterations)
100 // i. For each vertex v
101 // retrieve it's join neighbour j
102 // retrieve it's split neighbour s
103 // if v has no join neighbour (i.e. j == -1)
104 // skip (i.e. v is the root)
105 // else if j has a contour arc assigned
106 // set v's neighbour to j's neighbour
107 // if v has no split neighbour (i.e. s == -1)
108 // skip (i.e. v is the root)
109 // else if s has a contour arc assigned
110 // set v's neighbour to s's neighbour
111 //
112 // Initially, we will do this with all vertices, regular or otherwise, then restrict to
113 // the critical points. Number of iterations - regular vertices will slow this down, so
114 // the worst case is O(n) passes. Even if we restrict to critical points, W's in the tree
115 // will serialise, so O(n) still applies. I believe that the W edges can be suppressed,
116 // but let's leave that to optimisation for now.
117 //
118 //=======================================================================================
119 
120 #ifndef vtkm_worklet_contourtree_contourtree_h
121 #define vtkm_worklet_contourtree_contourtree_h
122 
123 // local includes
144 
145 #include <vtkm/Pair.h>
147 #include <vtkm/cont/ArrayHandle.h>
151 
152 //#define DEBUG_PRINT 1
153 //#define DEBUG_TIMING 1
154 
155 namespace vtkm
156 {
157 namespace worklet
158 {
159 namespace contourtree
160 {
161 
162 template <typename T, typename StorageType>
164 {
165 public:
170 
171  // reference to the underlying data
173 
174  // vector of superarcs in the contour tree (stored as inward-pointing)
176 
177  // vector of supernodes
179 
180  // vector of supernodes still unprocessed
182 
183  // references to join & split trees
185 
186  // references to join & split graphs
188 
189  // vectors of up & down degree used during computation
191 
192  // vectors for tracking merge arcs
194 
195  // counter for how many iterations it took to compute
197 
198  // contour tree constructor
200  MergeTree<T, StorageType>& JoinTree,
201  MergeTree<T, StorageType>& SplitTree,
202  ChainGraph<T, StorageType>& JoinGraph,
203  ChainGraph<T, StorageType>& SplitGraph);
204 
205  // routines for computing the contour tree
206  // combines the list of active vertices for join & split trees
207  // then reduces them to eliminate regular vertices & non-connectivity critical points
208  void FindSupernodes();
209 
210  // transfers leaves from join/split trees to contour tree
211  void TransferLeaves();
212 
213  // collapses regular edges along leaf superarcs
214  void CollapseRegular(bool isJoin);
215 
216  // compresses trees to remove transferred vertices
217  void CompressTrees();
218 
219  // compresses active set of supernodes
221 
222  // finds the degree of each supernode from the join & split trees
223  void FindDegrees();
224 
225  // collect the resulting saddle peaks in sort pairs
227 
228  void DebugPrint(const char* message);
229 
230 }; // class ContourTree
231 
233 {
234 public:
235  using ControlSignature = void(FieldIn supernode, WholeArrayIn superarcs, FieldOut hasSuperArc);
236  using ExecutionSignature = _3(_1, _2);
237  using InputDomain = _1;
238 
240 
242  VertexAssigned(bool VertexIsAssigned)
243  : vertexIsAssigned(VertexIsAssigned)
244  {
245  }
246 
247  template <typename InPortalFieldType>
248  VTKM_EXEC vtkm::Id operator()(const vtkm::Id supernode, const InPortalFieldType& superarcs) const
249  {
250  if (vertexIsAssigned == false)
251  {
252  if (superarcs.Get(supernode) == NO_VERTEX_ASSIGNED)
253  return vtkm::Id(1);
254  else
255  return vtkm::Id(0);
256  }
257  else
258  {
259  if (superarcs.Get(supernode) != NO_VERTEX_ASSIGNED)
260  return vtkm::Id(1);
261  else
262  return vtkm::Id(0);
263  }
264  }
265 };
266 
267 // creates contour tree
268 template <typename T, typename StorageType>
270  MergeTree<T, StorageType>& JoinTree,
271  MergeTree<T, StorageType>& SplitTree,
272  ChainGraph<T, StorageType>& JoinGraph,
273  ChainGraph<T, StorageType>& SplitGraph)
274  : values(Values)
275  , joinTree(JoinTree)
276  , splitTree(SplitTree)
277  , joinGraph(JoinGraph)
278  , splitGraph(SplitGraph)
279 {
280 
281  // first we have to get the correct list of supernodes
282  // this will also set the degrees of the vertices initially
283  FindSupernodes();
284 
285  // and track how many iterations it takes
286  nIterations = 0;
287 
288  // loop until no arcs remaining to be found
289  // tree can end with either 0 or 1 vertices unprocessed
290  // 0 means the last edge was pruned from both ends
291  // 1 means that there were two final edges meeting at a vertex
292 
293  while (activeSupernodes.GetNumberOfValues() > 1)
294  { // loop until no active vertices remaining
295 #ifdef DEBUG_PRINT
296  std::cout << "========================================" << std::endl;
297  std::cout << " " << std::endl;
298  std::cout << "Iteration " << nIterations << " Size " << activeSupernodes.GetNumberOfValues()
299  << std::endl;
300  std::cout << " " << std::endl;
301  std::cout << "========================================" << std::endl;
302 #endif
303 
304  // transfer all leaves to the contour tree
305  TransferLeaves();
306 
307  // collapse regular vertices from leaves, upper then lower
308  CollapseRegular(true);
309  CollapseRegular(false);
310 
311  // compress the join and split trees
312  CompressTrees();
313 
314  // compress the active list of supernodes
316 
317  // recompute the vertex degrees
318  FindDegrees();
319 
320  nIterations++;
321  }
322 } // constructor
323 
324 // combines the list of active vertices for join & split trees
325 // then reduces them to eliminate regular vertices & non-connectivity critical points
326 template <typename T, typename StorageType>
328 {
329  // both trees may have non-connectivity critical points, so we first make a joint list
330  // here, we will explicitly assume that the active lists are in numerical order
331  // which is how we are currently constructing them
332  vtkm::Id nCandidates =
333  joinGraph.valueIndex.GetNumberOfValues() + splitGraph.valueIndex.GetNumberOfValues();
335 
336  // take the union of the two sets of vertices
338  joinGraph.valueIndex, splitGraph.valueIndex);
339  vtkm::cont::Algorithm::Copy(candidateArray, candidates);
340  vtkm::cont::Algorithm::Sort(candidates);
341  vtkm::cont::Algorithm::Unique(candidates);
342 
343  nCandidates = candidates.GetNumberOfValues();
344  vtkm::cont::ArrayHandleIndex candidateIndexArray(nCandidates);
345 
346  // we need an array lookup to convert vertex ID's
347  vtkm::Id nValues = values.GetNumberOfValues();
348  vtkm::cont::ArrayHandle<vtkm::Id> regularToCritical;
350  vtkm::cont::Algorithm::Copy(noVertArray, regularToCritical);
351 
352  if (nCandidates > 0)
353  {
354  RegularToCriticalUp regularToCriticalUp;
355  vtkm::worklet::DispatcherMapField<RegularToCriticalUp> regularToCriticalUpDispatcher(
356  regularToCriticalUp);
357 
358  regularToCriticalUpDispatcher.Invoke(candidateIndexArray, // input
359  candidates, // input
360  regularToCritical); // output (whole array)
361  }
362 
363  // now that we have a complete list of active nodes from each, we can call the trees
364  // to connect them properly
365  joinTree.ComputeAugmentedSuperarcs();
366  joinTree.ComputeAugmentedArcs(candidates);
367  splitTree.ComputeAugmentedSuperarcs();
368  splitTree.ComputeAugmentedArcs(candidates);
369 
370  // we create up & down degree arrays
371  vtkm::cont::ArrayHandleConstant<vtkm::Id> initCandidateArray(0, nCandidates);
373  vtkm::cont::ArrayHandle<vtkm::Id> downCandidate;
374  vtkm::cont::Algorithm::Copy(initCandidateArray, upCandidate);
375  vtkm::cont::Algorithm::Copy(initCandidateArray, downCandidate);
376 
377  // This next chunk changes in parallel - it has to count the up & down degree for each
378  // vertex. It's a simple loop in serial, but in parallel, what we have to do is:
379  // 1. Copy the lower ends of the edges, converting from regular ID to candidate ID
380  // 2. Sort the lower ends of the edges
381  // 3. For each value, store the beginning of the range
382  // 4. Compute the delta to get the degree.
383 
384  // create a sorting vector
386  sortVector.Allocate(nCandidates);
387 
388  // 1. Copy the lower ends of the edges, converting from regular ID to candidate ID
389  if (nCandidates > 0)
390  {
391  RegularToCandidate regularToCandidate;
392  vtkm::worklet::DispatcherMapField<RegularToCandidate> regularToCandidateDispatcher(
393  regularToCandidate);
394 
395  regularToCandidateDispatcher.Invoke(candidates, // input
396  joinTree.mergeArcs, // input (whole array)
397  regularToCritical, // input (whole array)
398  sortVector); // output
399  }
400 
401  // 2. Sort the lower ends of the edges
402  vtkm::cont::Algorithm::Sort(sortVector);
403 
404  // 3. For each value, store the beginning & end of the range (in parallel)
405  // The 0th element is guaranteed to be NO_VERTEX_ASSIGNED, & can be skipped
406  // Otherwise, if the i-1th element is different, we are the offset for the subrange
407  // and store into the ith place
408  vtkm::cont::ArrayHandleCounting<vtkm::Id> subsetIndexArray(1, 1, nCandidates - 1);
409  if (nCandidates > 0)
410  {
411  SubrangeOffset subRangeOffset;
412  vtkm::worklet::DispatcherMapField<SubrangeOffset> subrangeOffsetDispatcher(subRangeOffset);
413 
414  subrangeOffsetDispatcher.Invoke(subsetIndexArray, // index
415  sortVector, // input
416  upCandidate); // output
417  }
418 
419  // 4. Compute the delta to get the degree.
420  if (nCandidates > 0)
421  {
422  DegreeDelta degreeDelta(nCandidates);
423  vtkm::worklet::DispatcherMapField<DegreeDelta> degreeDeltaDispatcher(degreeDelta);
424 
425  degreeDeltaDispatcher.Invoke(subsetIndexArray, // input
426  sortVector, // input (whole array)
427  upCandidate); // output (whole array)
428  }
429 
430  // Now repeat the same steps for the downdegree
431  // 1. Copy the upper ends of the edges, converting from regular ID to candidate ID
432  if (nCandidates > 0)
433  {
434  RegularToCriticalDown regularToCriticalDown;
435  vtkm::worklet::DispatcherMapField<RegularToCriticalDown> regularToCriticalDownDispatcher(
436  regularToCriticalDown);
437 
438  regularToCriticalDownDispatcher.Invoke(candidates, // input
439  splitTree.mergeArcs, // input (whole array)
440  regularToCritical, // input (whole array)
441  sortVector); // output
442  }
443 
444  // 2. Sort the lower ends of the edges
445  vtkm::cont::Algorithm::Sort(sortVector);
446 
447  // 3. For each value, store the beginning & end of the range (in parallel)
448  // The 0th element is guaranteed to be NO_VERTEX_ASSIGNED, & can be skipped
449  // Otherwise, if the i-1th element is different, we are the offset for the subrange
450  // and store into the ith place
451  if (nCandidates > 0)
452  {
453  SubrangeOffset subRangeOffset;
454  vtkm::worklet::DispatcherMapField<SubrangeOffset> subrangeOffsetDispatcher(subRangeOffset);
455 
456  subrangeOffsetDispatcher.Invoke(subsetIndexArray, // index
457  sortVector, // input
458  downCandidate); // output
459  }
460 
461  // 4. Compute the delta to get the degree.
462  if (nCandidates > 0)
463  {
464  DegreeDelta degreeDelta(nCandidates);
465  vtkm::worklet::DispatcherMapField<DegreeDelta> degreeDeltaDispatcher(degreeDelta);
466 
467  degreeDeltaDispatcher.Invoke(subsetIndexArray, // index
468  sortVector, // input
469  downCandidate); // in out
470  }
471 
472  // create an index vector for whether the vertex is to be kept
474  isSupernode.Allocate(nCandidates);
475 
476  // fill the vector in
477  if (nCandidates > 0)
478  {
479  FillSupernodes fillSupernodes;
480  vtkm::worklet::DispatcherMapField<FillSupernodes> fillSupernodesDispatcher(fillSupernodes);
481 
482  fillSupernodesDispatcher.Invoke(upCandidate, // input
483  downCandidate, // input
484  isSupernode); // output
485  }
486 
487  // do a compaction to find the new index for each
488  // We end with 0 in position 0, and need one extra position to find the new size
490  vtkm::cont::Algorithm::ScanExclusive(isSupernode, supernodeID);
491 
492  // size is the position of the last element + the size of the last element (0/1)
493  vtkm::Id nSupernodes = vtkm::cont::ArrayGetValue(nCandidates - 1, supernodeID) +
494  vtkm::cont::ArrayGetValue(nCandidates - 1, isSupernode);
495 
496  // allocate memory for our arrays
497  supernodes.ReleaseResources();
498  updegree.ReleaseResources();
499  downdegree.ReleaseResources();
500 
501  supernodes.Allocate(nSupernodes);
502  updegree.Allocate(nSupernodes);
503  downdegree.Allocate(nSupernodes);
504 
505  // now copy over the positions to compact
506  if (nCandidates > 0)
507  {
508  CopySupernodes copySupernodes;
509  vtkm::worklet::DispatcherMapField<CopySupernodes> copySupernodesDispatcher(copySupernodes);
510 
511  copySupernodesDispatcher.Invoke(isSupernode, // input
512  candidates, // input
513  supernodeID, // input
514  upCandidate, // input
515  downCandidate, // input
516  regularToCritical, // output (whole array)
517  supernodes, // output (whole array)
518  updegree, // output (whole array)
519  downdegree); // output (whole array)
520  }
521 
522  // now we call the merge tree again to reset the merge arcs
523  joinTree.ComputeAugmentedArcs(supernodes);
524  splitTree.ComputeAugmentedArcs(supernodes);
525 
526  // next we create the working arrays of merge arcs
527  nSupernodes = supernodes.GetNumberOfValues();
528  vtkm::cont::ArrayHandleIndex supernodeIndexArray(nSupernodes);
529  joinArcs.ReleaseResources();
530  splitArcs.ReleaseResources();
531  joinArcs.Allocate(nSupernodes);
532  splitArcs.Allocate(nSupernodes);
533 
534  // and copy them across, setting IDs for both ends
535  SetJoinAndSplitArcs setJoinAndSplitArcs;
536  vtkm::worklet::DispatcherMapField<SetJoinAndSplitArcs> setJoinAndSplitArcsDispatcher(
537  setJoinAndSplitArcs);
538 
539  setJoinAndSplitArcsDispatcher.Invoke(supernodes, // input
540  joinTree.mergeArcs, // input (whole array)
541  splitTree.mergeArcs, // input (whole array)
542  regularToCritical, // input (whole array)
543  joinArcs, // output
544  splitArcs); // output
545 
547  superarcs.ReleaseResources();
548  vtkm::cont::Algorithm::Copy(newsuperarcs, superarcs);
549 
550  // create the active supernode vector
551  activeSupernodes.ReleaseResources();
552  activeSupernodes.Allocate(nSupernodes);
553  vtkm::cont::ArrayHandleIndex supernodeSeq(nSupernodes);
554  vtkm::cont::Algorithm::Copy(supernodeSeq, activeSupernodes);
555 
556 #ifdef DEBUG_PRINT
557  DebugPrint("Supernodes Found");
558 #endif
559 } // FindSupernodes()
560 
561 // transfers leaves from join/split trees to contour tree
562 template <typename T, typename StorageType>
564 {
565  FindLeaves findLeaves;
566  vtkm::worklet::DispatcherMapField<FindLeaves> findLeavesDispatcher(findLeaves);
567 
568  findLeavesDispatcher.Invoke(activeSupernodes, // input
569  updegree, // input (whole array)
570  downdegree, // input (whole array)
571  joinArcs, // input (whole array)
572  splitArcs, // input (whole array)
573  superarcs); // i/o (whole array)
574 #ifdef DEBUG_PRINT
575  DebugPrint("Leaves Transferred");
576 #endif
577 } // TransferLeaves()
578 
579 // collapses regular edges along leaf superarcs
580 template <typename T, typename StorageType>
582 {
583  // we'll have a vector for tracking outwards
584  vtkm::Id nSupernodes = supernodes.GetNumberOfValues();
585  vtkm::cont::ArrayHandleConstant<vtkm::Id> nullArray(0, nSupernodes);
587  outbound.Allocate(nSupernodes);
588  vtkm::cont::ArrayCopy(nullArray, outbound);
589 
590  // and a reference for the inwards array and to the degrees
594  if (isJoin)
595  {
596  vtkm::cont::ArrayCopy(joinArcs, inbound);
597  vtkm::cont::ArrayCopy(downdegree, indegree);
598  vtkm::cont::ArrayCopy(updegree, outdegree);
599  }
600  else
601  {
602  vtkm::cont::ArrayCopy(splitArcs, inbound);
603  vtkm::cont::ArrayCopy(updegree, indegree);
604  vtkm::cont::ArrayCopy(downdegree, outdegree);
605  }
606 
607  // loop to copy join/split
608  CopyJoinSplit copyJoinSplit;
609  vtkm::worklet::DispatcherMapField<CopyJoinSplit> copyJoinSplitDispatcher(copyJoinSplit);
610 
611  copyJoinSplitDispatcher.Invoke(activeSupernodes, // input
612  inbound, // input (whole array)
613  indegree, // input (whole array)
614  outdegree, // input (whole array)
615  outbound); // output (whole array)
616 
617  // Compute the number of log steps required in this pass
618  vtkm::Id nLogSteps = 1;
619  vtkm::Id nActiveSupernodes = activeSupernodes.GetNumberOfValues();
620  for (vtkm::Id shifter = nActiveSupernodes; shifter != 0; shifter >>= 1)
621  nLogSteps++;
622 
623  // loop to find the now-regular vertices and collapse past them without altering
624  // the existing join & split arcs
625  for (vtkm::Id iteration = 0; iteration < nLogSteps; iteration++)
626  {
627  UpdateOutbound updateOutbound;
628  vtkm::worklet::DispatcherMapField<UpdateOutbound> updateOutboundDispatcher(updateOutbound);
629 
630  updateOutboundDispatcher.Invoke(activeSupernodes, // input
631  outbound); // i/o (whole array)
632  }
633 
634  // at this point, the outbound vector chains everything outwards to the leaf
635  // any vertices on the last outbound leaf superarc point to the leaf
636 
637  // Now, any regular leaf vertex points out to a leaf, so the condition we test is
638  // a. outbound is not -1 (i.e. vertex is regular)
639  // b. superarc[outbound] is not -1 (i.e. outbound is a leaf)
640  SetSupernodeInward setSupernodeInward;
641  vtkm::worklet::DispatcherMapField<SetSupernodeInward> setSupernodeInwardDispatcher(
642  setSupernodeInward);
643 
644  setSupernodeInwardDispatcher.Invoke(activeSupernodes, // input
645  inbound, // input (whole array)
646  outbound, // input (whole array)
647  indegree, // input (whole array)
648  outdegree, // input (whole array)
649  superarcs); // i/o (whole array)
650  outbound.ReleaseResources();
651 
652 #ifdef DEBUG_PRINT
653  DebugPrint(isJoin ? "Upper Regular Nodes Collapsed" : "Lower Regular Nodes Collapsed");
654 #endif
655 } // CollapseRegular()
656 
657 // compresses trees to remove transferred vertices
658 template <typename T, typename StorageType>
660 {
661  // Compute the number of log steps required in this pass
662  vtkm::Id nActiveSupernodes = activeSupernodes.GetNumberOfValues();
663  vtkm::Id nLogSteps = 1;
664  for (vtkm::Id shifter = nActiveSupernodes; shifter != 0; shifter >>= 1)
665  nLogSteps++;
666 
667  // loop to update the merge trees
668  for (vtkm::Id logStep = 0; logStep < nLogSteps; logStep++)
669  {
670  SkipVertex skipVertex;
671  vtkm::worklet::DispatcherMapField<SkipVertex> skipVertexDispatcher(skipVertex);
672 
673  skipVertexDispatcher.Invoke(activeSupernodes, // input
674  superarcs, // input (whole array)
675  joinArcs, // i/o (whole array)
676  splitArcs); // i/o (whole array)
677  }
678 
679 #ifdef DEBUG_PRINT
680  DebugPrint("Trees Compressed");
681 #endif
682 } // CompressTrees()
683 
684 // compresses active set of supernodes
685 template <typename T, typename StorageType>
687 {
688  // copy only if the superarc is not set
689  vtkm::cont::ArrayHandle<vtkm::Id> noSuperarcArray;
690  noSuperarcArray.Allocate(activeSupernodes.GetNumberOfValues());
691 
692  VertexAssigned vertexAssigned(false);
693  vtkm::worklet::DispatcherMapField<VertexAssigned> vertexAssignedDispatcher(vertexAssigned);
694 
695  vertexAssignedDispatcher.Invoke(activeSupernodes, superarcs, noSuperarcArray);
696 
697  vtkm::cont::ArrayHandle<vtkm::Id> compressSupernodes;
698  vtkm::cont::Algorithm::CopyIf(activeSupernodes, noSuperarcArray, compressSupernodes);
699 
700  activeSupernodes.ReleaseResources();
701  vtkm::cont::ArrayCopy(compressSupernodes, activeSupernodes);
702 
703 #ifdef DEBUG_PRINT
704  DebugPrint("Active Supernodes Compressed");
705 #endif
706 } // CompressActiveSupernodes()
707 
708 // recomputes the degree of each supernode from the join & split trees
709 template <typename T, typename StorageType>
711 {
712  if (activeSupernodes.GetNumberOfValues() == 0)
713  return;
714 
715  vtkm::Id nActiveSupernodes = activeSupernodes.GetNumberOfValues();
716  ResetDegrees resetDegrees;
717  vtkm::worklet::DispatcherMapField<ResetDegrees> resetDegreesDispatcher(resetDegrees);
718 
719  resetDegreesDispatcher.Invoke(activeSupernodes, // input
720  updegree, // output (whole array)
721  downdegree); // output (whole array)
722 
723  // create a temporary sorting array
725  sortVector.Allocate(nActiveSupernodes);
726  vtkm::cont::ArrayHandleIndex activeSupernodeIndexArray(nActiveSupernodes);
727 
728  // 1. Copy the neighbours for each active edge
729  if (nActiveSupernodes > 0)
730  {
731  CopyNeighbors copyNeighbors;
732  vtkm::worklet::DispatcherMapField<CopyNeighbors> copyNeighborsDispatcher(copyNeighbors);
733 
734  copyNeighborsDispatcher.Invoke(activeSupernodeIndexArray, // input
735  activeSupernodes, // input (whole array)
736  joinArcs, // input (whole array)
737  sortVector); // output
738  }
739 
740  // 2. Sort the neighbours
741  vtkm::cont::Algorithm::Sort(sortVector);
742 
743  // 3. For each value, store the beginning & end of the range (in parallel)
744  // The 0th element is guaranteed to be NO_VERTEX_ASSIGNED, & can be skipped
745  // Otherwise, if the i-1th element is different, we are the offset for the subrange
746  // and store into the ith place
747  vtkm::cont::ArrayHandleCounting<vtkm::Id> subsetIndexArray(1, 1, nActiveSupernodes - 1);
748  if (nActiveSupernodes > 1)
749  {
750  DegreeSubrangeOffset degreeSubrangeOffset;
751  vtkm::worklet::DispatcherMapField<DegreeSubrangeOffset> degreeSubrangeOffsetDispatcher(
752  degreeSubrangeOffset);
753 
754  degreeSubrangeOffsetDispatcher.Invoke(subsetIndexArray, // input
755  sortVector, // input (whole array)
756  updegree); // output (whole array)
757  }
758 
759  // 4. Compute the delta to get the degree.
760  if (nActiveSupernodes > 1)
761  {
762  DegreeDelta degreeDelta(nActiveSupernodes);
763  vtkm::worklet::DispatcherMapField<DegreeDelta> degreeDeltaDispatcher(degreeDelta);
764 
765  degreeDeltaDispatcher.Invoke(subsetIndexArray, // input
766  sortVector, // input
767  updegree); // in out
768  }
769 
770  // Now repeat the same steps for the downdegree
771  // 1. Copy the neighbours for each active edge
772  if (nActiveSupernodes > 0)
773  {
774  CopyNeighbors copyNeighbors;
775  vtkm::worklet::DispatcherMapField<CopyNeighbors> copyNeighborsDispatcher(copyNeighbors);
776 
777  copyNeighborsDispatcher.Invoke(activeSupernodeIndexArray, // input
778  activeSupernodes, // input (whole array)
779  splitArcs, // input (whole array)
780  sortVector); // output
781  }
782 
783  // 2. Sort the neighbours
784  vtkm::cont::Algorithm::Sort(sortVector);
785 
786  // 3. For each value, store the beginning & end of the range (in parallel)
787  // The 0th element is guaranteed to be NO_VERTEX_ASSIGNED, & can be skipped
788  // Otherwise, if the i-1th element is different, we are the offset for the subrange
789  // and store into the ith place
790  if (nActiveSupernodes > 1)
791  {
792  DegreeSubrangeOffset degreeSubrangeOffset;
793  vtkm::worklet::DispatcherMapField<DegreeSubrangeOffset> degreeSubrangeOffsetDispatcher(
794  degreeSubrangeOffset);
795 
796  degreeSubrangeOffsetDispatcher.Invoke(subsetIndexArray, // input
797  sortVector, // input (whole array)
798  downdegree); // output (whole array)
799  }
800 
801  // 4. Compute the delta to get the degree.
802  if (nActiveSupernodes > 1)
803  {
804  DegreeDelta degreeDelta(nActiveSupernodes);
805  vtkm::worklet::DispatcherMapField<DegreeDelta> degreeDeltaDispatcher(degreeDelta);
806 
807  degreeDeltaDispatcher.Invoke(subsetIndexArray, // input
808  sortVector, // input (whole array)
809  downdegree); // in out (whole array)
810  }
811 #ifdef DEBUG_PRINT
812  DebugPrint("Degrees Recomputed");
813 #endif
814 } // FindDegrees()
815 
816 // small class for storing the contour arcs
817 class EdgePair
818 {
819 public:
821 
822  // constructor - defaults to -1
823  EdgePair(vtkm::Id Low = -1, vtkm::Id High = -1)
824  : low(Low)
825  , high(High)
826  {
827  }
828 };
829 
830 // comparison operator <
831 bool operator<(const EdgePair LHS, const EdgePair RHS)
832 {
833  if (LHS.low < RHS.low)
834  return true;
835  if (LHS.low > RHS.low)
836  return false;
837  if (LHS.high < RHS.high)
838  return true;
839  if (LHS.high > RHS.high)
840  return false;
841  return false;
842 }
843 
845 {
847  const vtkm::Pair<vtkm::Id, vtkm::Id>& b) const
848  {
849  if (a.first < b.first)
850  return true;
851  if (a.first > b.first)
852  return false;
853  if (a.second < b.second)
854  return true;
855  if (a.second > b.second)
856  return false;
857  return false;
858  }
859 };
860 
861 // sorted print routine
862 template <typename T, typename StorageType>
865 {
866  // Collect the valid saddle peak pairs
867  std::vector<vtkm::Pair<vtkm::Id, vtkm::Id>> superarcVector;
868  const auto supernodePortal = supernodes.ReadPortal();
869  const auto superarcPortal = superarcs.ReadPortal();
870  for (vtkm::Id supernode = 0; supernode < supernodes.GetNumberOfValues(); supernode++)
871  {
872  // ID of regular node
873  const vtkm::Id regularID = supernodePortal.Get(supernode);
874 
875  // retrieve ID of target supernode
876  const vtkm::Id superTo = superarcPortal.Get(supernode);
877  ;
878 
879  // if this is true, it is the last pruned vertex
880  if (superTo == NO_VERTEX_ASSIGNED)
881  {
882  continue;
883  }
884 
885  // retrieve the regular ID for it
886  const vtkm::Id regularTo = supernodePortal.Get(superTo);
887 
888  // how we print depends on which end has lower ID
889  if (regularID < regularTo)
890  { // from is lower
891  // extra test to catch duplicate edge
892  if (superarcPortal.Get(superTo) != supernode)
893  {
894  superarcVector.push_back(vtkm::make_Pair(regularID, regularTo));
895  }
896  } // from is lower
897  else
898  {
899  superarcVector.push_back(vtkm::make_Pair(regularTo, regularID));
900  }
901  } // per vertex
902 
903  // Setting saddlePeak reference to the make_ArrayHandle directly does not work
906 
907  // now sort it
909  vtkm::cont::Algorithm::Copy(tempArray, saddlePeak);
910 
911 #ifdef DEBUG_PRINT
912  const vtkm::Id arcVecSize = static_cast<vtkm::Id>(superarcVector.size());
913  for (vtkm::Id superarc = 0; superarc < arcVecSize; superarc++)
914  {
915  std::cout << std::setw(PRINT_WIDTH) << saddlePeak.WritePortal().Get(superarc).first << " ";
916  std::cout << std::setw(PRINT_WIDTH) << saddlePeak.WritePortal().Get(superarc).second
917  << std::endl;
918  }
919 #endif
920 } // CollectSaddlePeak()
921 
922 // debug routine
923 template <typename T, typename StorageType>
925 {
926  std::cout << "---------------------------" << std::endl;
927  std::cout << std::string(message) << std::endl;
928  std::cout << "---------------------------" << std::endl;
929  std::cout << std::endl;
930 
931  // print out the supernode arrays
932  vtkm::Id nSupernodes = supernodes.GetNumberOfValues();
933  PrintHeader(nSupernodes);
934 
935  PrintIndices("Supernodes", supernodes);
936 
938  vtkm::cont::ArrayCopy(PermuteValueType(supernodes, values), supervalues);
939  PrintValues("Value", supervalues);
940 
941  PrintIndices("Up degree", updegree);
942  PrintIndices("Down degree", downdegree);
943  PrintIndices("Join arc", joinArcs);
944  PrintIndices("Split arc", splitArcs);
945  PrintIndices("Superarcs", superarcs);
946  std::cout << std::endl;
947 
948  // print out the active supernodes
949  vtkm::Id nActiveSupernodes = activeSupernodes.GetNumberOfValues();
950  PrintHeader(nActiveSupernodes);
951 
952  PrintIndices("Active Supernodes", activeSupernodes);
953 
954  vtkm::cont::ArrayHandle<vtkm::Id> activeUpdegree;
955  vtkm::cont::ArrayCopy(PermuteIndexType(activeSupernodes, updegree), activeUpdegree);
956  PrintIndices("Active Up Degree", activeUpdegree);
957 
958  vtkm::cont::ArrayHandle<vtkm::Id> activeDowndegree;
959  vtkm::cont::ArrayCopy(PermuteIndexType(activeSupernodes, downdegree), activeDowndegree);
960  PrintIndices("Active Down Degree", activeDowndegree);
961 
962  vtkm::cont::ArrayHandle<vtkm::Id> activeJoinArcs;
963  vtkm::cont::ArrayCopy(PermuteIndexType(activeSupernodes, joinArcs), activeJoinArcs);
964  PrintIndices("Active Join Arcs", activeJoinArcs);
965 
966  vtkm::cont::ArrayHandle<vtkm::Id> activeSplitArcs;
967  vtkm::cont::ArrayCopy(PermuteIndexType(activeSupernodes, splitArcs), activeSplitArcs);
968  PrintIndices("Active Split Arcs", activeSplitArcs);
969 
970  vtkm::cont::ArrayHandle<vtkm::Id> activeSuperarcs;
971  vtkm::cont::ArrayCopy(PermuteIndexType(activeSupernodes, superarcs), activeSuperarcs);
972  PrintIndices("Active Superarcs", activeSuperarcs);
973  std::cout << std::endl;
974 } // DebugPrint()
975 }
976 }
977 }
978 
979 #endif
ArrayHandleConcatenate.h
vtkm::worklet::contourtree::PrintHeader
void PrintHeader(vtkm::Id howMany)
Definition: PrintVectors.h:155
vtkm::worklet::contourtree::VertexAssigned::operator()
VTKM_EXEC vtkm::Id operator()(const vtkm::Id supernode, const InPortalFieldType &superarcs) const
Definition: ContourTree.h:248
vtkm::cont::ArrayHandle::GetNumberOfValues
VTKM_CONT vtkm::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:448
vtkm::cont::make_ArrayHandle
VTKM_CONT vtkm::cont::ArrayHandleBasic< T > make_ArrayHandle(const T *array, vtkm::Id numberOfValues, vtkm::CopyFlag copy)
A convenience function for creating an ArrayHandle from a standard C array.
Definition: ArrayHandleBasic.h:217
vtkm::worklet::contourtree::ChainGraph
Definition: ChainGraph.h:127
vtkm::worklet::contourtree::SaddlePeakSort
Definition: ContourTree.h:844
vtkm::cont::ArrayHandle< vtkm::Id >
ArrayHandle.h
vtkm::make_Pair
VTKM_EXEC_CONT vtkm::Pair< typename std::decay< T1 >::type, typename std::decay< T2 >::type > make_Pair(T1 &&v1, T2 &&v2)
Definition: Pair.h:164
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::ContourTree::CompressTrees
void CompressTrees()
Definition: ContourTree.h:659
vtkm::worklet::contourtree::ContourTree::splitGraph
ChainGraph< T, StorageType > & splitGraph
Definition: ContourTree.h:187
vtkm::worklet::contourtree::SaddlePeakSort::operator()
VTKM_EXEC_CONT bool operator()(const vtkm::Pair< vtkm::Id, vtkm::Id > &a, const vtkm::Pair< vtkm::Id, vtkm::Id > &b) const
Definition: ContourTree.h:846
vtkm::worklet::contourtree::VertexAssigned::ExecutionSignature
_3(_1, _2) ExecutionSignature
Definition: ContourTree.h:236
FindLeaves.h
vtkm::cont::ArrayHandleConcatenate
Definition: ArrayHandleConcatenate.h:241
MergeTree.h
vtkm::worklet::contourtree::CopyJoinSplit
Definition: CopyJoinSplit.h:71
vtkm::worklet::contourtree::VertexAssigned::vertexIsAssigned
bool vertexIsAssigned
Definition: ContourTree.h:239
WorkletMapField.h
ChainGraph.h
vtkm::worklet::contourtree::CopySupernodes
Definition: CopySupernodes.h:70
VTKM_EXEC_CONT
#define VTKM_EXEC_CONT
Definition: ExportMacros.h:52
vtkm::worklet::contourtree::ResetDegrees
Definition: ResetDegrees.h:70
vtkm::cont::ArrayHandle::Allocate
VTKM_CONT void Allocate(vtkm::Id numberOfValues, vtkm::CopyFlag preserve, vtkm::cont::Token &token) const
Allocates an array large enough to hold the given number of values.
Definition: ArrayHandle.h:465
vtkm::worklet::WorkletMapField::FieldOut
A control signature tag for output fields.
Definition: WorkletMapField.h:60
vtkm::worklet::contourtree::MergeTree
Definition: MergeTree.h:126
vtkm::worklet::contourtree::UpdateOutbound
Definition: UpdateOutbound.h:71
PRINT_WIDTH
#define PRINT_WIDTH
Definition: PrintVectors.h:77
Pair.h
vtkm::worklet::contourtree::RegularToCandidate
Definition: RegularToCandidate.h:71
vtkm::worklet::contourtree::EdgePair::low
vtkm::Id low
Definition: ContourTree.h:820
SubrangeOffset.h
CopyJoinSplit.h
vtkm::worklet::contourtree::ContourTree::superarcs
vtkm::cont::ArrayHandle< vtkm::Id > superarcs
Definition: ContourTree.h:175
vtkm::cont::Algorithm::Sort
static VTKM_CONT void Sort(vtkm::cont::DeviceAdapterId devId, vtkm::cont::ArrayHandle< T, Storage > &values)
Definition: Algorithm.h:965
vtkm::worklet::contourtree::operator<
bool operator<(const EdgePair LHS, const EdgePair RHS)
Definition: ContourTree.h:831
vtkm::worklet::contourtree::ContourTree::CompressActiveSupernodes
void CompressActiveSupernodes()
Definition: ContourTree.h:686
vtkm::cont::ArrayGetValue
VTKM_CONT T ArrayGetValue(vtkm::Id id, const vtkm::cont::ArrayHandle< T, S > &data)
Obtain a small set of values from an ArrayHandle with minimal device transfers.
Definition: ArrayGetValues.h:264
vtkm::cont::Algorithm::Copy
static VTKM_CONT bool Copy(vtkm::cont::DeviceAdapterId devId, const vtkm::cont::ArrayHandle< T, CIn > &input, vtkm::cont::ArrayHandle< U, COut > &output)
Definition: Algorithm.h:410
FillSupernodes.h
vtkm::worklet::contourtree::ContourTree::CollapseRegular
void CollapseRegular(bool isJoin)
Definition: ContourTree.h:581
vtkm::worklet::contourtree::SetSupernodeInward
Definition: SetSupernodeInward.h:71
vtkm::worklet::contourtree::DegreeDelta
Definition: DegreeDelta.h:70
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::worklet::contourtree::ContourTree::updegree
vtkm::cont::ArrayHandle< vtkm::Id > updegree
Definition: ContourTree.h:190
RegularToCandidate.h
vtkm::worklet::contourtree::PrintValues
void PrintValues(std::string label, vtkm::cont::ArrayHandle< T, StorageType > &dVec, vtkm::Id nValues=-1)
Definition: PrintVectors.h:174
CopyNeighbors.h
SkipVertex.h
UpdateOutbound.h
vtkm::worklet::contourtree::ContourTree::supernodes
vtkm::cont::ArrayHandle< vtkm::Id > supernodes
Definition: ContourTree.h:178
vtkm::cont::Algorithm::Unique
static VTKM_CONT void Unique(vtkm::cont::DeviceAdapterId devId, vtkm::cont::ArrayHandle< T, Storage > &values)
Definition: Algorithm.h:1063
vtkm::worklet::DispatcherMapField
Dispatcher for worklets that inherit from WorkletMapField.
Definition: DispatcherMapField.h:25
DegreeSubrangeOffset.h
vtkm::worklet::contourtree::VertexAssigned::InputDomain
_1 InputDomain
Definition: ContourTree.h:237
CopySupernodes.h
ArrayHandlePermutation.h
vtkm::worklet::contourtree::VertexAssigned
Definition: ContourTree.h:232
vtkm::worklet::WorkletMapField::FieldIn
A control signature tag for input fields.
Definition: WorkletMapField.h:49
vtkm::cont::Algorithm::ScanExclusive
static VTKM_CONT T ScanExclusive(vtkm::cont::DeviceAdapterId devId, const vtkm::cont::ArrayHandle< T, CIn > &input, vtkm::cont::ArrayHandle< T, COut > &output)
Definition: Algorithm.h:816
vtkm::cont::ArrayHandlePermutation
Implicitly permutes the values in an array.
Definition: ArrayHandlePermutation.h:227
vtkm::cont::ArrayHandleCounting< vtkm::Id >
vtkm::Pair::first
FirstType first
The pair's first object.
Definition: Pair.h:50
vtkm::cont::ArrayCopy
void ArrayCopy(const SourceArrayType &source, DestArrayType &destination)
Does a deep copy from one array to another array.
Definition: ArrayCopy.h:142
vtkm::cont::Algorithm::CopyIf
static VTKM_CONT void CopyIf(vtkm::cont::DeviceAdapterId devId, const vtkm::cont::ArrayHandle< T, CIn > &input, const vtkm::cont::ArrayHandle< U, CStencil > &stencil, vtkm::cont::ArrayHandle< T, COut > &output)
Definition: Algorithm.h:435
vtkm::worklet::contourtree::EdgePair::EdgePair
EdgePair(vtkm::Id Low=-1, vtkm::Id High=-1)
Definition: ContourTree.h:823
vtkm::worklet::contourtree::ContourTree::downdegree
vtkm::cont::ArrayHandle< vtkm::Id > downdegree
Definition: ContourTree.h:190
ResetDegrees.h
vtkm::worklet::contourtree::ContourTree::joinGraph
ChainGraph< T, StorageType > & joinGraph
Definition: ContourTree.h:187
vtkm::worklet::contourtree::VertexAssigned::ControlSignature
void(FieldIn supernode, WholeArrayIn superarcs, FieldOut hasSuperArc) ControlSignature
Definition: ContourTree.h:235
NO_VERTEX_ASSIGNED
#define NO_VERTEX_ASSIGNED
Definition: filter/scalar_topology/worklet/contourtree/Types.h:77
vtkm::worklet::contourtree::ContourTree::splitTree
MergeTree< T, StorageType > & splitTree
Definition: ContourTree.h:184
RegularToCriticalUp.h
vtkm::cont::ArrayHandleConstant
An array handle with a constant value.
Definition: ArrayHandleConstant.h:63
vtkm::worklet::contourtree::RegularToCriticalDown
Definition: RegularToCriticalDown.h:71
ArrayGetValues.h
vtkm::worklet::contourtree::SkipVertex
Definition: SkipVertex.h:71
vtkm::worklet::contourtree::ContourTree::DebugPrint
void DebugPrint(const char *message)
Definition: ContourTree.h:924
vtkm::worklet::contourtree::EdgePair::high
vtkm::Id high
Definition: ContourTree.h:820
vtkm::worklet::contourtree::ContourTree::values
const vtkm::cont::ArrayHandle< T, StorageType > values
Definition: ContourTree.h:172
vtkm::CopyFlag::Off
@ Off
SetSupernodeInward.h
vtkm::worklet::contourtree::ContourTree::FindSupernodes
void FindSupernodes()
Definition: ContourTree.h:327
SetJoinAndSplitArcs.h
vtkm::worklet::contourtree::ContourTree::ContourTree
ContourTree(const vtkm::cont::ArrayHandle< T, StorageType > &Values, MergeTree< T, StorageType > &JoinTree, MergeTree< T, StorageType > &SplitTree, ChainGraph< T, StorageType > &JoinGraph, ChainGraph< T, StorageType > &SplitGraph)
Definition: ContourTree.h:269
vtkm::worklet::contourtree::EdgePair
Definition: ContourTree.h:817
vtkm::worklet::contourtree::ContourTree
Definition: ContourTree.h:163
DegreeDelta.h
vtkm::worklet::contourtree::FillSupernodes
Definition: FillSupernodes.h:70
vtkm::worklet::contourtree::SetJoinAndSplitArcs
Definition: SetJoinAndSplitArcs.h:71
RegularToCriticalDown.h
vtkm::worklet::contourtree::RegularToCriticalUp
Definition: RegularToCriticalUp.h:70
vtkm::worklet::contourtree::ContourTree::CollectSaddlePeak
void CollectSaddlePeak(vtkm::cont::ArrayHandle< vtkm::Pair< vtkm::Id, vtkm::Id >> &saddlePeak)
Definition: ContourTree.h:863
PrintVectors.h
vtkm::worklet::contourtree::ContourTree::TransferLeaves
void TransferLeaves()
Definition: ContourTree.h:563
vtkm::worklet::contourtree::PrintIndices
void PrintIndices(std::string label, vtkm::cont::ArrayHandle< vtkm::Id > &iVec, vtkm::Id nIndices=-1)
Definition: PrintVectors.h:202
vtkm::worklet::contourtree::VertexAssigned::VertexAssigned
VTKM_EXEC_CONT VertexAssigned(bool VertexIsAssigned)
Definition: ContourTree.h:242
Types.h
vtkm::worklet::contourtree::SubrangeOffset
Definition: SubrangeOffset.h:70
vtkm::worklet::contourtree::ContourTree::splitArcs
vtkm::cont::ArrayHandle< vtkm::Id > splitArcs
Definition: ContourTree.h:193
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::cont::ArrayHandle::ReleaseResources
VTKM_CONT void ReleaseResources() const
Releases all resources in both the control and execution environments.
Definition: ArrayHandle.h:559
vtkm::worklet::contourtree::DegreeSubrangeOffset
Definition: DegreeSubrangeOffset.h:71
vtkm::worklet::contourtree::ContourTree::nIterations
vtkm::Id nIterations
Definition: ContourTree.h:196
vtkm::worklet::contourtree::ContourTree::joinTree
MergeTree< T, StorageType > & joinTree
Definition: ContourTree.h:184
vtkm::Pair::second
SecondType second
The pair's second object.
Definition: Pair.h:55
vtkm::worklet::contourtree::ContourTree::activeSupernodes
vtkm::cont::ArrayHandle< vtkm::Id > activeSupernodes
Definition: ContourTree.h:181
vtkm::worklet::contourtree::FindLeaves
Definition: FindLeaves.h:71
vtkm::cont::ArrayHandleIndex
An implicit array handle containing the its own indices.
Definition: ArrayHandleIndex.h:54
vtkm::worklet::contourtree::ContourTree::FindDegrees
void FindDegrees()
Definition: ContourTree.h:710
vtkm::worklet::WorkletMapField
Base class for worklets that do a simple mapping of field arrays.
Definition: WorkletMapField.h:38
vtkm::worklet::contourtree::ContourTree::joinArcs
vtkm::cont::ArrayHandle< vtkm::Id > joinArcs
Definition: ContourTree.h:193
vtkm::worklet::contourtree::CopyNeighbors
Definition: CopyNeighbors.h:71