VTK-m  2.0
HierarchicalAugmenter.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 // Parallel Peak Pruning v. 2.0
43 //
44 // Started June 15, 2017
45 //
46 // Copyright Hamish Carr, University of Leeds
47 //
48 // HierarchicalAugmenter.h
49 //
50 //=======================================================================================
51 //
52 // COMMENTS:
53 //
54 // In order to compute geometric measures properly, we probably need to have all supernodes
55 // inserted rather than the lazy insertion implicit in the existing computation. After discussion,
56 // we have decided to make this a post-processing step in order to keep our options open.
57 //
58 // Fortunately, the HierarchicalContourTree structure will hold a tree augmented with lower level
59 // supernodes, so we just want a factory class that takes a HCT as input and produces another one
60 // as output. Note that the output will no longer have insertions to be made, as all subtrees will
61 // be rooted at a supernode in the parent level.
62 //
63 // Since this is blockwise, we will have the main loop external (as with the HierarchicalHyperSweeper)
64 // and have it invoke subroutines here
65 //
66 // The processing will be based on a fanin with partners as usual
67 // I. Each block swaps all attachment points for the level with its partner
68 // II. Fanning-in builds sets of all attachment points to insert into each superarc except the base level
69 // III.At the end of the fanin, we know the complete set of all supernodes to be inserted in all superarcs,
70 // so we insert them all at once & renumber. We should not need to do so in a fan-out
71 //
72 // After some prototyping in Excel, the test we will need to apply is the following:
73 //
74 // In round N, we transfer all attachment points whose round is < N+1 and whose superparent round is >= N+1
75 // (NB: In excel, I started with Round 1, when I should have started with round 0 to keep the swap-partner correct)
76 //
77 // The superparent round is the round at which the attachment point will be inserted at the end, so the
78 // attachment point needs to be shared at all levels up to and including that round, hence the second branch
79 // of the test.
80 //
81 // The first branch is because the attachment points at round N are already represented in the partner
82 // due to the construction of the hierarchical contour tree. Therefore transferring them is redundant and
83 // complicates processing, so we omit them. For higher levels, they will need to be inserted.
84 //
85 // This test is independent of things such as sort order, so we can keep our arrays in unsorted order.
86 // We may wish to revisit this later to enforce a canonical order for validation / verification
87 // but as long as we are consistent, we should in fact have a canonical ordering on each block.
88 //
89 //=======================================================================================
90 
91 #ifndef vtk_m_worklet_contourtree_distributed_hierarchical_augmenter_h
92 #define vtk_m_worklet_contourtree_distributed_hierarchical_augmenter_h
93 
94 #include <iomanip>
95 #include <string>
116 
117 
118 namespace vtkm
119 {
120 namespace worklet
121 {
122 namespace contourtree_distributed
123 {
124 
126 template <typename FieldType>
128 { // class HierarchicalAugmenter
129 public:
134 
137 
140 
143 
148 
154 
158 
161 
167  FieldType>
171  FieldType>
173 
193 
196 
198  void Initialize(
199  vtkm::Id blockId,
202 
205 
208 
210  void ReleaseSwapArrays();
211 
213  void BuildAugmentedTree();
214 
215  // subroutines for BuildAugmentedTree
217  void PrepareAugmentedTree();
219  void CopyHyperstructure();
221  void CopySuperstructure();
223  void UpdateHyperstructure();
226 
227  // subroutines for CopySuperstructure
229  void RetrieveOldSupernodes(vtkm::Id roundNumber);
231  void ResizeArrays(vtkm::Id roundNumber);
233  void CreateSuperarcs(vtkm::Id roundNumber);
234 
236  std::string DebugPrint(std::string message, const char* fileName, long lineNum);
237  void DebugSave(std::string filename);
238 
239 private:
242 
243 }; // class HierarchicalAugmenter
244 
245 
246 
247 // initalizating function
248 template <typename FieldType>
250  vtkm::Id blockId,
253 { // Initialize()
254  // copy the parameters for use
255  this->BlockId = blockId;
256  this->BaseTree = baseTree;
257  this->AugmentedTree = augmentedTree;
258 
259  // now construct a list of all attachment points on the block
260  // to do this, we construct an index array with all supernode ID's that satisfy:
261  // 1. superparent == NO_SUCH_ELEMENT (i.e. root of interior tree)
262  // 2. round < nRounds (except the top level, where 1. indicates the tree root)
263  // initalize AttachementIds
264  {
266  isAttachementPointPredicate(
267  this->BaseTree->Superarcs, this->BaseTree->WhichRound, this->BaseTree->NumRounds);
268  auto tempSupernodeIndex =
269  vtkm::cont::ArrayHandleIndex(this->BaseTree->Supernodes.GetNumberOfValues());
271  // first a list of all of the supernodes
272  tempSupernodeIndex,
273  // then our stencil
274  tempSupernodeIndex,
275  // And the CopyIf compress the supernodes array to eliminate the non-attachement points and
276  // save to this->AttachmentIds
277  this->AttachmentIds,
278  // then our predicate identifies all attachment points
279  // i.e., an attachment point is defined by having no superarc (NO_SUCH_ELEMENT) and not
280  // being in the final round (where this indicates the global root) defined by the condition
281  // if (noSuchElement(baseTree->superarcs[supernode]) && (baseTree->whichRound[supernode] < baseTree->nRounds))
282  isAttachementPointPredicate);
283  }
284 
285  // we now resize the working arrays
286  this->GlobalRegularIds.Allocate(this->AttachmentIds.GetNumberOfValues());
287  this->DataValues.Allocate(this->AttachmentIds.GetNumberOfValues());
288  this->SupernodeIds.Allocate(this->AttachmentIds.GetNumberOfValues());
289  this->Superparents.Allocate(this->AttachmentIds.GetNumberOfValues());
290  this->SuperparentRounds.Allocate(this->AttachmentIds.GetNumberOfValues());
291  this->WhichRounds.Allocate(this->AttachmentIds.GetNumberOfValues());
292 
293  // and do an indexed copy (permutation) to copy in the attachment point information
294  {
295  auto hierarchicalRegularIds =
296  vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->BaseTree->Supernodes);
297  auto superparents =
298  vtkm::cont::make_ArrayHandlePermutation(hierarchicalRegularIds, this->BaseTree->Superparents);
299  // globalRegularIDs[attachmentPoint] = baseTree->regularNodeGlobalIDs[hierarchicalRegularID];
301  hierarchicalRegularIds, BaseTree->RegularNodeGlobalIds),
302  this->GlobalRegularIds);
303  //dataValues[attachmentPoint] = baseTree->dataValues [hierarchicalRegularID];
305  vtkm::cont::make_ArrayHandlePermutation(hierarchicalRegularIds, BaseTree->DataValues),
306  this->DataValues);
307  //supernodeIDs[attachmentPoint] = supernodeID;
308  vtkm::cont::Algorithm::Copy(this->AttachmentIds, // these are our supernodeIds
309  this->SupernodeIds);
310  //superparentRounds[attachmentPoint] = baseTree->whichRound [superparent];
312  vtkm::cont::make_ArrayHandlePermutation(superparents, this->BaseTree->WhichRound),
313  this->SuperparentRounds);
314  //whichRounds[attachmentPoint] = baseTree->whichRound[supernodeID];
316  vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->BaseTree->WhichRound),
317  this->WhichRounds);
318 
319  // get the ascending flag from the superparent's superarc and transfer to the superparent
320  // Array decorator to add the IS_ASCENDING flag to our superparent, i.e.,
321  // if (isAscending(baseTree->superarcs[superparent])){ superparent |= IS_ASCENDING; }
322  // TODO: When using the superparents ArrayHandlePermutation in the ArrayHandleDecorator the compiler
323  // has issues discovering the StorageType when calling Copy(isAscendingSuperparentArr, superparents)
324  // by copying superparents to an actual array in tempArrSuperparents we can avoid this issue,
325  // at the cost of an extra copy.
327  vtkm::cont::Algorithm::Copy(superparents, tempArrSuperparents);
328  auto isAscendingSuperparentArr = vtkm::cont::make_ArrayHandleDecorator(
329  tempArrSuperparents.GetNumberOfValues(), //superparents.GetNumberOfValues(),
331  tempArrSuperparents, //superparents,
332  this->BaseTree->Superarcs);
333  vtkm::cont::Algorithm::Copy(isAscendingSuperparentArr, this->Superparents);
334  }
335 
336  // clean up memory
337  this->AttachmentIds.ReleaseResources();
338 } // Initialize()
339 
340 
341 
342 // routine to prepare the set of attachment points to transfer
343 template <typename FieldType>
345 { // PrepareOutAttachmentPoints()
346  {
347  vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
348  IsAttachementPointNeededPredicate isAttachementPointNeededPredicate(
349  this->SuperparentRounds, this->WhichRounds, round);
350  auto tempAttachmentPointsIndex =
351  vtkm::cont::ArrayHandleIndex(this->GlobalRegularIds.GetNumberOfValues());
353  // 1. fancy array of all of the attachment points of which parts are copied to this->AttachmentIds
354  tempAttachmentPointsIndex, // input
355  // 2. stencil used with the predicate to decide which AttachementIds to keep
356  tempAttachmentPointsIndex, // stencil
357  // 3. CopyIf compress the supernodes array to eliminate the non-attachement
358  // points and save to this->AttachmentIds
359  this->AttachmentIds,
360  // 4. the unary predicate uses the stencil to identify all attachment points needed
361  isAttachementPointNeededPredicate);
362  }
363 
364  // 4. resize the out array. We don't need to allocate here because in step 5. the Copy
365  // algorithm will do the initalization for us
366 
367  // 5. copy the points we want
368  {
369  // outGlobalRegularIDs[outAttachmentPoint] = globalRegularIDs[attachmentPoint];
371  vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->GlobalRegularIds),
372  this->OutData.GlobalRegularIds);
373  // outDataValues[outAttachmentPoint] = dataValues[attachmentPoint];
375  vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->DataValues),
376  this->OutData.DataValues);
377  // outSupernodeIDs[outAttachmentPoint] = supernodeIDs[attachmentPoint];
379  vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->SupernodeIds),
380  this->OutData.SupernodeIds);
381  // outSuperparents[outAttachmentPoint] = superparents[attachmentPoint];
383  vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->Superparents),
384  this->OutData.Superparents);
385  // outSuperparentRounds[outAttachmentPoint] = superparentRounds[attachmentPoint];
387  vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->SuperparentRounds),
388  this->OutData.SuperparentRounds);
389  // outWhichRounds[outAttachmentPoint] = whichRounds[attachmentPoint];
391  vtkm::cont::make_ArrayHandlePermutation(this->AttachmentIds, this->WhichRounds),
392  this->OutData.WhichRounds);
393  }
394 
395  // clean up memory
396  this->AttachmentIds.ReleaseResources();
397 } // PrepareOutAttachmentPoints()
398 
399 
400 // routine to add partner's current list of attachment points
401 template <typename FieldType>
403 { // RetrieveInAttachmentPoints()
404  // what we want to do here is to copy all of the partner's attachments for the round into our own buffer
405  // this code will be replaced in the MPI with a suitable transmit / receive
406  // store the current size
407  vtkm::Id numAttachmentsCurrently = this->GlobalRegularIds.GetNumberOfValues();
408  vtkm::Id numIncomingAttachments = InData.GlobalRegularIds.GetNumberOfValues();
409  vtkm::Id numTotalAttachments = numAttachmentsCurrently + numIncomingAttachments;
410 
411  // I. resize the existing arrays
412  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
413  this->GlobalRegularIds, numTotalAttachments, static_cast<vtkm::Id>(0));
414  vtkm::worklet::contourtree_augmented::ResizeVector<FieldType>(
415  this->DataValues, numTotalAttachments, static_cast<FieldType>(0));
416  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
417  this->SupernodeIds, numTotalAttachments, static_cast<vtkm::Id>(0));
418  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
419  this->Superparents, numTotalAttachments, static_cast<vtkm::Id>(0));
420  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
421  this->SuperparentRounds, numTotalAttachments, static_cast<vtkm::Id>(0));
422  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
423  this->WhichRounds, numTotalAttachments, static_cast<vtkm::Id>(0));
424 
425  /*this->GlobalRegularIds.Allocate(numTotalAttachments);
426  this->DataValues.Allocate(numTotalAttachments);
427  this->SupernodeIds.Allocate(numTotalAttachments);
428  this->Superparents.Allocate(numTotalAttachments);
429  this->SuperparentRounds.Allocate(numTotalAttachments);
430  this->WhichRounds.Allocate(numTotalAttachments);*/
431 
432  // II. copy the additional points into them
433  {
434  // The following sequence of copy operations implements the following for from the orginal code
435  // for (vtkm::Id inAttachmentPoint = 0; inAttachmentPoint < inGlobalRegularIDs.size(); inAttachmentPoint++)
436  // globalRegularIDs[attachmentPoint] = inGlobalRegularIDs[outAttachmentPoint];
437  auto tempGlobalRegularIdsView = vtkm::cont::make_ArrayHandleView(
438  this->GlobalRegularIds, numAttachmentsCurrently, numIncomingAttachments);
439  vtkm::cont::Algorithm::Copy(InData.GlobalRegularIds, tempGlobalRegularIdsView);
440  // dataValues[attachmentPoint] = inDataValues[outAttachmentPoint];
441  auto tempDataValuesView = vtkm::cont::make_ArrayHandleView(
442  this->DataValues, numAttachmentsCurrently, numIncomingAttachments);
443  vtkm::cont::Algorithm::Copy(InData.DataValues, tempDataValuesView);
444  // supernodeIDs[attachmentPoint] = NO_SUCH_ELEMENT;
445  auto tempNoSuchElementArr = vtkm::cont::make_ArrayHandleConstant(
447  auto tempSupernodeIdsView = vtkm::cont::make_ArrayHandleView(
448  this->SupernodeIds, numAttachmentsCurrently, numIncomingAttachments);
449  vtkm::cont::Algorithm::Copy(tempNoSuchElementArr, tempSupernodeIdsView);
450  // superparents[attachmentPoint] = inSuperparents[outAttachmentPoint];
451  auto tempSuperparentsView = vtkm::cont::make_ArrayHandleView(
452  this->Superparents, numAttachmentsCurrently, numIncomingAttachments);
453  vtkm::cont::Algorithm::Copy(InData.Superparents, tempSuperparentsView);
454  // superparentRounds[attachmentPoint] = inSuperparentRounds[outAttachmentPoint];
455  auto tempSuperparentRoundsView = vtkm::cont::make_ArrayHandleView(
456  this->SuperparentRounds, numAttachmentsCurrently, numIncomingAttachments);
457  vtkm::cont::Algorithm::Copy(InData.SuperparentRounds, tempSuperparentRoundsView);
458  // whichRounds[attachmentPoint] = inWhichRounds[outAttachmentPoint];
459  auto tempWhichRoundsView = vtkm::cont::make_ArrayHandleView(
460  this->WhichRounds, numAttachmentsCurrently, numIncomingAttachments);
461  vtkm::cont::Algorithm::Copy(InData.WhichRounds, tempWhichRoundsView);
462  }
463 } // RetrieveInAttachmentPoints()
464 
465 
466 // routine to release memory used for out arrays
467 template <typename FieldType>
469 { // ReleaseSwapArrays()
470  this->OutData.ReleaseResources();
471  this->InData.ReleaseResources();
472 } // ReleaseSwapArrays()
473 
474 
475 // routine to reconstruct a hierarchical tree using the augmenting supernodes
476 template <typename FieldType>
478 { // BuildAugmentedTree()
479  // 1. Prepare the data structures for filling in, copying in basic information & organising the attachment points
480  this->PrepareAugmentedTree();
481  // 2. Copy the hyperstructure, using the old super IDs for now
482  this->CopyHyperstructure();
483  // 3. Copy the superstructure, inserting additional points as we do
484  this->CopySuperstructure();
485  // 4. Update the hyperstructure to use the new super IDs
486  this->UpdateHyperstructure();
487  // 5. Copy the remaining regular structure at the bottom level, setting up the regular sort order in the process
488  this->CopyBaseRegularStructure();
489 } // BuildAugmentedTree()
490 
491 
492 // initial preparation
493 template <typename FieldType>
495 { // PrepareAugmentedTree()
496  // 1. Sort attachment points on superparent round, with secondary sort on global index so duplicates appear next to each other
497  // This can (and does) happen when a vertex on the boundary is an attachment point separately for multiple blocks
498  // We add a tertiary sort on supernode ID so that on each block, it gets the correct "home" supernode ID for reconciliation
499  //: note that we use a standard comparator that tie breaks with index. This separates into
500  // segments with identical superparent round, which is all we need for now
502  vtkm::cont::ArrayHandleIndex(this->GlobalRegularIds.GetNumberOfValues()), this->AttachmentIds);
503  // 1a. We now need to suppress duplicates,
504  {
505  // Sort the attachement Ids
506  vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
507  AttachmentSuperparentAndIndexComparator attachmentSuperparentAndIndexComparator(
508  this->SuperparentRounds, this->GlobalRegularIds, this->SupernodeIds);
509  vtkm::cont::Algorithm::Sort(this->AttachmentIds, attachmentSuperparentAndIndexComparator);
510  // Remove the duplicate values using GlobalRegularIds[AttachmentIds] for checking for equality
512  attachmentIdsEqualComparator(this->GlobalRegularIds);
513  vtkm::cont::Algorithm::Unique(this->AttachmentIds, attachmentIdsEqualComparator);
514  }
515 
516  // 2. Set up array with bounds for subsegments
517  // We do +2 because the top level is extra, and we need an extra sentinel value at the end
518  // We initialise to NO_SUCH_ELEMENT because we may have rounds with none and we'll need to clean up serially (over the number of rounds, i.e. lg n)
521  this->BaseTree->NumRounds + 2),
522  this->FirstAttachmentPointInRound);
523 
524  // Now do a parallel set operation
525  {
526  vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
527  SetFirstAttachmentPointInRoundWorklet setFirstAttachmentPointInRoundWorklet;
528  this->Invoke(setFirstAttachmentPointInRoundWorklet,
529  this->AttachmentIds, // input
530  this->SuperparentRounds, // input
531  this->FirstAttachmentPointInRound);
532  }
533  // The last element in the array is always set to the size as a sentinel value
534  // We need to pull the firstAttachmentPointInRound array to the control environment
535  // anyways for the loop afterwards so can do this set here without using Copy
536  // Use regular WritePortal here since we need to update a number of values and the array should be small
537  auto firstAttachmentPointInRoundPortal = this->FirstAttachmentPointInRound.WritePortal();
538  firstAttachmentPointInRoundPortal.Set(this->BaseTree->NumRounds + 1,
539  this->AttachmentIds.GetNumberOfValues());
540 
541 #ifdef DEBUG_PRINT
543  this->DebugPrint("First Attachment Point Set Where Possible", __FILE__, __LINE__));
544 #endif
545  // Now clean up by looping through the rounds (serially - this is logarithmic at worst)
546  // We loop backwards so that the next up propagates downwards
547  // WARNING: DO NOT PARALLELISE THIS LOOP
548  for (vtkm::Id roundNumber = this->BaseTree->NumRounds; roundNumber >= 0; roundNumber--)
549  { // per round
550  // if it still holds NSE, there are none in this round, so use the next one up
552  firstAttachmentPointInRoundPortal.Get(roundNumber)))
553  {
554  firstAttachmentPointInRoundPortal.Set(roundNumber,
555  firstAttachmentPointInRoundPortal.Get(roundNumber + 1));
556  }
557  } // per round
558 
559 #ifdef DEBUG_PRINT
560  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Subsegments Identified", __FILE__, __LINE__));
561 #endif
562  // 3. Initialise an array to keep track of the mapping from old supernode ID to new supernode ID
565  this->BaseTree->Supernodes.GetNumberOfValues()),
566  this->NewSupernodeIds);
567 
568 #ifdef DEBUG_PRINT
570  this->DebugPrint("Augmented Tree Prepared", __FILE__, __LINE__));
571 
572 #endif
573 } // PrepareAugmentedTree()
574 
575 
576 // transfer of hyperstructure but not superchildren count
577 template <typename FieldType>
579 { // CopyHyperstructure()
580  // we can also resize some of the additional information
581  this->AugmentedTree->NumRounds = this->BaseTree->NumRounds;
584  static_cast<vtkm::Id>(0), this->BaseTree->NumRegularNodesInRound.GetNumberOfValues()),
585  this->AugmentedTree->NumRegularNodesInRound);
588  static_cast<vtkm::Id>(0), this->BaseTree->NumSupernodesInRound.GetNumberOfValues()),
589  this->AugmentedTree->NumSupernodesInRound);
590 
591  // this chunk needs to be here to prevent the HierarchicalContourTree::DebugPrint() routine from crashing
592  this->AugmentedTree->FirstSupernodePerIteration.resize(
593  this->BaseTree->FirstSupernodePerIteration.size());
594  // this loop doesn't need to be parallelised, as it is a small size: we will fill in values later
595  for (vtkm::Id roundNumber = 0;
596  roundNumber < static_cast<vtkm::Id>(this->AugmentedTree->FirstSupernodePerIteration.size());
597  roundNumber++)
598  {
601  static_cast<vtkm::Id>(0),
602  this->BaseTree->FirstSupernodePerIteration[roundNumber].GetNumberOfValues()),
603  this->AugmentedTree->FirstSupernodePerIteration[roundNumber]);
604  }
605 
606  // hyperstructure is unchanged, so we can copy it
607  vtkm::cont::Algorithm::Copy(this->BaseTree->NumHypernodesInRound,
608  this->AugmentedTree->NumHypernodesInRound);
609  vtkm::cont::Algorithm::Copy(this->BaseTree->NumIterations, this->AugmentedTree->NumIterations);
610  this->AugmentedTree->FirstHypernodePerIteration.resize(
611  this->BaseTree->FirstHypernodePerIteration.size());
612  // this loop doesn't need to be parallelised, as it is a small size
613  for (vtkm::Id roundNumber = 0;
614  roundNumber < static_cast<vtkm::Id>(this->AugmentedTree->FirstHypernodePerIteration.size());
615  roundNumber++)
616  { // per round
617  // duplicate the existing array
618  vtkm::cont::Algorithm::Copy(this->BaseTree->FirstHypernodePerIteration[roundNumber],
619  this->AugmentedTree->FirstHypernodePerIteration[roundNumber]);
620  } // per round
621 
622 #ifdef DEBUG_PRINT
623  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Hyperstructure Copied", __FILE__, __LINE__));
624 #endif
625 } // CopyHyperstructure()
626 
627 
628 // transfer level of superstructure with insertions
629 template <typename FieldType>
631 { // CopySuperstructure()
632 
633  // Loop from the top down:
634  for (vtkm::Id roundNumber = this->BaseTree->NumRounds; roundNumber >= 0; roundNumber--)
635  { // per round
636  // start by retrieving list of old supernodes from the tree (except for attachment points)
637  this->RetrieveOldSupernodes(roundNumber);
638  // since we know the number of attachment points, we can now allocate space for the level
639  // and set up arrays for sorting the supernodes
640  this->ResizeArrays(roundNumber);
641  // now we create the superarcs for the round in the new tree
642  this->CreateSuperarcs(roundNumber);
643  } // per round
644 #ifdef DEBUG_PRINT
646  this->DebugPrint("Superstructure Copied", __FILE__, __LINE__));
647 #endif
648 } // CopySuperstructure()
649 
650 
651 // reset the super IDs in the hyperstructure to the new values
652 template <typename FieldType>
654 { // UpdateHyperstructure()
655 
656  // 5. Reset hypernodes, hyperarcs and superchildren using supernode IDs
657  // The hyperstructure is unchanged, but uses old supernode IDs
658  {
659  vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
660  UpdateHyperstructureSetHyperarcsAndNodesWorklet
661  updateHyperstructureSetHyperarcsAndNodesWorklet;
662  this->Invoke(
663  updateHyperstructureSetHyperarcsAndNodesWorklet,
664  this->BaseTree->Hypernodes, // input
665  this->BaseTree->Hyperarcs, // input
666  this->NewSupernodeIds, // input
667  this->AugmentedTree->Hypernodes, // output (the array is automatically resized here)
668  this->AugmentedTree->Hyperarcs // output (the array is automatically resized here)
669  );
670  }
671 
672  // finally, find the number of superchildren as the delta between the
673  // super ID and the next hypernode's super ID
674  {
675  vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
676  UpdateHyperstructureSetSuperchildrenWorklet updateHyperstructureSetSuperchildrenWorklet(
677  this->AugmentedTree->Supernodes.GetNumberOfValues());
678  this->Invoke(
679  updateHyperstructureSetSuperchildrenWorklet,
680  this->AugmentedTree->Hypernodes, // input
681  this->AugmentedTree->Superchildren // output (the array is automatically resized here)
682  );
683  }
684 } // UpdateHyperstructure()
685 
686 
687 // copy the remaining base level regular nodes
688 template <typename FieldType>
690 { // CopyBaseRegularStructure()
691  // 6. Set up the regular node sorter for the final phase
693  vtkm::cont::ArrayHandleIndex(this->AugmentedTree->RegularNodeGlobalIds.GetNumberOfValues()),
694  this->AugmentedTree->RegularNodeSortOrder);
695  {
696  vtkm::worklet::contourtree_distributed::PermuteComparator // hierarchical_contour_tree::
697  permuteComparator(this->AugmentedTree->RegularNodeGlobalIds);
698  vtkm::cont::Algorithm::Sort(this->AugmentedTree->RegularNodeSortOrder, permuteComparator);
699  }
700 
701 #ifdef DEBUG_PRINT
703  DebugPrint("Regular Node Sorter Sorted", __FILE__, __LINE__));
704 #endif
705 
706  // 7. Cleanup at level = 0. The principal task here is to insert all of the regular
707  // nodes in the original block into the regular arrays. The problem is that we
708  // haven't got a canonical list of them since in the original hierarchical tree,
709  // they might have been passed upwards as part of the boundary resolution. We
710  // now have a choice: we can take all "unfiled" regular nodes in the original hierarchical
711  // tree, or we can return to the block of data. The difference here is that the
712  // "unfiled" regular nodes can include nodes from other blocks which were passed up
713  // and retained in both partners. On the other hand, we already have the list of
714  // unfiled regular nodes, so the overhead for using them is not huge. And if we
715  // return to the block, we will need to pass it in as a parameter and template
716  // on mesh type. So, for the purposes of tidy coding, I shall use the first
717  // option, which means that not all of the Level 0 regular nodes belong to the block.
718  {
719  // For each regular node, if it hasn't been transferred to the new tree, search for the superarc to which it belongs
720  // default the superparent to NO_SUCH_ELEMENT to use as a flag for "we can ignore it"
721  // now loop, finding the superparent for each node needed and set the approbriate value or set to
722  // NO_SUCH_ELEMENT if not needed. The worklet also automatically sized our arrays
723  // temporary array so we can stream compact (aka CopyIf) afterwards
725  // create the worklet
726  vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
727  FindSuperparentForNecessaryNodesWorklet findSuperparentForNecessaryNodesWorklet;
728  // Get a FindRegularByGlobal and FindSuperArcForUnknownNode execution object for our worklet
729  auto findRegularByGlobal = this->AugmentedTree->GetFindRegularByGlobal();
730  auto findSuperArcForUnknownNode = this->AugmentedTree->GetFindSuperArcForUnknownNode();
731 
732  // excute the worklet
733  this->Invoke(findSuperparentForNecessaryNodesWorklet, // the worklet to call
734  // inputs
735  this->BaseTree->RegularNodeGlobalIds, // input domain
736  this->BaseTree->Superparents, // input
737  this->BaseTree->DataValues, // input
738  this->BaseTree->Superarcs, // input
739  this->NewSupernodeIds, // input
740  // Execution objects from the AugmentedTree
741  findRegularByGlobal,
742  findSuperArcForUnknownNode,
743  // Output arrays to populate
744  this->RegularSuperparents, // output
745  tempRegularNodesNeeded // output. will be CopyIf'd to this->RegularNodesNeeded
746  );
747  // We now compress to get the set of nodes to transfer. I.e., remove all
748  // NO_SUCH_ELEMENT entires and copy the values to keep to our proper arrays
751  tempRegularNodesNeeded, // input data
752  tempRegularNodesNeeded, // stencil (same as input)
753  this->RegularNodesNeeded, // target array (will be resized)
754  notNoSuchElementPredicate // predicate returning true of element is NOT NO_SUCH_ELEMENT
755  );
756  }
757 
758  // resize the regular arrays to fit
759  vtkm::Id numRegNeeded = this->RegularNodesNeeded.GetNumberOfValues();
760  vtkm::Id numExistingRegular = this->AugmentedTree->RegularNodeGlobalIds.GetNumberOfValues();
761  vtkm::Id numTotalRegular = numExistingRegular + numRegNeeded;
762  {
763  // Resize the array, while preserving the orginial values and initalizing new values
764  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
765  this->AugmentedTree->RegularNodeGlobalIds, numTotalRegular, static_cast<vtkm::Id>(0));
766  vtkm::worklet::contourtree_augmented::ResizeVector<FieldType>(
767  this->AugmentedTree->DataValues, numTotalRegular, static_cast<FieldType>(0));
768  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
769  this->AugmentedTree->RegularNodeSortOrder, numTotalRegular, static_cast<vtkm::Id>(0));
770  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
771  this->AugmentedTree->Regular2Supernode,
772  numTotalRegular,
774  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
775  this->AugmentedTree->Superparents, numTotalRegular, static_cast<vtkm::Id>(0));
776  }
777 
778  // OK: we have a complete list of the nodes to transfer. Since we make no guarantees (yet) about sorting, they just copy across
779  {
781  copyBaseRegularStructureWorklet(numExistingRegular);
782  // NOTE: We require the input arrays (aside form the input domain) to be permutted by the
783  // regularNodesNeeded input domain so that we can use FieldIn instead of WholeArrayIn
784  // NOTE: We require ArrayHandleView for the output arrays of the range [numExistingRegular:end] so
785  // that we can use FieldOut instead of requiring WholeArrayInOut
786  // input domain for the worklet of [0, regularNodesNeeded.GetNumberOfValues()]
787  auto regularNodesNeededRange =
788  vtkm::cont::ArrayHandleIndex(this->RegularNodesNeeded.GetNumberOfValues());
789  // input baseTree->regularNodeGlobalIds permuted by regularNodesNeeded
790  auto baseTreeRegularNodeGlobalIdsPermuted = vtkm::cont::make_ArrayHandlePermutation(
791  this->RegularNodesNeeded, this->BaseTree->RegularNodeGlobalIds);
792  // input baseTree->dataValues permuted by regularNodesNeeded
793  auto baseTreeDataValuesPermuted =
794  vtkm::cont::make_ArrayHandlePermutation(this->RegularNodesNeeded, this->BaseTree->DataValues);
795  // input regularSuperparents permuted by regularNodesNeeded
796  auto regularSuperparentsPermuted =
797  vtkm::cont::make_ArrayHandlePermutation(this->RegularNodesNeeded, this->RegularSuperparents);
798  // input view of augmentedTree->regularNodeGlobalIds[numExistingRegular:]
799  auto augmentedTreeRegularNodeGlobalIdsView =
800  vtkm::cont::make_ArrayHandleView(this->AugmentedTree->RegularNodeGlobalIds,
801  numExistingRegular, // start writing at numExistingRegular
802  numRegNeeded); // fill until the end
803  // input view of augmentedTree->dataValues[numExistingRegular:]
804  auto augmentedTreeDataValuesView =
805  vtkm::cont::make_ArrayHandleView(this->AugmentedTree->DataValues,
806  numExistingRegular, // start writing at numExistingRegular
807  numRegNeeded); // fill until the end
808  // input view of augmentedTree->superparents[numExistingRegular:]
809  auto augmentedTreeSuperparentsView =
810  vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Superparents,
811  numExistingRegular, // start writing at numExistingRegular
812  numRegNeeded); // fill until the end
813  // input view of augmentedTree->regularNodeSortOrder[numExistingRegular:]
814  auto augmentedTreeRegularNodeSortOrderView =
815  vtkm::cont::make_ArrayHandleView(this->AugmentedTree->RegularNodeSortOrder,
816  numExistingRegular, // start writing at numExistingRegular
817  numRegNeeded); // fill until the end
818  this->Invoke(copyBaseRegularStructureWorklet, // worklet to call
819  regularNodesNeededRange, // input domain
820  baseTreeRegularNodeGlobalIdsPermuted, // input
821  baseTreeDataValuesPermuted, // input
822  regularSuperparentsPermuted, // input
823  augmentedTreeRegularNodeGlobalIdsView, // output
824  augmentedTreeDataValuesView, // output
825  augmentedTreeSuperparentsView, // output
826  augmentedTreeRegularNodeSortOrderView // output
827  );
828  }
829 
830  // Finally, we resort the regular node sort order
831  {
832  vtkm::worklet::contourtree_distributed::PermuteComparator // hierarchical_contour_tree::
833  permuteComparator(this->AugmentedTree->RegularNodeGlobalIds);
834  vtkm::cont::Algorithm::Sort(this->AugmentedTree->RegularNodeSortOrder, permuteComparator);
835  }
836 } // CopyBaseRegularStructure()
837 
838 
839 // subroutines for CopySuperstructure
840 // gets a list of all the old supernodes to transfer at this level (ie except attachment points
841 template <typename FieldType>
843 { // RetrieveOldSupernodes()
844  // a. Transfer supernodes from same level of old tree minus attachment points, storing by global regular ID not regular ID
845  // Use compression to get the set of supernode IDs that we want to keep
846  // TODO PERFORMANCE STATISTICS:
847  // the # of supernodes at each level minus the # of kept supernodes gives us the # of attachment points we lose at this level
848  // in addition to this, the firstAttachmentPointInRound array gives us the # of attachment points we gain at this level
849  vtkm::Id supernodeIndexBase =
850  vtkm::cont::ArrayGetValue(0, this->BaseTree->FirstSupernodePerIteration[roundNumber]);
852  supernodeIndexBase, // start
853  1, // step
854  this->BaseTree->NumSupernodesInRound.ReadPortal().Get(roundNumber));
855  // the test for whether to keep it is:
856  // a1. at the top level, keep everything
857  if (!(roundNumber < this->BaseTree->NumRounds))
858  {
859  vtkm::cont::Algorithm::Copy(supernodeIdVals, this->KeptSupernodes);
860  }
861  // a2. at lower levels, keep them if the superarc is NO_SUCH_ELEMENT
862  else
863  {
864  // Reset this-KeptSupernodes to the right size and initalize with NO_SUCH_ELEMENT.
865  // TODO: Check if a simple free and allocate without initalizing the array is sufficient
867  // Create const array to copy
870  this->BaseTree->NumSupernodesInRound.ReadPortal().Get(roundNumber)),
871  // target array
872  this->KeptSupernodes);
873  // Create the predicate for the CopyIf
875  // Copy supernodeId to this->KeptSupernodes
877  // first we generate a list of supernodeIds
878  supernodeIdVals,
879  // Stencil with baseTree->superarcs[supernodeID]
881  this->BaseTree->Superarcs, supernodeIndexBase, this->KeptSupernodes.GetNumberOfValues()),
882  // And the CopyIf compresses the array to eliminate unnecssary elements
883  // save to this->KeptSupernodes
884  this->KeptSupernodes,
885  // then our predicate identifies all necessary points. These
886  // are all points that suffice the condition
887  // vtkm::Id supernodeID = keptSupernode + supernodeIndexBase;
888  // !noSuchElement(baseTree->superarcs[supernodeID]);
889  notNoSuchElementPredicate);
890  }
891 
892 #ifdef DEBUG_PRINT
894  DebugPrint(std::string("Round ") + std::to_string(roundNumber) +
895  std::string(" Old Supernodes Retrieved"),
896  __FILE__,
897  __LINE__));
898 #endif
899 } // RetrieveOldSupernodes()
900 
901 
902 // resizes the arrays for the level
903 template <typename FieldType>
905 { // ResizeArrays()
906  // at this point, we know how many supernodes are kept from the same level of the old tree
907  // we can also find out how many supernodes are being inserted, which gives us the correct amount to expand by, saving a double resize() call
908  // note that some of these arrays could probably be resized later, but it's cleaner this way
909  // also note that if it becomes a problem, we could resize all of the arrays to baseTree->supernodes.size() + # of attachmentPoints as an over-estimate
910  // then cut them down at the end. The code would however be even messier if we did so
911  vtkm::Id numSupernodesAlready = this->AugmentedTree->Supernodes.GetNumberOfValues();
912  vtkm::Id numInsertedSupernodes =
913  vtkm::cont::ArrayGetValue(roundNumber + 1, this->FirstAttachmentPointInRound) -
914  vtkm::cont::ArrayGetValue(roundNumber, this->FirstAttachmentPointInRound);
915  vtkm::Id numSupernodesThisLevel =
916  numInsertedSupernodes + this->KeptSupernodes.GetNumberOfValues();
917  vtkm::Id newSupernodeCount = numSupernodesAlready + numSupernodesThisLevel;
918 
919  // conveniently, the value numSupernodesThisLevel is the number of supernodes *!AND!* regular nodes to store for the round
921  roundNumber, numSupernodesThisLevel, this->AugmentedTree->NumRegularNodesInRound);
923  roundNumber, numSupernodesThisLevel, this->AugmentedTree->NumSupernodesInRound);
925  0, numSupernodesAlready, this->AugmentedTree->FirstSupernodePerIteration[roundNumber]);
926 
927  // resize the arrays accordingly.
928  // NOTE: We have to resize arrays (not just allocate them) as we need to
929  // expand the arrays while preserving the original values
930  {
932  this->AugmentedTree->Supernodes,
933  newSupernodeCount,
936  this->AugmentedTree->Supernodes,
937  newSupernodeCount,
940  this->AugmentedTree->Superarcs,
941  newSupernodeCount,
944  this->AugmentedTree->Hyperparents,
945  newSupernodeCount,
948  this->AugmentedTree->Super2Hypernode,
949  newSupernodeCount,
952  this->AugmentedTree->WhichRound,
953  newSupernodeCount,
956  this->AugmentedTree->WhichIteration,
957  newSupernodeCount,
959 
960  // we also know that only supernodes are needed as regular nodes at each level, so we resize those here as well
961  // we note that it might be possible to update all regular IDs at the end, but leave that optimisation out for now
962  // therefore we resize the regular-sized arrays as well
964  this->AugmentedTree->RegularNodeGlobalIds,
965  newSupernodeCount,
967  vtkm::worklet::contourtree_augmented::ResizeVector<FieldType>(
968  this->AugmentedTree->DataValues, newSupernodeCount, static_cast<FieldType>(0));
970  this->AugmentedTree->Regular2Supernode,
971  newSupernodeCount,
974  this->AugmentedTree->Superparents,
975  newSupernodeCount,
977  }
978 
979 #ifdef DEBUG_PRINT
980  VTKM_LOG_S(
982  DebugPrint(std::string("Round ") + std::to_string(roundNumber) + std::string(" Arrays Resized"),
983  __FILE__,
984  __LINE__));
985 #endif
986 
987  // The next task is to assemble a sorting array which we will use to construct the new superarcs, containing both the
988  // kept supernodes and the attachment points. The attachment points are easier since we already have them, so we start
989  // by allocating space and copying them in: this means another set of arrays for the individual elements. However, we do not
990  // need all of the data elements, since superparentRound is fixed (and equal to roundNumber inside this loop), and whichRound will be reset
992  this->SupernodeSorter);
993  {
994  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
995  this->GlobalRegularIdSet, numSupernodesThisLevel, static_cast<vtkm::Id>(0));
996  vtkm::worklet::contourtree_augmented::ResizeVector<FieldType>(
997  this->DataValueSet, numSupernodesThisLevel, static_cast<FieldType>(0));
998  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
999  this->SuperparentSet, numSupernodesThisLevel, static_cast<vtkm::Id>(0));
1000  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1001  this->SupernodeIdSet, numSupernodesThisLevel, static_cast<vtkm::Id>(0));
1002  }
1003 #ifdef DEBUG_PRINT
1005  DebugPrint(std::string("Round ") + std::to_string(roundNumber) +
1006  std::string(" Sorter Set Resized"),
1007  __FILE__,
1008  __LINE__));
1009 #endif
1010 
1011  // b. Transfer attachment points for level into new supernode array
1012  // to copy them in, we use the existing array of attachment point IDs by round
1013  {
1014  vtkm::Id firstAttachmentPointInRoundCurrent =
1015  vtkm::cont::ArrayGetValue(roundNumber, this->FirstAttachmentPointInRound);
1016  vtkm::Id firstAttachmentPointInRoundNext =
1017  vtkm::cont::ArrayGetValue(roundNumber + 1, this->FirstAttachmentPointInRound);
1018  vtkm::Id currRange = firstAttachmentPointInRoundNext - firstAttachmentPointInRoundCurrent;
1019  auto attachmentPointIdView =
1020  vtkm::cont::make_ArrayHandleView(this->AttachmentIds, // array to subset
1021  firstAttachmentPointInRoundCurrent, // start index
1022  currRange); // count
1023  // Permute the source arrays for the copy
1024  auto globalRegularIdsPermuted =
1025  vtkm::cont::make_ArrayHandlePermutation(attachmentPointIdView, // index array
1026  this->GlobalRegularIds // value array
1027  );
1028  auto dataValuesPermuted =
1029  vtkm::cont::make_ArrayHandlePermutation(attachmentPointIdView, this->DataValues);
1030  auto superparentsPermuted =
1031  vtkm::cont::make_ArrayHandlePermutation(attachmentPointIdView, this->Superparents);
1032  auto supernodeIdsPermuted =
1033  vtkm::cont::make_ArrayHandlePermutation(attachmentPointIdView, this->SupernodeIds);
1034  // Now use CopySubRange to copy the values into the right places. This allows
1035  // us to place them in the right place and avoid shrinking the array on Copy
1037  // copy all values of our permutted array
1038  globalRegularIdsPermuted,
1039  0,
1040  globalRegularIdsPermuted.GetNumberOfValues(),
1041  // copy target
1042  this->GlobalRegularIdSet,
1043  0);
1045  dataValuesPermuted, 0, dataValuesPermuted.GetNumberOfValues(), this->DataValueSet, 0);
1047  superparentsPermuted, 0, superparentsPermuted.GetNumberOfValues(), this->SuperparentSet, 0);
1049  supernodeIdsPermuted, 0, supernodeIdsPermuted.GetNumberOfValues(), this->SupernodeIdSet, 0);
1050  }
1051 
1052 #ifdef DEBUG_PRINT
1054  DebugPrint(std::string("Round ") + std::to_string(roundNumber) +
1055  std::string(" Attachment Points Transferred"),
1056  __FILE__,
1057  __LINE__));
1058 #endif
1059 
1060  // Now we copy in the kept supernodes
1061  {
1062  auto oldRegularIdArr =
1063  vtkm::cont::make_ArrayHandlePermutation(this->KeptSupernodes, // index
1064  this->BaseTree->Supernodes); // values
1065  // Permute the source arrays for the copy
1066  auto baseTreeregularNodeGlobalIdsPermuted = vtkm::cont::make_ArrayHandlePermutation(
1067  oldRegularIdArr, this->BaseTree->RegularNodeGlobalIds);
1068  auto baseTreeDataValuesPermuted =
1069  vtkm::cont::make_ArrayHandlePermutation(oldRegularIdArr, this->BaseTree->DataValues);
1070 
1071  // Now use CopySubRange to copy the values into the right places. This allows
1072  // us to place them in the right place and avoids shrinking the array on Copy
1073  vtkm::cont::Algorithm::CopySubRange(baseTreeregularNodeGlobalIdsPermuted,
1074  0,
1075  baseTreeregularNodeGlobalIdsPermuted.GetNumberOfValues(),
1076  this->GlobalRegularIdSet,
1077  numInsertedSupernodes);
1078  vtkm::cont::Algorithm::CopySubRange(baseTreeDataValuesPermuted,
1079  0,
1080  baseTreeDataValuesPermuted.GetNumberOfValues(),
1081  this->DataValueSet,
1082  numInsertedSupernodes);
1083  vtkm::cont::Algorithm::CopySubRange(this->KeptSupernodes,
1084  0,
1085  this->KeptSupernodes.GetNumberOfValues(),
1086  this->SupernodeIdSet,
1087  numInsertedSupernodes);
1088  // For this->SuperparentSet we need to set values to
1089  // superparentSet[supernodeSetID] = oldSupernodeID | (isAscending(baseTree->superarcs[oldSupernodeID]) ? IS_ASCENDING: 0x00);
1090  // so we use an ArrayHanldeDecorator instead to compute the values and copy them in place
1091  auto setSuperparentSetArrayDecorator = vtkm::cont::make_ArrayHandleDecorator(
1092  this->KeptSupernodes.GetNumberOfValues(),
1094  this->KeptSupernodes,
1095  this->BaseTree->Superarcs);
1096  vtkm::cont::Algorithm::CopySubRange(setSuperparentSetArrayDecorator,
1097  0,
1098  this->KeptSupernodes.GetNumberOfValues(),
1099  this->SuperparentSet,
1100  numInsertedSupernodes);
1101  }
1102 
1103 #ifdef DEBUG_PRINT
1105  DebugPrint(std::string("Round ") + std::to_string(roundNumber) +
1106  std::string(" Kept Supernodes Transferred"),
1107  __FILE__,
1108  __LINE__));
1109 #endif
1110 
1111  // c. Create a permutation array and sort supernode segment by a. superparent, b. value, d. global index to establish segments (reversing as needed)
1112  {
1113  vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
1114  AttachmentAndSupernodeComparator<FieldType>
1115  attachmentAndSupernodeComparator(
1116  this->SuperparentSet, this->DataValueSet, this->GlobalRegularIdSet);
1117  vtkm::cont::Algorithm::Sort(this->SupernodeSorter, attachmentAndSupernodeComparator);
1118  }
1119 
1120 #ifdef DEBUG_PRINT
1122  DebugPrint(std::string("Round ") + std::to_string(roundNumber) +
1123  std::string(" Sorter Set Sorted"),
1124  __FILE__,
1125  __LINE__));
1126 #endif
1127 
1128  // d. Build the inverse permutation array for lookup purposes:
1129  {
1130  vtkm::worklet::contourtree_distributed::hierarchical_augmenter::
1131  ResizeArraysBuildNewSupernodeIdsWorklet resizeArraysBuildNewSupernodeIdsWorklet(
1132  numSupernodesAlready);
1133  auto supernodeIndex = vtkm::cont::ArrayHandleIndex(this->SupernodeSorter.GetNumberOfValues());
1134  auto supernodeIdSetPermuted =
1135  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->SupernodeIdSet);
1136  this->Invoke(
1137  resizeArraysBuildNewSupernodeIdsWorklet,
1138  supernodeIndex, // input domain. We only need the index because supernodeIdSetPermuted already does the permute
1139  supernodeIdSetPermuted, // input input supernodeIDSet permuted by supernodeSorter to allow for FieldIn
1140  this
1141  ->NewSupernodeIds // output/input (both are necessary since not all values will be overwritten)
1142  );
1143  }
1144 
1145 #ifdef DEBUG_PRINT
1147  DebugPrint(std::string("Round ") + std::to_string(roundNumber) +
1148  std::string(" Sorting Arrays Built"),
1149  __FILE__,
1150  __LINE__));
1151 #endif
1152 } // ResizeArrays()
1153 
1154 
1155 // adds a round full of superarcs (and regular nodes) to the tree
1156 template <typename FieldType>
1158 { // CreateSuperarcs()
1159  // retrieve the ID number of the first supernode at this level
1160  vtkm::Id numSupernodesAlready =
1161  vtkm::cont::ArrayGetValue(0, this->AugmentedTree->FirstSupernodePerIteration[roundNumber]);
1162 
1163  // e. Connect superarcs for the level & set hyperparents & superchildren count, whichRound, whichIteration, super2hypernode
1164  { // START scope for e. to delete temporary variables
1165  // Note: The original PPP algorithm performed all operations listed in this block
1166  // in a single parralel for loop. Many of those operations were smart array
1167  // copies. So to simplfy the worklet and to make more effective use of
1168  // VTKm algorithm, a large number of copy operations have been extracted from
1169  // the loop and are performed here via combinations of fancy array handles and
1170  // vtkm::cont::Algorithm::Copy operations.
1171 
1172  // Define the new supernode and regular Id. Both are actually the same here since we are
1173  // augmenting the tree here, but for clarity we define them as separate variables.
1174  // At all levels above 0, we used to keep regular vertices in case
1175  // they are attachment points. After augmentation, we don't need to.
1176  // Instead, at all levels above 0, the regular nodes in each round
1177  // are identical to the supernodes. In order to avoid confusion,
1178  // we will copy the Id into a separate variable
1180  numSupernodesAlready, // start
1181  static_cast<vtkm::Id>(1), // step
1182  this->SupernodeSorter.GetNumberOfValues() // number of values
1183  );
1184  auto newRegularId = newSupernodeId;
1185  // define the superparentOldSuperId
1186  auto permutedSuperparentSet =
1187  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->SuperparentSet);
1188  auto superparentOldSuperId = vtkm::cont::make_ArrayHandleTransform(
1190 
1191  // set the supernode's regular Id. Set: augmentedTree->supernodes[newSupernodeID] = newRegularID;
1192  auto permutedAugmentedTreeSupernodes =
1193  vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->Supernodes);
1194  vtkm::cont::Algorithm::Copy(newRegularId, permutedAugmentedTreeSupernodes);
1195 
1196  // Run the worklet for more complex operations
1197  { // START block for CreateSuperarcsWorklet
1198  // create the worklet
1200  createSuperarcsWorklet(
1201  numSupernodesAlready,
1202  this->BaseTree->NumRounds,
1203  vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations),
1204  roundNumber,
1205  this->AugmentedTree->Supernodes.GetNumberOfValues());
1206  // create fancy arrays needed to allow use of FieldIn for worklet parameters
1207  auto permutedGlobalRegularIdSet =
1208  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->GlobalRegularIdSet);
1209  auto augmentedTreeSuperarcsView =
1210  vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Superarcs,
1211  numSupernodesAlready,
1212  this->SupernodeSorter.GetNumberOfValues());
1213  auto augmentedTreeSuper2HypernodeView =
1214  vtkm::cont::make_ArrayHandleView(this->AugmentedTree->Super2Hypernode,
1215  numSupernodesAlready,
1216  this->SupernodeSorter.GetNumberOfValues());
1217  // invoke the worklet
1218  this->Invoke(createSuperarcsWorklet, // the worklet
1219  this->SupernodeSorter, // input domain
1220  this->SuperparentSet, // input
1221  this->BaseTree->Superarcs, // input
1222  this->NewSupernodeIds, // input
1223  this->BaseTree->Supernodes, // input
1224  this->BaseTree->RegularNodeGlobalIds, // input
1225  permutedGlobalRegularIdSet, // input
1226  this->BaseTree->Super2Hypernode, // input
1227  this->BaseTree->WhichIteration, // input
1228  augmentedTreeSuperarcsView, // output
1229  this->AugmentedTree->FirstSupernodePerIteration[roundNumber], // input/output
1230  augmentedTreeSuper2HypernodeView // output
1231  );
1232  } // END block for CreateSuperarcsWorklet
1233 
1234  // setting the hyperparent is straightforward since the hyperstructure is preserved
1235  // we take the superparent (which is guaranteed to be in the baseTree), find it's hyperparent and use that
1236  // Set: augmentedTree->hyperparents[newSupernodeID] = baseTree->hyperparents[superparentOldSuperID];
1237  auto permutedAugmentedTreeHyperparents =
1238  vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->Hyperparents);
1239  auto permutedBaseTreeHyperparents =
1240  vtkm::cont::make_ArrayHandlePermutation(superparentOldSuperId, this->BaseTree->Hyperparents);
1241  vtkm::cont::Algorithm::Copy(permutedBaseTreeHyperparents, permutedAugmentedTreeHyperparents);
1242 
1243  // which round and iteration carry over
1244  // Set: augmentedTree->whichRound[newSupernodeID] = baseTree->whichRound[superparentOldSuperID];
1245  auto permutedAugmentedTreeWhichRound =
1246  vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->WhichRound);
1247  auto permutedBaseTreeWhichRound =
1248  vtkm::cont::make_ArrayHandlePermutation(superparentOldSuperId, this->BaseTree->WhichRound);
1249  vtkm::cont::Algorithm::Copy(permutedBaseTreeWhichRound, permutedAugmentedTreeWhichRound);
1250 
1251  // Set: augmentedTree->whichIteration[newSupernodeID] = baseTree->whichIteration[superparentOldSuperID];
1252  auto permutedAugmentedTreeWhichIteration =
1253  vtkm::cont::make_ArrayHandlePermutation(newSupernodeId, this->AugmentedTree->WhichIteration);
1254  auto permutedBaseTreeWhichIterationPortal = vtkm::cont::make_ArrayHandlePermutation(
1255  superparentOldSuperId, this->BaseTree->WhichIteration);
1256  vtkm::cont::Algorithm::Copy(permutedBaseTreeWhichIterationPortal,
1257  permutedAugmentedTreeWhichIteration);
1258 
1259  // now we deal with the regular-sized arrays. In the following supernodeSetIndex is simply supernodeSorterPortal.Get(supernode);
1260  // copy the global regular Id and data value
1261  // Set: augmentedTree->regularNodeGlobalIDs[newRegularID] = globalRegularIDSet[supernodeSetIndex];
1262  auto permutedAugmentedTreeRegularNodeGlobalIds = vtkm::cont::make_ArrayHandlePermutation(
1263  newRegularId, this->AugmentedTree->RegularNodeGlobalIds);
1264  auto permutedGlobalRegularIdSet =
1265  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->GlobalRegularIdSet);
1266  vtkm::cont::Algorithm::Copy(permutedGlobalRegularIdSet,
1267  permutedAugmentedTreeRegularNodeGlobalIds);
1268  // SetL augmentedTree->dataValues[newRegularID] = dataValueSet[supernodeSetIndex];
1269  auto permutedAugmentedTreeDataValues =
1270  vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->DataValues);
1271  auto permutedDataValueSet =
1272  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->DataValueSet);
1273  vtkm::cont::Algorithm::Copy(permutedDataValueSet, permutedAugmentedTreeDataValues);
1274 
1275  // the sort order will be dealt with later
1276  // since all of these nodes are supernodes, they will be their own superparent, which means that:
1277  // a. the regular2node can be set immediately
1278  // Set: augmentedTree->regular2supernode[newRegularID] = newSupernodeID;
1279  auto permutedAugmentedTreeRegular2Supernode =
1280  vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->Regular2Supernode);
1281  vtkm::cont::Algorithm::Copy(newSupernodeId, permutedAugmentedTreeRegular2Supernode);
1282 
1283  // b. as can the superparent
1284  // Set: augmentedTree->superparents[newRegularID] = newSupernodeID;
1285  auto permutedAugmentedTreeSuperparents =
1286  vtkm::cont::make_ArrayHandlePermutation(newRegularId, this->AugmentedTree->Superparents);
1287  vtkm::cont::Algorithm::Copy(newSupernodeId, permutedAugmentedTreeSuperparents);
1288  } // END scope for e. to delete temporary variables
1289 
1290  // We have one last bit of cleanup to do. If there were attachment points, then the round in which they transfer has been removed
1291  // While it is possible to turn this into a null round, it is better to reduce the iteration count by one and resize the arrays
1292  // To do this, we access the *LAST* element written and check to see whether it is in the final iteration (according to the base tree)
1293  // But there might be *NO* supernodes in the round, so we check first
1294  vtkm::Id iterationArraySize =
1295  vtkm::cont::ArrayGetValue(roundNumber, this->AugmentedTree->NumIterations);
1296  if (iterationArraySize > 0)
1297  { // at least one iteration
1298  vtkm::Id lastSupernodeThisLevel = this->AugmentedTree->Supernodes.GetNumberOfValues() - 1;
1300  vtkm::cont::ArrayGetValue(lastSupernodeThisLevel, this->AugmentedTree->WhichIteration));
1301  // if there were no attachment points, it will be in the last iteration: if there were attachment points, it will be in the previous one
1302  if (lastIterationThisLevel < iterationArraySize - 1)
1303  { // attachment point round was removed
1304  // decrement the iteration count (still with an extra element as sentinel)
1306  roundNumber, iterationArraySize - 1, this->AugmentedTree->NumIterations);
1307  // shrink the supernode array
1308  this->AugmentedTree->FirstSupernodePerIteration[roundNumber].Allocate(
1309  iterationArraySize, vtkm::CopyFlag::On); // shrink array but keep values
1311  iterationArraySize - 1,
1312  this->AugmentedTree->Supernodes.GetNumberOfValues(),
1313  this->AugmentedTree->FirstSupernodePerIteration[roundNumber]);
1314  // for the hypernode array, the last iteration is guaranteed not to have hyperarcs by construction
1315  // so the last iteration will already have the correct sentinel value, and we just need to shrink the array
1316  this->AugmentedTree->FirstHypernodePerIteration[roundNumber].Allocate(
1317  iterationArraySize, vtkm::CopyFlag::On); // shrink array but keep values
1318  } // attachment point round was removed
1319  } // at least one iteration
1320 
1321  // in the interests of debug, we resize the sorting array to zero here,
1322  // even though we will re-resize them in the next function
1323  this->SupernodeSorter.ReleaseResources();
1324  this->GlobalRegularIdSet.ReleaseResources();
1325  this->DataValueSet.ReleaseResources();
1326  this->SuperparentSet.ReleaseResources();
1327  this->SupernodeIdSet.ReleaseResources();
1328 } // CreateSuperarcs()
1329 
1330 
1331 // debug routine
1332 template <typename FieldType>
1333 std::string HierarchicalAugmenter<FieldType>::DebugPrint(std::string message,
1334  const char* fileName,
1335  long lineNum)
1336 { // DebugPrint()
1337  std::stringstream resultStream;
1338  resultStream << std::endl;
1339  resultStream << "----------------------------------------" << std::endl;
1340  resultStream << std::setw(30) << std::left << fileName << ":" << std::right << std::setw(4)
1341  << lineNum << std::endl;
1342  resultStream << "Block " << std::setw(4) << this->BlockId << ": " << std::left << message
1343  << std::endl;
1344  resultStream << "----------------------------------------" << std::endl;
1345 
1346  resultStream << this->BaseTree->DebugPrint(
1347  (message + std::string(" Base Tree")).c_str(), fileName, lineNum);
1348  resultStream << this->AugmentedTree->DebugPrint(
1349  (message + std::string(" Augmented Tree")).c_str(), fileName, lineNum);
1350  resultStream << "========================================" << std::endl;
1351  resultStream << "Local List of Attachment Points" << std::endl;
1352  vtkm::worklet::contourtree_augmented::PrintHeader(this->GlobalRegularIds.GetNumberOfValues());
1354  "Global Regular Ids", this->GlobalRegularIds, -1, resultStream);
1356  "Data Values", this->DataValues, -1, resultStream);
1358  "Supernode Ids", this->SupernodeIds, -1, resultStream);
1360  "Superparents", this->Superparents, -1, resultStream);
1362  "Superparent Rounds", this->SuperparentRounds, -1, resultStream);
1364  "WhichRounds", this->WhichRounds, -1, resultStream);
1365  resultStream << std::endl;
1366  resultStream << "Outgoing Attachment Points" << std::endl;
1368  this->OutData.GlobalRegularIds.GetNumberOfValues());
1370  "Out Global Regular Ids", this->OutData.GlobalRegularIds, -1, resultStream);
1372  "Out Data Values", this->OutData.DataValues, -1, resultStream);
1374  "Out Supernode Ids", this->OutData.SupernodeIds, -1, resultStream);
1376  "Out Superparents", this->OutData.Superparents, -1, resultStream);
1378  "Out Superparent Rounds", this->OutData.SuperparentRounds, -1, resultStream);
1380  "Out WhichRounds", this->OutData.WhichRounds, -1, resultStream);
1381  resultStream << std::endl;
1382  resultStream << "Incoming Attachment Points" << std::endl;
1384  this->InData.GlobalRegularIds.GetNumberOfValues());
1386  "In Global Regular Ids", this->InData.GlobalRegularIds, -1, resultStream);
1388  "In Data Values", this->InData.DataValues, -1, resultStream);
1390  "In Supernode Ids", this->InData.SupernodeIds, -1, resultStream);
1392  "In Superparents", this->InData.Superparents, -1, resultStream);
1394  "In Superparent Rounds", this->InData.SuperparentRounds, -1, resultStream);
1396  "In WhichRounds", this->InData.WhichRounds, -1, resultStream);
1397  resultStream << std::endl;
1398  resultStream << "Holding Arrays" << std::endl;
1400  this->FirstAttachmentPointInRound.GetNumberOfValues());
1402  "First Attach / Rd", this->FirstAttachmentPointInRound, -1, resultStream);
1403  vtkm::worklet::contourtree_augmented::PrintHeader(this->AttachmentIds.GetNumberOfValues());
1405  "AttachmentIds", this->AttachmentIds, -1, resultStream);
1406  vtkm::worklet::contourtree_augmented::PrintHeader(this->NewSupernodeIds.GetNumberOfValues());
1408  "New Supernode Ids", this->NewSupernodeIds, -1, resultStream);
1409  vtkm::worklet::contourtree_augmented::PrintHeader(this->KeptSupernodes.GetNumberOfValues());
1411  "Kept Supernodes", this->KeptSupernodes, -1, resultStream);
1412  vtkm::worklet::contourtree_augmented::PrintHeader(this->SupernodeSorter.GetNumberOfValues());
1414  "Supernode Sorter", this->SupernodeSorter, -1, resultStream);
1416  "Global Regular Id", this->GlobalRegularIdSet, -1, resultStream);
1418  "Data Values", this->DataValueSet, -1, resultStream);
1420  "Superparents", this->SuperparentSet, -1, resultStream);
1422  "SupernodeIds", this->SupernodeIdSet, -1, resultStream);
1423  resultStream << std::endl;
1424  resultStream << std::endl;
1425 
1426  vtkm::worklet::contourtree_augmented::PrintHeader(this->SupernodeSorter.GetNumberOfValues());
1428  "Supernode Id", this->SupernodeSorter, -1, resultStream);
1430  "Permuted Superparent",
1431  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->SuperparentSet),
1432  -1,
1433  resultStream);
1435  "Permuted Value",
1436  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->DataValueSet),
1437  -1,
1438  resultStream);
1440  "Permuted Global Id",
1441  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->GlobalRegularIdSet),
1442  -1,
1443  resultStream);
1445  "Permuted Supernode Id",
1446  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->SupernodeIdSet),
1447  -1,
1448  resultStream);
1449  resultStream << std::endl;
1450  resultStream << std::endl;
1451 
1452  vtkm::worklet::contourtree_augmented::PrintHeader(this->RegularSuperparents.GetNumberOfValues());
1454  "RegularNodesNeeded", this->RegularNodesNeeded, -1, resultStream);
1456  "RegularSuperparents", this->RegularSuperparents, -1, resultStream);
1457  resultStream << std::endl;
1458  // for now, nothing here at all
1459  //std::string hierarchicalTreeDotString = HierarchicalContourTreeDotGraphPrint(message,
1460  // this->BaseTree,
1461  // SHOW_SUPER_STRUCTURE|SHOW_HYPER_STRUCTURE|GV_NODE_NAME_USES_GLOBAL_ID|SHOW_ALL_IDS|SHOW_ALL_SUPERIDS|SHOW_ALL_HYPERIDS|SHOW_EXTRA_DATA,
1462  // this->BlockId,
1463  // this->SweepValues
1464  // );
1465  return resultStream.str();
1466 } // DebugPrint()
1467 
1468 
1469 // debug routine
1470 template <typename FieldType>
1472 { // DebugSave
1473  std::ofstream outstream(filename);
1474  outstream << "Augmented Tree:" << std::endl;
1476  vtkm::cont::Algorithm::Copy(vtkm::cont::make_ArrayHandleConstant<vtkm::Id>(
1477  0, this->AugmentedTree->Supernodes.GetNumberOfValues()),
1478  temp);
1479  std::string dumpVolumesString =
1481  this->AugmentedTree->Supernodes,
1482  this->AugmentedTree->Superarcs,
1483  this->AugmentedTree->RegularNodeGlobalIds,
1484  0,
1485  temp,
1486  temp);
1487  outstream << dumpVolumesString;
1489  "Global Regular IDs", this->GlobalRegularIds, -1, outstream);
1490  vtkm::worklet::contourtree_augmented::PrintValues("Data Values", this->DataValues, -1, outstream);
1492  "Supernode IDs", this->SupernodeIds, -1, outstream);
1494  "Superparents", this->Superparents, -1, outstream);
1496  "Superparent Rounds", this->SuperparentRounds, -1, outstream);
1498  "WhichRounds", this->WhichRounds, -1, outstream);
1500  "Out Global Regular IDs", this->OutData.GlobalRegularIds, -1, outstream);
1502  "Out Data Values", this->OutData.DataValues, -1, outstream);
1504  "Out Supernode IDs", this->OutData.SupernodeIds, -1, outstream);
1506  "Out Superparents", this->OutData.Superparents, -1, outstream);
1508  "Out Superparent Rounds", this->OutData.SuperparentRounds, -1, outstream);
1510  "Out WhichRounds", this->OutData.WhichRounds, -1, outstream);
1512  "In Global Regular IDs", this->InData.GlobalRegularIds, -1, outstream);
1514  "In Data Values", this->InData.DataValues, -1, outstream);
1516  "In Supernode IDs", this->InData.SupernodeIds, -1, outstream);
1518  "In Superparents", this->InData.Superparents, -1, outstream);
1520  "In Superparent Rounds", this->InData.SuperparentRounds, -1, outstream);
1522  "In WhichRounds", this->InData.WhichRounds, -1, outstream);
1524  "First Attach / Rd", this->FirstAttachmentPointInRound, -1, outstream);
1526  "AttachmentIDs", this->AttachmentIds, -1, outstream);
1528  "New Supernode IDs", this->NewSupernodeIds, -1, outstream);
1530  "Kept Supernodes", this->KeptSupernodes, -1, outstream);
1532  "Supernode Sorter", this->SupernodeSorter, -1, outstream);
1534  "Global Regular ID", this->GlobalRegularIdSet, -1, outstream);
1536  "Data Values", this->DataValueSet, -1, outstream);
1538  "Superparents", this->SuperparentSet, -1, outstream);
1540  "SupernodeIDs", this->SupernodeIdSet, -1, outstream);
1542  "Supernode ID", this->SupernodeSorter, -1, outstream);
1544  "Permuted Superparent",
1545  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->SuperparentSet),
1546  -1,
1547  outstream);
1549  "Permuted Value",
1550  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->DataValueSet),
1551  -1,
1552  outstream);
1554  "Permuted Global ID",
1555  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->GlobalRegularIdSet),
1556  -1,
1557  outstream);
1559  "Permuted Supernode ID",
1560  vtkm::cont::make_ArrayHandlePermutation(this->SupernodeSorter, this->SupernodeIdSet),
1561  -1,
1562  outstream);
1564  "RegularNodesNeeded", this->RegularNodesNeeded, -1, outstream);
1566  "RegularSuperparents", this->RegularSuperparents, -1, outstream);
1567 } // DebugSave
1568 
1569 
1570 
1571 } // namespace contourtree_distributed
1572 } // namespace worklet
1573 } // namespace vtkm
1574 
1575 
1576 #endif
UpdateHyperstructureSetHyperarcsAndNodesWorklet.h
vtkm::cont::ArrayHandle::GetNumberOfValues
VTKM_CONT vtkm::Id GetNumberOfValues() const
Returns the number of entries in the array.
Definition: ArrayHandle.h:448
vtkm::worklet::contourtree_distributed::HierarchicalContourTree
Hierarchical Contour Tree data structure.
Definition: HierarchicalContourTree.h:100
vtkm::cont::ArrayHandle< vtkm::Id >
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::WhichRounds
vtkm::worklet::contourtree_augmented::IdArrayType WhichRounds
we also want to track the round on which the attachment point was originally transferred
Definition: HierarchicalAugmenter.h:160
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::InData
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::HierarchicalAugmenterInOutData< FieldType > InData
Output arrays used in DIY exchange.
Definition: HierarchicalAugmenter.h:172
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::SetSuperparentSetDecorator
Decorator to add the Ascending flag if necessary.
Definition: SetSuperparentSetDecorator.h:62
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::CreateSuperarcsWorklet
Worklet used to implement the main part of HierarchicalAugmenter::CreateSuperarcs Connect superarcs f...
Definition: CreateSuperarcsWorklet.h:64
FindSuperparentForNecessaryNodesWorklet.h
vtkm::worklet::contourtree_distributed::PermuteComparator
Definition: hierarchical_contour_tree/PermuteComparator.h:121
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
IsAttachementPointPredicate.h
vtkm::cont::make_ArrayHandleView
ArrayHandleView< ArrayHandleType > make_ArrayHandleView(const ArrayHandleType &array, vtkm::Id startIndex, vtkm::Id numValues)
Definition: ArrayHandleView.h:222
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::CreateSuperarcs
void CreateSuperarcs(vtkm::Id roundNumber)
adds a round full of superarcs (and regular nodes) to the tree
Definition: HierarchicalAugmenter.h:1157
vtkm::worklet::contourtree_augmented::ResizeVector
void ResizeVector(vtkm::cont::ArrayHandle< ValueType > &thearray, vtkm::Id newSize, ValueType fillValue)
Helper function used to resize a 1D ArrayHandle and initalize new values with a given fillValue.
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:180
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::UpdateHyperstructure
void UpdateHyperstructure()
reset the super Ids in the hyperstructure to the new values
Definition: HierarchicalAugmenter.h:653
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::Invoke
vtkm::cont::Invoker Invoke
Used internally to Invoke worklets.
Definition: HierarchicalAugmenter.h:241
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::IsAttachementPointPredicate
Definition: IsAttachementPointPredicate.h:109
AttachmentSuperparentAndIndexComparator.h
HierarchicalAugmenterInOutData.h
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::PrepareOutAttachmentPoints
void PrepareOutAttachmentPoints(vtkm::Id round)
routine to prepare the set of attachment points to transfer
Definition: HierarchicalAugmenter.h:344
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::CopySuperstructure
void CopySuperstructure()
transfer level of superstructure with insertions
Definition: HierarchicalAugmenter.h:630
PermuteComparator.h
vtkm::cont::Algorithm::CopySubRange
static VTKM_CONT bool CopySubRange(vtkm::cont::DeviceAdapterId devId, const vtkm::cont::ArrayHandle< T, CIn > &input, vtkm::Id inputStartIndex, vtkm::Id numberOfElementsToCopy, vtkm::cont::ArrayHandle< U, COut > &output, vtkm::Id outputIndex=0)
Definition: Algorithm.h:472
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::OutData
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::HierarchicalAugmenterInOutData< FieldType > OutData
if we're not careful, we'll have read-write conflicts when swapping with the partner there are other ...
Definition: HierarchicalAugmenter.h:168
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::AugmentedTree
vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > * AugmentedTree
the tree that it is building
Definition: HierarchicalAugmenter.h:133
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::BaseTree
vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > * BaseTree
the tree that it hypersweeps over
Definition: HierarchicalAugmenter.h:131
vtkm::cont::Algorithm::Sort
static VTKM_CONT void Sort(vtkm::cont::DeviceAdapterId devId, vtkm::cont::ArrayHandle< T, Storage > &values)
Definition: Algorithm.h:965
vtkm::cont::make_ArrayHandleConstant
vtkm::cont::ArrayHandleConstant< T > make_ArrayHandleConstant(T value, vtkm::Id numberOfValues)
make_ArrayHandleConstant is convenience function to generate an ArrayHandleImplicit.
Definition: ArrayHandleConstant.h:89
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
PrintVectors.h
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::cont::make_ArrayHandleDecorator
VTKM_CONT ArrayHandleDecorator< typename std::decay< DecoratorImplT >::type, typename std::decay< ArrayTs >::type... > make_ArrayHandleDecorator(vtkm::Id numValues, DecoratorImplT &&f, ArrayTs &&... arrays)
Create an ArrayHandleDecorator with the specified number of values that uses the provided DecoratorIm...
Definition: ArrayHandleDecorator.h:677
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::GlobalRegularIds
vtkm::worklet::contourtree_augmented::IdArrayType GlobalRegularIds
arrays storing the details for the attachment points & old supernodes the Id in the global data set
Definition: HierarchicalAugmenter.h:139
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::AttachmentIdsEqualComparator
Execution object for a comparator that sorts supernode pairs by:
Definition: AttachmentIdsEqualComparator.h:93
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::HierarchicalAugmenter
HierarchicalAugmenter()
empty constructor
Definition: HierarchicalAugmenter.h:195
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::PrepareAugmentedTree
void PrepareAugmentedTree()
initial preparation
Definition: HierarchicalAugmenter.h:494
SetSuperparentSetDecorator.h
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::BuildAugmentedTree
void BuildAugmentedTree()
routine to reconstruct a hierarchical tree using the augmenting supernodes
Definition: HierarchicalAugmenter.h:477
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::DataValues
vtkm::cont::ArrayHandle< FieldType > DataValues
the data value
Definition: HierarchicalAugmenter.h:142
AttachmentAndSupernodeComparator.h
vtkm::worklet::contourtree_augmented::NoSuchElement
VTKM_EXEC_CONT bool NoSuchElement(vtkm::Id flaggedIndex)
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:97
vtkm::cont::LogLevel::Info
@ Info
Information messages (detected hardware, etc) and temporary debugging output.
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::SuperparentRounds
vtkm::worklet::contourtree_augmented::IdArrayType SuperparentRounds
we want to track the round on which the superparent is transferred (we could look it up,...
Definition: HierarchicalAugmenter.h:157
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::contourtree_distributed::HierarchicalAugmenter::SupernodeIds
vtkm::worklet::contourtree_augmented::IdArrayType SupernodeIds
the supernode index when we swap attachment points, we will set this to NO_SUCH_ELEMENT because the s...
Definition: HierarchicalAugmenter.h:147
vtkm::cont::make_ArrayHandleTransform
VTKM_CONT vtkm::cont::ArrayHandleTransform< HandleType, FunctorType > make_ArrayHandleTransform(HandleType handle, FunctorType functor)
make_ArrayHandleTransform is convenience function to generate an ArrayHandleTransform.
Definition: ArrayHandleTransform.h:474
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::CopyHyperstructure
void CopyHyperstructure()
transfer of hyperstructure but not superchildren count
Definition: HierarchicalAugmenter.h:578
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::Initialize
void Initialize(vtkm::Id blockId, vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > *inBaseTree, vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > *inAugmentedTree)
initializer (called explicitly after constructor)
Definition: HierarchicalAugmenter.h:249
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter
Facture class for augmenting the hierarchical contour tree to enable computations of measures,...
Definition: HierarchicalAugmenter.h:127
IsAttachementPointNeededPredicate.h
vtkm::cont::ArrayHandleCounting< vtkm::Id >
vtkm::cont::Invoker
Allows launching any worklet without a dispatcher.
Definition: Invoker.h:41
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::DebugSave
void DebugSave(std::string filename)
Definition: HierarchicalAugmenter.h:1471
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_distributed::HierarchicalContourTree::DumpVolumes
static VTKM_CONT std::string DumpVolumes(const vtkm::worklet::contourtree_augmented::IdArrayType &supernodes, const vtkm::worklet::contourtree_augmented::IdArrayType &superarcs, const vtkm::worklet::contourtree_augmented::IdArrayType &regularNodeGlobalIds, vtkm::Id totalVolume, const vtkm::worklet::contourtree_augmented::IdArrayType &intrinsicVolume, const vtkm::worklet::contourtree_augmented::IdArrayType &dependentVolume)
Definition: HierarchicalContourTree.h:892
Types.h
vtkm::worklet::contourtree_augmented::MaskedIndexFunctor
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:208
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::BlockId
vtkm::Id BlockId
the ID of the base block (used for debug output)
Definition: HierarchicalAugmenter.h:136
UpdateHyperstructureSetSuperchildrenWorklet.h
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::FirstAttachmentPointInRound
vtkm::worklet::contourtree_augmented::IdArrayType FirstAttachmentPointInRound
tracks segments of attachment points by round
Definition: HierarchicalAugmenter.h:179
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::DebugPrint
std::string DebugPrint(std::string message, const char *fileName, long lineNum)
debug routine
Definition: HierarchicalAugmenter.h:1333
ResizeArraysBuildNewSupernodeIdsWorklet.h
vtkm::cont::ArrayHandleConstant
An array handle with a constant value.
Definition: ArrayHandleConstant.h:63
vtkm::worklet::contourtree_augmented::PrintValues
void PrintValues(std::string label, const vtkm::cont::ArrayHandle< T, StorageType > &dVec, vtkm::Id nValues=-1, std::ostream &outStream=std::cout)
Definition: augmented/PrintVectors.h:197
vtkm::CopyFlag::On
@ On
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::AttachmentIds
vtkm::worklet::contourtree_augmented::IdArrayType AttachmentIds
these are essentially temporary local variables, but are placed here to make the DebugPrint() more co...
Definition: HierarchicalAugmenter.h:177
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::RetrieveOldSupernodes
void RetrieveOldSupernodes(vtkm::Id roundNumber)
gets a list of all the old supernodes to transfer at this level (ie except attachment points
Definition: HierarchicalAugmenter.h:842
PrintGraph.h
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::SuperparentSet
vtkm::worklet::contourtree_augmented::IdArrayType SuperparentSet
Definition: HierarchicalAugmenter.h:188
AttachmentIdsEqualComparator.h
NotNoSuchElementPredicate.h
vtkm::worklet::contourtree_augmented::NotNoSuchElementPredicate
Definition: NotNoSuchElementPredicate.h:67
VTKM_LOG_S
#define VTKM_LOG_S(level,...)
Writes a message using stream syntax to the indicated log level.
Definition: Logging.h:261
vtkm::cont::make_ArrayHandlePermutation
VTKM_CONT vtkm::cont::ArrayHandlePermutation< IndexArrayHandleType, ValueArrayHandleType > make_ArrayHandlePermutation(IndexArrayHandleType indexArray, ValueArrayHandleType valueArray)
make_ArrayHandleTransform is convenience function to generate an ArrayHandleTransform.
Definition: ArrayHandlePermutation.h:279
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::ResizeArrays
void ResizeArrays(vtkm::Id roundNumber)
resizes the arrays for the level
Definition: HierarchicalAugmenter.h:904
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::RetrieveInAttachmentPoints
void RetrieveInAttachmentPoints()
routine to retrieve partner's current list of attachment points
Definition: HierarchicalAugmenter.h:402
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::RegularSuperparents
vtkm::worklet::contourtree_augmented::IdArrayType RegularSuperparents
data for transferring regular nodes
Definition: HierarchicalAugmenter.h:191
CreateSuperarcsWorklet.h
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::DataValueSet
vtkm::cont::ArrayHandle< FieldType > DataValueSet
Definition: HierarchicalAugmenter.h:187
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::ReleaseSwapArrays
void ReleaseSwapArrays()
routine to release memory used for swap arrays
Definition: HierarchicalAugmenter.h:468
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::HierarchicalAugmenterInOutData
Class for storing input or output data for the HierarchicalAugmenter.
Definition: HierarchicalAugmenterInOutData.h:73
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::SupernodeSorter
vtkm::worklet::contourtree_augmented::IdArrayType SupernodeSorter
sorting array & arrays for data details
Definition: HierarchicalAugmenter.h:185
IsAscendingDecorator.h
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::Superparents
vtkm::worklet::contourtree_augmented::IdArrayType Superparents
the superarc will ALWAYS be -1 for a true attachment point, so we don't store it instead,...
Definition: HierarchicalAugmenter.h:153
vtkm::worklet::contourtree_augmented::PrintIndices
void PrintIndices(std::string label, const vtkm::cont::ArrayHandle< T > &iVec, vtkm::Id nIndices=-1, std::ostream &outStream=std::cout)
Definition: augmented/PrintVectors.h:253
vtkm::worklet::contourtree_augmented::PrintHeader
void PrintHeader(vtkm::Id howMany, std::ostream &outStream=std::cout)
Definition: augmented/PrintVectors.h:151
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::SupernodeIdSet
vtkm::worklet::contourtree_augmented::IdArrayType SupernodeIdSet
Definition: HierarchicalAugmenter.h:189
vtkm::worklet::contourtree_augmented::IdArraySetValue
VTKM_CONT void IdArraySetValue(vtkm::Id index, vtkm::Id value, IdArrayType &arr)
Helper function to set a single array valye with CopySubRange to avoid pulling the array to the contr...
Definition: filter/scalar_topology/worklet/contourtree_augmented/Types.h:165
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::CopyBaseRegularStructure
void CopyBaseRegularStructure()
copy the remaining base level regular nodes
Definition: HierarchicalAugmenter.h:689
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::RegularNodesNeeded
vtkm::worklet::contourtree_augmented::IdArrayType RegularNodesNeeded
Definition: HierarchicalAugmenter.h:192
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::NewSupernodeIds
vtkm::worklet::contourtree_augmented::IdArrayType NewSupernodeIds
maps from old supernode Id to new supernode Id
Definition: HierarchicalAugmenter.h:181
vtkm::worklet::contourtree_augmented::PrintArrayHandle
void PrintArrayHandle(std::string label, const ARRAYTYPE &dVec, vtkm::Id nValues, std::ostream &outStream)
Definition: augmented/PrintVectors.h:171
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::IsAscendingDecorator
Decorator to add the Ascending flag if necessary.
Definition: IsAscendingDecorator.h:62
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::contourtree_distributed::HierarchicalAugmenter::KeptSupernodes
vtkm::worklet::contourtree_augmented::IdArrayType KeptSupernodes
tracks which supernodes are kept in a given round
Definition: HierarchicalAugmenter.h:183
SetFirstAttachmentPointInRoundWorklet.h
vtkm::worklet::contourtree_distributed::HierarchicalAugmenter::GlobalRegularIdSet
vtkm::worklet::contourtree_augmented::IdArrayType GlobalRegularIdSet
Definition: HierarchicalAugmenter.h:186
CopyBaseRegularStructureWorklet.h
vtkm::worklet::contourtree_distributed::hierarchical_augmenter::CopyBaseRegularStructureWorklet
Worklet used in HierarchicalAugmenter::CopyBaseRegularStructure for finding the superparent for each ...
Definition: CopyBaseRegularStructureWorklet.h:63
vtkm::cont::ArrayHandleIndex
An implicit array handle containing the its own indices.
Definition: ArrayHandleIndex.h:54