VTK-m  2.0
TreeGrafter.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 // TreeResidue.h - A data structure storing the residue information for transfer
49 // to the grafting phase
50 //
51 //================================================================================
52 //
53 // COMMENTS:
54 //
55 //
56 //================================================================================
57 
58 
59 #ifndef vtk_m_worklet_contourtree_distributed_tree_grafter_h
60 #define vtk_m_worklet_contourtree_distributed_tree_grafter_h
61 
62 #include <vtkm/Types.h>
65 
93 
94 #include <sstream>
95 #include <string>
96 #include <utility>
97 
98 
99 namespace vtkm
100 {
101 namespace worklet
102 {
103 namespace contourtree_distributed
104 {
105 
107 template <typename MeshType, typename FieldType>
109 { // class TreeGrafter
110 public:
111  // pointers to the related data structures
112  MeshType* Mesh;
115 
116  // arrays sized to all regular vertices - this may not be necessary, but is robust
118 
119  // flags for type of supernode
121 
122  // new supernode Ids for each supernode
124 
125  // maps supernode Ids to regular Ids in parent hierarchical tree, if any
127  // does the same to supernode Ids, if any
129  // and for superparents
131  // does the same for hypernode Ids, if any
133  // this array tracks which superarc we insert into / belong on
135  // this one tracks what the hyperarc points to
137  // this array is for tracking when we are transferred
139 
140  // upwards & downwards neighbours for collapsing superarcs
143 
144  // active supernode set used for re-constructing hyperstructure
146 
147  // arrays holding the nodes, supernodes and hypernodes that need to be transferred
151 
152  // variable for tracking # of iterations needed in transfer
154 
157  MeshType* mesh,
160  : Mesh(mesh)
161  , ContourTree(contourTree)
162  , InteriorForest(interiorForest)
163  { // constructor
164  } // constructor
165 
176  template <typename StorageTag>
178  vtkm::Id theRound,
181  const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler =
182  nullptr);
183 
184 
193  template <typename StorageTag>
194  void GetHierarchicalIds(
197  const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler =
198  nullptr);
199 
202 
204  void FindCriticalPoints();
205 
207  void CollapseRegularChains();
208 
210  void IdentifyLeafHyperarcs();
211 
213  void CompressActiveArrays();
214 
216  void ListNewHypernodes(
218 
220  void ListNewSupernodes(
222 
229  void ListNewNodes(
231  const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler =
232  nullptr);
233 
235  void CopyNewHypernodes(
237 
239  void CopyNewSupernodes(
241  vtkm::Id theRound);
242 
253  template <typename StorageTag>
254  void CopyNewNodes(
257  const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler =
258  nullptr);
259 
263  vtkm::Id theRound);
264 
266  std::string DebugPrint(const char* message, const char* fileName, long lineNum);
267 
268 private:
271 }; // class TreeGrafter
272 
273 
274 // routine to graft the InteriorForest residue from the BoundaryTree computation into the tree
275 template <typename MeshType, typename FieldType>
276 template <typename StorageTag>
278  vtkm::Id theRound,
281  const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler)
282 { // GraftInteriorForests()
283  // Since all supernodes represented in the bract have been dealt with, this routine needs to
284  // identify which supernodes / superarcs need to be added
285 
286  // The first step is simply to find out which supernodes are already hierarchical supernodes
287  // To do this, we rely on arrays from the TreeGrafter:
288  //
289  // We therefore need to do the following:
290  // 1. For each supernode, search by global ID in the hierarchy to determine whether
291  // it is already present, saving the regular and super IDs if it is, NO_SUCH_ELEMENT otherwise
292  // 2. We can then test these IDs to classify:
293  // Super != NSE: Already present.
294  // Super = NSE, Regular != NSE: Attachment point, but it is already represented as a regular node
295  // Super = NSE, Regular = NSE: Free supernode. No additional work required
296  // 3. Reconstruct the hyperstructure from the outside in
297 
298  // 1. For each supernode, search by global ID in the hierarchy to determine
299  // whether it is already present, saving the regular and super IDs if it is, NO_SUCH_ELEMENT otherwise
300 
301 #ifdef DEBUG_PRINT
302  VTKM_LOG_S(vtkm::cont::LogLevel::Info, "theRound: " << theRound);
304  this->DebugPrint("Before GraftResidue()", __FILE__, __LINE__));
305  VTKM_LOG_S(
307  this->ContourTree.DebugPrint("Contour Tree Before GraftResidue()", __FILE__, __LINE__));
309  hierarchicalTree.DebugPrint("Hier Tree Before GraftResidue()", __FILE__, __LINE__));
310  VTKM_LOG_S(
312  this->InteriorForest->DebugPrint("InteriorForest Before GraftResidue()", __FILE__, __LINE__));
313 #endif
314 
315  this->GetHierarchicalIds(hierarchicalTree, meshDataValues, localToGlobalIdRelabeler);
316 
317  // now we need to replicate the merge phase to construct a new hyperstructure
318  // 2. Establish the active set of supernodes & superarcs
319  this->InitializeActiveSuperarcs();
320 
321  // count the number of iterations
322  this->NumTransferIterations = 0;
323 
324  // There are several cases we need to handle properly
325  // 1. We could have a round with no superarcs to add (in which case we are
326  // guaranteed not to have attachment points)
327  // 2. We could have a round with some superarcs but no attachment points
328  // (because we attach to existing supernodes)
329  // 3. We could have a round with attachment points to add
330  // Attachment points are interior, so are never added to the active superarc
331  // list in the first place. This means that we need to have an extra round
332  // some of the time to transfer attachment points. So the logic is:
333  // first we transfer all active superarcs, then we test (somehow) for having
334  // attachment points to transfer
335  // Loop to transfer active superarcs with a variation of the PPP transfer phase
336  // We stop when all that is left are attachment points (which aren't included in the active list)
337  while (this->ActiveSuperarcs.GetNumberOfValues() > 0)
338  { // loop to transfer
339  // 3. Use the write-collision trick to find leaves, regular nodes
340  this->FindCriticalPoints();
341 
342  // 4. Chain up/down to find hyperarcs
343  this->CollapseRegularChains();
344 
345  // 5. Test for leaves & identify hyperarcs
346  // alternating betwen up and down
347  // NB: it is therefore possible to have 0 leaves in an iteration, eg if there are no upper leaves to be transferred
348  this->IdentifyLeafHyperarcs();
349 
350  // 6. Compress arrays & repeat
351  this->CompressActiveArrays();
352 
353  // 7. Update the iteration count
354  this->NumTransferIterations++;
355  } // loop to transfer
356 
357 #ifdef DEBUG_PRINT
359  DebugPrint("Finished Transfer Iterations", __FILE__, __LINE__));
360 #endif
361 
362  // At this point, we can check to see whether all supernodes in the residue have already been transferred
363  // length of the attachementCounter will be set to (this->ContourTree->Supernodes.GetNumberOfValue());
364  // as a result of the worklet
367  calculateAttachementCounterWorklet;
368  this->Invoke(calculateAttachementCounterWorklet, // worklet
369  this->SupernodeType, // input
370  this->HierarchicalSuperId, // input
371  attachmentCounter // output
372  );
373  // Compute the sum of all values in attachmentCounter. vtkm::Add() is the default (so it could be omitted).
374  // We include it here to be more explicit about what Reduce does.
375  vtkm::Id numAttachmentPoints =
376  vtkm::cont::Algorithm::Reduce(attachmentCounter, static_cast<vtkm::Id>(0), vtkm::Add());
377 
378  // if there are any at all, we need an extra iteration
379  if (numAttachmentPoints > 0)
380  { // attachment points needing transfer
381  // Now set the transfer iteration for all attachment points
382  // If there were no supernodes to transfer, their types are all NO_SUCH_ELEMENT
383  auto setTransferIterationWorklet = vtkm::worklet::contourtree_distributed::tree_grafter::
384  GraftInteriorForestsSetTransferIterationWorklet(this->NumTransferIterations);
385  this->Invoke(setTransferIterationWorklet,
386  this->SupernodeType, // input
387  this->HierarchicalSuperId, // input
388  this->WhenTransferred // output
389  );
390  // and increment the number of iterations
391  this->NumTransferIterations++;
392  } // attachment points needing transfer
393 
394 #ifdef DEBUG_PRINT
396  DebugPrint("Finished Setting Attachment Point Iterations", __FILE__, __LINE__));
397 #endif
398  // The secondary arrays now hold all of the information we need, and we have to transfer it to the hierarchical tree
399  // This used to be one single huge function, but has now been broken up for clarity (and because it simplified it)
400 
401  // Copying is easiest if we know the mapping of old IDs to new IDs for all regular, super and hyper nodes first, so we establish this
402  // (this can be done in any order):
403  ListNewHypernodes(hierarchicalTree);
404  ListNewSupernodes(hierarchicalTree);
405  ListNewNodes(hierarchicalTree, localToGlobalIdRelabeler);
406 
407  // Once we have done so, we can transfer them all to the hierarchical tree
408  // WARNING! WARNING! WARNING!
409  // CopyNewNodes() depends on having CopyNewHypernodes() & CopyNewSupernodes() called first!!!!
410  CopyNewHypernodes(hierarchicalTree);
411  CopyNewSupernodes(hierarchicalTree, theRound);
412  CopyNewNodes(hierarchicalTree, meshDataValues, localToGlobalIdRelabeler);
413 
414  // Now we can copy the remaining details to the hierarchical tree, and we are done!
415  CopyIterationDetails(hierarchicalTree, theRound);
416 
417 #ifdef DEBUG_PRINT
419  hierarchicalTree.DebugPrint("GraftInteriorForests() Completed", __FILE__, __LINE__));
420 #endif
421 } // GraftInteriorForests()
422 
423 
432 template <typename MeshType, typename FieldType>
433 template <typename StorageTag>
437  const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler)
438 { // GetHierarchicalIds()
439  // HAC: This appears to be the preferred idiom for resizing & initializing an array
440  // In order for us to build a hierarchical contour tree (HCT), we need to know where in the hierarchical tree a given
441  // supernode in the block's contour tree (BCT) belongs, and what its super/hyperparents are
442  // The possibilities are:
443  // 0. It's not necessary (in InFo but not attachment) cannot be in the HCT, so set arrays to NO_SUCH_ELEMENT
444  // 1. It's necessary but not in the HCT: all of the arrays need to be set to NO_SUCH_ELEMENT
445  // 2. It's in the HCT, but only as a regular node: regular ID needs to be set, as does superparent, others set to NO_SUCH_ELEMENT
446  // 3. It's in the HCT as a super but not hyper node: regular/super IDs are set, super/hyperparent are set, hyperID set to NO_SUCH_ELEMENT
447  // 4. It's in the HCT as a hyper node: all values need to be set
448  //
449  // The solution adopted is to set all of them to NO_SUCH_ELEMENT by default, and reset each of them as we determine them.
450 
451  // We start by resizing all of the arrays to the size of the BCT & setting everything to NO_SUCH_ELEMENT
452  {
453  auto tempNoSuchElementArray =
455  this->ContourTree.Supernodes.GetNumberOfValues());
456  vtkm::cont::Algorithm::Copy(tempNoSuchElementArray, this->HierarchicalRegularId);
457  vtkm::cont::Algorithm::Copy(tempNoSuchElementArray, this->HierarchicalSuperId);
458  vtkm::cont::Algorithm::Copy(tempNoSuchElementArray, this->HierarchicalSuperparent);
459  vtkm::cont::Algorithm::Copy(tempNoSuchElementArray, this->HierarchicalHyperparent);
460  vtkm::cont::Algorithm::Copy(tempNoSuchElementArray, this->HierarchicalHyperId);
461  }
462 
463  // Now, to convert from supernode IDs in the BCT to regular IDs in the HCT, we either need to track IDs forward through the entire computation
464  // or we need to be able to look them up. We chose the latter approach, and therefore need to convert the supernode IDs into global IDs
465  // create an array with all of the supernodes
466  // NOTE:supernodeGlobalIds may have different type depending on the mesh we use a different smart array handle to avoid memory allocation
467  /*
468  vtkm::worklet::contourtree_augmented::IdArrayType supernodeGlobalIds;
469  vtkm::cont::Algorithm::Copy(
470  vtkm::cont::make_ArrayHandleConstant(vtkm::worklet::contourtree_augmented::NO_SUCH_ELEMENT,
471  this->ContourTree.Supernodes.GetNumberOfValues()),
472  supernodeGlobalIds);
473  // and ask the mesh to fill it in
474  mesh->GetGlobalIDsFromSortIndices(contourTree->supernodes, supernodeGlobalID);
475  */
476  auto supernodeGlobalIds =
477  this->Mesh->GetGlobalIdsFromSortIndices(this->ContourTree.Supernodes, localToGlobalIdRelabeler);
478 
479  // retrieve the regular, super IDs (if present)
480  auto getHierarchicalIdsWorklet =
482 
483  auto findRegularByGlobal = hierarchicalTree.GetFindRegularByGlobal();
484  auto findSuperArcForUnknownNode = hierarchicalTree.GetFindSuperArcForUnknownNode();
485 
486  // TODO: A possible slight optimization would be to use a permutted array for the Mesh->SortedValues/Mesh->SortOrder because we in the ContourTreeMesh we can just do direct lookup. Since in the ContourTreeMesh the SortOrder is handled as a VTKm fancy array the extra cost should not be too bad in terms of memory and compute, but it would help avoid extra function calls and might help the compiler optimize things more.
487  this->Invoke(getHierarchicalIdsWorklet,
488  // input array
489  this->ContourTree.Supernodes,
490 
491  // arrays used for reference (read-only)
492  supernodeGlobalIds,
493  this->Mesh->SortOrder,
494  meshDataValues,
495  this->InteriorForest->IsNecessary,
496  this->InteriorForest->Above,
497  this->InteriorForest->Below,
498  hierarchicalTree.Superparents,
499  hierarchicalTree.Hyperparents,
500  hierarchicalTree.Regular2Supernode,
501  hierarchicalTree.Super2Hypernode,
502  // Execution object to use the FindRegularByGlobal and
503  // FindSuperArcForUnknownNode for the hierarchical tree.
504  findRegularByGlobal,
505  findSuperArcForUnknownNode,
506 
507  // arrays used to write output to
508  this->HierarchicalRegularId,
509  this->HierarchicalSuperId,
510  this->HierarchicalHyperId,
511  this->HierarchicalSuperparent,
512  this->HierarchicalHyperparent);
513 
514 #ifdef DEBUG_PRINT
516  DebugPrint("GetHierarchicalIDs() Complete", __FILE__, __LINE__));
517 #endif
518 } // GetHierarchicalIDs()
519 
520 
530 template <typename MeshType, typename FieldType>
532 { // InitializeActiveSuperarcs()
533  // Resize the up/down neighbours to all supernodes (we won't use all of them, but ...)
536  this->ContourTree.Supernodes.GetNumberOfValues()),
537  this->UpNeighbour);
540  this->ContourTree.Supernodes.GetNumberOfValues()),
541  this->DownNeighbour);
542 #ifdef DEBUG_PRINT
543  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Up & Down Resized", __FILE__, __LINE__));
544 #endif
545 
546  // start by working out a mapping from existing superarc ID to active superarc ID
547  // the root superarc, which is guaranteed to be at the end of the array, is omitted
549  activeSuperarcId.Allocate(this->ContourTree.Supernodes.GetNumberOfValues() - 1);
550  {
551  // loop to one less, i.e. excluding null superarc from root. tempSuperarcIndex is used as our loop index for the worklet
552  auto tempSuperarcIndex =
553  vtkm::cont::ArrayHandleIndex(this->ContourTree.Supernodes.GetNumberOfValues() - 1);
554  auto initActiceSuperarcIdWorklet =
556  this->Invoke(initActiceSuperarcIdWorklet,
557  tempSuperarcIndex, // input iteration index,
558  this->ContourTree.Superarcs, // input
559  this->InteriorForest->IsNecessary, // input
560  activeSuperarcId // output
561  );
562  }
563  // TODO: Check that it is Ok to use the same array as input and ouput for the partial sum in VTKm
564  // TODO: According to the original code this WANTS to be an exclusive_scan / prefix_sum,
565  // but it was not compiling in the orginal code, so this was workaround: see also comment in the following worklet
566  // In VTKm we could change this to a ScanExclusive but using the inclusive scan is fine too
567  // compute the new indices for each:
568  {
570  vtkm::cont::Algorithm::Copy(activeSuperarcId, tempASI);
571  vtkm::cont::Algorithm::ScanInclusive(tempASI, activeSuperarcId);
572  // vtkm::cont::Algorithm::ScanInclusive(activeSuperarcId , activeSuperarcId);
573  }
574  // the final element will hold the result
575  vtkm::Id nFree =
576  vtkm::cont::ArrayGetValue(activeSuperarcId.GetNumberOfValues() - 1, activeSuperarcId);
577  // TODO FIX nFree is 0 here. Check that this is correct. I believe it should be non-zero.
578  // resize the active list accordingly
579  this->ActiveSuperarcs.Allocate(nFree);
580 
581  // Initalize the active superarcs
582  {
583  // loop to one less, i.e. excluding null superarc from root. tempSuperarcIndex is used as our loop index for the worklet
584  auto tempSuperarcIndex =
585  vtkm::cont::ArrayHandleIndex(this->ContourTree.Supernodes.GetNumberOfValues() - 1);
586  auto initActiceSuperarcsWorklet =
588  this->Invoke(initActiceSuperarcsWorklet,
589  tempSuperarcIndex, // input iterator variable
590  this->ContourTree.Superarcs, // input
591  this->InteriorForest->IsNecessary, // input
592  activeSuperarcId, // input
593  this->ActiveSuperarcs // output
594  );
595  }
596 
597 #ifdef DEBUG_PRINT
599  DebugPrint("Active Superarc Array Initialized", __FILE__, __LINE__));
600 #endif
601 
602  // prepare memory for our transfer arrays
605  this->ContourTree.Supernodes.GetNumberOfValues()),
606  this->WhenTransferred);
609  this->ContourTree.Supernodes.GetNumberOfValues()),
610  this->SupernodeType);
613  this->ContourTree.Supernodes.GetNumberOfValues()),
614  this->HierarchicalHyperarc);
615 
616 #ifdef DEBUG_PRINT
618  DebugPrint("InitializeActiveSuperarcs() Complete", __FILE__, __LINE__));
619 #endif
620 } // InitializeActiveSuperarcs()
621 
622 
629 template <typename MeshType, typename FieldType>
631 { // FindCriticalPoints()
632  // allocate memory for type of supernode
634  this->SupernodeType,
635  this->ContourTree.Supernodes.GetNumberOfValues(),
637  // Reset the UpNeighbour and DownNeighbour array
640  this->UpNeighbour.GetNumberOfValues()),
641  this->UpNeighbour);
644  this->DownNeighbour.GetNumberOfValues()),
645  this->DownNeighbour);
646 
647 #ifdef DEBUG_PRINT
648  // TODO: Hamish: I don't think we need this DebugPrint here.
650  DebugPrint("Setting Up/Down Neighbours", __FILE__, __LINE__));
651 #endif
652 
653  // fill in the up/down neighbour arrays
654  auto setUpDownNeighboursWorklet = vtkm::worklet::contourtree_distributed::tree_grafter::
655  FindCriticalPointsSetUpDownNeighboursWorklet();
656  this->Invoke(setUpDownNeighboursWorklet, // worklet to invoke
657  this->ActiveSuperarcs, // input
658  this->InteriorForest->IsNecessary, // input
659  this->UpNeighbour, // output
660  this->DownNeighbour, // output
661  this->SupernodeType // output
662  );
663 
664 #ifdef DEBUG_PRINT
665  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Up/Down Neighbours Set", __FILE__, __LINE__));
666 #endif
667 
668  // now test whether they match what we expect: if not, we've found a saddle
669  auto findSaddlesWorklet =
671  this->Invoke(findSaddlesWorklet,
672  this->ActiveSuperarcs, // input
673  this->InteriorForest->IsNecessary, // input
674  this->UpNeighbour, // input
675  this->DownNeighbour, // input
676  this->SupernodeType // output
677  );
678 
679 
680 #ifdef DEBUG_PRINT
681  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Saddles Identified", __FILE__, __LINE__));
682 #endif
683  // flag the leaves
684  auto findLeafsWorklet =
686  this->Invoke(findLeafsWorklet,
687  this->ActiveSuperarcs, // input
688  this->InteriorForest->IsNecessary, // input
689  this->UpNeighbour, // input
690  this->DownNeighbour, // input
691  this->SupernodeType // output (and input)
692  );
693 
694 #ifdef DEBUG_PRINT
695  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Attachments Identified", __FILE__, __LINE__));
696 #endif
697 
698  // one more pass to set terminal flags
699  auto findTerminalElementsWorklet = vtkm::worklet::contourtree_distributed::tree_grafter::
700  FindCriticalPointsFindTerminalElementsWorklet();
701  this->Invoke(findTerminalElementsWorklet,
702  this->ActiveSuperarcs, // input
703  this->SupernodeType, // input
704  this->UpNeighbour, // output (and input)
705  this->DownNeighbour // output (and input)
706  );
707 
708 #ifdef DEBUG_PRINT
710  DebugPrint("FindCriticalPoints() Complete", __FILE__, __LINE__));
711 #endif
712 
713 } // FindCriticalPoints()
714 
715 
721 template <typename MeshType, typename FieldType>
723 { // CollapseRegularChains()
724  // Compute the number of log steps required in this pass
725  vtkm::Id nLogSteps = static_cast<vtkm::Id>(1);
726  for (vtkm::Id shifter = this->ActiveSuperarcs.GetNumberOfValues(); shifter != 0; shifter >>= 1)
727  {
728  nLogSteps++;
729  }
730 
731  // loop to find the now-regular vertices and collapse past them without altering
732  // the existing join & split arcs
733  for (vtkm::Id iteration = 0; iteration < nLogSteps; iteration++)
734  { // per iteration
735  // loop through the vertices, updating up and down
736  auto collapseRegularChainsWorklet =
738  this->Invoke(collapseRegularChainsWorklet,
739  this->ActiveSuperarcs, // input
740  this->UpNeighbour, // output (and input)
741  this->DownNeighbour // output (and input)
742  );
743  } // per iteration
744 
745 #ifdef DEBUG_PRINT
747  DebugPrint("CollapseRegularChains() Complete", __FILE__, __LINE__));
748 #endif
749 
750 } // CollapseRegularChains()
751 
752 
759 template <typename MeshType, typename FieldType>
761 { // IdentifyLeafHyperarcs()
762  // At this stage, we have:
763  // i. hierarchicalRegularID set for any supernode stored at all in the parent
764  // ii. hierarchicalSuperID set for any supernode that is a supernode in the parent
765  // iii. hierarchicalHyperParent set for any attachment point
766  // iv. supernodeType set to indicate what type of supernode
767  // v. up/dn neighbours set for all supernodes
768 
769  // at the end of the chain collapse, the up/down neighbours define the start & end of the hyperarc
770  // one end may be a leaf, in which case we can transfer the hyperarc
771  // note that because we are grafting, we have a guarantee that they can't both be leaves
772  // we therefore:
773  // a. for leaves, determine whether up or down hyperarc, create hyperarc
774  // b. for regular vertices pointing to a leaf hyperarc, set superarc / hyperparent
775  // c. for other vertices, ignore
776  auto identifyLeafHyperarcsWorklet =
778  this->NumTransferIterations);
779  this->Invoke(identifyLeafHyperarcsWorklet,
780  this->ActiveSuperarcs, // input
781  this->SupernodeType, // input
782  this->UpNeighbour, // input
783  this->DownNeighbour, // input
784  this->HierarchicalHyperparent, // output
785  this->HierarchicalHyperarc, // output
786  this->WhenTransferred // output
787  );
788 
789  // Invariant: All free supernodes (only) should now have:
790  // Hierarchical Hyperparent set to a non-hierarchical superID
791  // Hierarchical Hyperarc set to the non-hierarchical superID of the target IFF the supernode becomes a hypernode
792  // WARNING! The other supernodes should all have the hierarchical hyperparent previously set IN HIERARCHICAL superIDs
793 #ifdef DEBUG_PRINT
795  DebugPrint("IdentifyLeafHyperarcs() Complete.", __FILE__, __LINE__));
796 #endif
797 
798 } // IdentifyLeafHyperarcs()
799 
800 
805 template <typename MeshType, typename FieldType>
807 { // CompressActiveArrays()
808  // create an array where we can put the compressed array
809  vtkm::worklet::contourtree_augmented::EdgePairArray compressedActiveSuperarcs;
810  // prediate for deciding which active superarcs to keep
811  // NOTE: The original PPP used std::remove_if instead of CopyIf so the predicate inverts the logic, i.e, the predicate indictes
812  // which values to keep rather than which ones to remove
813  auto superarcWasTransferredPredicate =
815  this->WhenTransferred);
816  // compress the array
818  this->ActiveSuperarcs, // compress the active superarcs
819  this
820  ->ActiveSuperarcs, // stencil. In reality this->WhenTransferred defines the stencil, but we need to lookup the values based on the superacrs itself
821  compressedActiveSuperarcs, // array where the comprees active superarcs are stored
822  superarcWasTransferredPredicate // unary predicate for deciding which active superarcs are considered true
823  );
824  // swap in the compressed array
825  this->ActiveSuperarcs = compressedActiveSuperarcs;
826 
827 #ifdef DEBUG_PRINT
829  DebugPrint("CompressActiveArrays() Complete", __FILE__, __LINE__));
830 #endif
831 } // CompressActiveArrays()
832 
833 
838 template <typename MeshType, typename FieldType>
841 { // ListNewHypernodes()
842  // A. Start with the list of all supernodes in the non-hierarchical tree
843  // NOTE: In contrast to the orignial code we directly initalize with iota instead of with NO_SUCH_ELEMENT first
845  vtkm::cont::ArrayHandleIndex(this->ContourTree.Supernodes.GetNumberOfValues()),
846  this->NewHypernodes);
847 
848  // B. Remove any which already have a hyper ID in the hierarchical tree
850  // NOTE: The original code used std::remove_if. Since we use CopyIf here we need to invert the predicat and check for which ones to keep not which ones to remove
851  auto notANewHypernodePredicate =
854  this->NewHypernodes, // compress the active superarcs
855  this->HierarchicalHyperarc, // stencil.
856  compressedNewHypernodes, // array where the comprees new hypernodes are stored
857  notANewHypernodePredicate // unary predicate for deciding which active hypernodes are considered true
858  );
859  this->NewHypernodes = compressedNewHypernodes; // swap in the compressed array
860 
861  // C. Sort them by iteration, tiebreaking on ID to make it canonical
862  auto hyperNodeWhenComparator =
864  this->WhenTransferred);
865  vtkm::cont::Algorithm::Sort(this->NewHypernodes, hyperNodeWhenComparator);
866 
867  if (this->NewHypernodes.GetNumberOfValues() == 0)
868  {
869 #ifdef DEBUG_PRINT
871  "TreeGrafter::ListNewHypernodes(): No new hypernodes. Returning.");
872 #endif
873  return;
874  }
875 
876  // D. Use this sorted array to set the hierarchical hyper index for each supernode that is a new hypernode
877  vtkm::Id nOldHypernodes = hierarchicalTree.Hypernodes.GetNumberOfValues();
878  // VTKm copy can't allocate for transformed arrays, but this->HierarchicalHyperId.Allocate(nOldHypernodes) has already been allocate earlier.
879  auto permutedHierarchicalHyperId =
880  vtkm::cont::make_ArrayHandlePermutation(this->NewHypernodes, // id array,
881  this->HierarchicalHyperId // value array to copy to
882  );
883  auto tempNewHierarchicalHyperIdValues = vtkm::cont::ArrayHandleCounting<vtkm::Id>(
884  nOldHypernodes, 1, this->NewHypernodes.GetNumberOfValues());
886  // copy nOldHypernodes + newHypernode
887  tempNewHierarchicalHyperIdValues,
888  // to hierarchicalHyperID[newHypernodes[newHypernode]]
889  permutedHierarchicalHyperId);
890 
891 #ifdef DEBUG_PRINT
892  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("New Hypernodes Listed", __FILE__, __LINE__));
893 #endif
894 } // ListNewHypernodes()
895 
896 
901 template <typename MeshType, typename FieldType>
904 { // ListNewSupernodes()
905 
906  // A. Start with the list of all supernodes in the non-hierarchical tree
907  // NOTE: In contrast to the orignial code we directly initalize with iota instead of with NO_SUCH_ELEMENT first
909  vtkm::cont::ArrayHandleIndex(this->ContourTree.Supernodes.GetNumberOfValues()),
910  this->NewSupernodes);
911  // B. Remove any which are already supernodes in the hierarchical tree
912  // Only new supernodes will have had whenTransferred set, so this is easy to test
914  // NOTE: We here can reuse the NewHypernodePredicate because it does the same, only the stencil changes.
915  // I.e., the predicate applys the NoSuchElement function to the stencil value and returns it as a bool
916  // Similar to ListNewHypernodes the predicate is inverted compared to the orginal because we here use
917  // CopyIf instead of remove_if in the original code
918  auto notANewSupernodePredicate =
921  this->NewSupernodes, // compress the active superarcs
922  this->WhenTransferred, // stencil.
923  compressedNewSupernodes, // array where the compressed new supernodes
924  notANewSupernodePredicate // unary predicate for deciding which supernodes are considered true
925  );
926  this->NewSupernodes = compressedNewSupernodes; // swap in the compressed array
927 
928  if (this->NewSupernodes.GetNumberOfValues() == 0)
929  {
930 #ifdef DEBUG_PRINT
932  "TreeGrafter::ListNewSupernodes(): No new supernodes. Returning.");
933 #endif
934  return;
935  }
936 
937  // C. Sort them to match the hyperarc sort: note that the supernodes array ALWAYS holds a sort index into the nodes
938  auto superNodeWhenComparator =
940  this->WhenTransferred,
941  this->HierarchicalHyperparent,
942  this->HierarchicalHyperId,
943  this->HierarchicalHyperarc,
944  this->ContourTree.Supernodes,
945  this->SupernodeType);
946  vtkm::cont::Algorithm::Sort(this->NewSupernodes, superNodeWhenComparator);
947  // D. Now we set the hierarchical super index which we need for subsequent writes
948  vtkm::Id nOldSupernodes = hierarchicalTree.Supernodes.GetNumberOfValues();
949  // VTKm copy can't allocate for transformed arrays, but this->HierarchicalSuperId.Allocate(nOldHypernodes) has already been allocate earlier.
950  auto permutedHierarchicalSuperId =
951  vtkm::cont::make_ArrayHandlePermutation(this->NewSupernodes, // id array,
952  this->HierarchicalSuperId); // value array to copy to
953  auto tempNewHierarchicalSuperIdValues = vtkm::cont::ArrayHandleCounting<vtkm::Id>(
954  nOldSupernodes, 1, this->NewSupernodes.GetNumberOfValues());
956  // copy nOldSupernodes + newSupernode
957  tempNewHierarchicalSuperIdValues,
958  // to hierarchicalSuperID[newSupernodes[newSupernode]]
959  permutedHierarchicalSuperId);
960 #ifdef DEBUG_PRINT
961  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("New Supernodes Listed", __FILE__, __LINE__));
962 #endif
963 } // ListNewSupernodes()
964 
965 
970 template <typename MeshType, typename FieldType>
973  const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler)
974 { // ListNewNodes()
975  // A. Initialise the array that maps regular IDs to "none"
978  this->ContourTree.Nodes.GetNumberOfValues()),
979  this->HierarchicalTreeId);
980 
981  // B. Set the ID correctly for every regular node
982  // They will not all be in the hierarchical tree, so NO_SUCH_ELEMENT will occur, but that is
983  // what we want in this case. It also means we don't have to set it to NO_SUCH_ELEMENT in section
984  // A., but paranoia indicates we leave that in
985  // This section implements:
986  // for (indexType vertex = 0; vertex < contourTree->nodes.size(); vertex++)
987  // { // per vertex in the bract
988  // // now convert to a global index
989  // indexType globalID = mesh->GetGlobalIDFromMeshIndex(vertex);
990  //
991  // // look that one up and store the result (NO_SUCH_ELEMENT is acceptable, but should never occur)
992  // hierarchicalTreeID[vertex] = hierarchicalTree.FindRegularByGlobal(globalID);
993  // } // per vertex in the bract
994  // Convert the mesh ids for the contourtree nodes to global ids. This will also be our
995  // main field array for the worklet
996  auto globalIdsForBoundaryTreeMeshIndices =
997  this->Mesh->template GetGlobalIdsFromMeshIndices<vtkm::cont::ArrayHandleIndex>(
998  vtkm::cont::ArrayHandleIndex(this->ContourTree.Nodes.GetNumberOfValues()),
999  localToGlobalIdRelabeler);
1000  // Get a FindRegularByGlobal execution object that we can use as an input for worklets to call the function
1001  auto findRegularByGlobal = hierarchicalTree.GetFindRegularByGlobal();
1002  // look up our gloabl ids (NO_SUCH_ELEMENT is acceptable, but should never occur) and
1003  // copy the regular ids found from global ids in the this->HierarchicalTreeId array
1004  // NOTE: we should technically be able to just use a ArrayHandleTransrom with findRegularByGlobal and copy the values but it is not clear how to get FindRegularByGlobal to work in both the execution and control environment as ArrayHandleTransform requires ExecutionAndControlObject as base class. The implementation via a worklet is fine but could be made more elegant this way.
1005  auto listNewNodesCopyIdsWorklet =
1007  this->Invoke(listNewNodesCopyIdsWorklet,
1008  globalIdsForBoundaryTreeMeshIndices, // input global indices
1009  findRegularByGlobal, // input object to call FindRegularByGlobal
1010  this->HierarchicalTreeId);
1011 
1012  // C. Start with the list of all nodes in the non-hierarchical tree
1013  // NOTE: In contrast to the orignial code we directly initalize with iota instead of with NO_SUCH_ELEMENT first
1015  vtkm::cont::ArrayHandleIndex(this->ContourTree.Nodes.GetNumberOfValues()), this->NewNodes);
1016 
1017  // D. Copy them if they don't already have an ID set in the hierarchical tree
1018  // create an array where we can put the compressed array
1020  // prediate for deciding which nodes to keep.
1021  // NOTE: Similar to ListNewHypernodes the predicate is inverted compared
1022  // to the orginal because we here use CopyIf instead of remove_if in the original code
1023  auto notANewNodePredicate =
1025  // compress the array
1027  this->NewNodes, // compress the active superarcs
1028  this->HierarchicalTreeId, // stencil
1029  compressedNewNodes, // array where the compressed NewNodes are stored
1030  notANewNodePredicate // unary predicate for deciding which nodes are considered true
1031  );
1032  // swap in the compressed array
1033  this->NewNodes = compressedNewNodes;
1034 
1035  if (this->NewNodes.GetNumberOfValues() == 0)
1036  {
1037 #ifdef DEBUG_PRINT
1039  "TreeGrafter::ListNewNodes(): No noew nodes. Returning.");
1040 #endif
1041  return;
1042  }
1043 
1044  // E. And set their new ID for future use
1045  vtkm::Id nOldNodes = hierarchicalTree.RegularNodeGlobalIds.GetNumberOfValues();
1046  // VTKm copy can't allocate for transformed arrays, but this->HierarchicalTreeId has already been allocate earlier.
1047  auto permutedHierarchicalTreeId =
1048  vtkm::cont::make_ArrayHandlePermutation(this->NewNodes, // id array,
1049  this->HierarchicalTreeId); // value array to copy to
1050  auto tempNewHierarchicalTreeIdValues =
1051  vtkm::cont::ArrayHandleCounting<vtkm::Id>(nOldNodes, 1, this->NewNodes.GetNumberOfValues());
1053  // copy nOldNodes + newNodes
1054  tempNewHierarchicalTreeIdValues,
1055  // to hierarchicalTreeId[newNodes[newNode]]
1056  permutedHierarchicalTreeId);
1057 
1058  // WARNING: FOR NOW, we assume that we don't want to sort the regular nodes, just copy them in
1059  // We now have a list of all nodes needing transfer, and a mapping of their IDs
1060 #ifdef DEBUG_PRINT
1061  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("New Nodes Listed", __FILE__, __LINE__));
1062 #endif
1063 } // ListNewNodes()
1064 
1065 
1071 template <typename MeshType, typename FieldType>
1074 { // CopyNewHypernodes()
1075  // A. Resize the hyper arrays
1076  vtkm::Id nOldHypernodes = hierarchicalTree.Hypernodes.GetNumberOfValues();
1077  vtkm::Id nNewHypernodes = this->NewHypernodes.GetNumberOfValues();
1078  vtkm::Id totalNHypernodes = nOldHypernodes + nNewHypernodes;
1079  // Need to resize the vectors while keeping the original values. I.e., we must do a true resize.
1080  // VTKm does not provide a real resize so we need to do our own.
1081  {
1082  // Resize array to length totalNHypernodes and fill new values with NO_SUCH_ELEMENT (or 0) (while keeping original values)
1083  // NOTE: hierarchicalTree.Superchildren is initalized here but not used by this function
1084  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1085  hierarchicalTree.Hypernodes,
1086  totalNHypernodes,
1088  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1089  hierarchicalTree.Hyperarcs,
1090  totalNHypernodes,
1092  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1093  hierarchicalTree.Superchildren, totalNHypernodes, static_cast<vtkm::Id>(0));
1094  }
1095  // B. Copy in the hypernodes & hyperarcs
1096  auto copyNewHypernodesWorklet =
1098  this->Invoke(copyNewHypernodesWorklet,
1099  this->NewHypernodes, // input iteration index.
1100  this->HierarchicalSuperId, // input
1101  this->HierarchicalHyperarc, // input
1102  hierarchicalTree.Hypernodes, // output
1103  hierarchicalTree.Hyperarcs // output
1104  );
1105 
1106  // we will get the superchildren to set the size for us
1107 #ifdef DEBUG_PRINT
1108  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("New Hypernodes Copied", __FILE__, __LINE__));
1110  hierarchicalTree.DebugPrint("New Hypernodes Copied", __FILE__, __LINE__));
1111 #endif
1112 
1113 } // CopyNewHypernodes()
1114 
1115 
1127 template <typename MeshType, typename FieldType>
1130  vtkm::Id theRound)
1131 { // CopyNewSupernodes()
1132  // A. Resize the relevant arrays
1133  vtkm::Id nOldSupernodes = hierarchicalTree.Supernodes.GetNumberOfValues();
1134  vtkm::Id nNewSupernodes = this->NewSupernodes.GetNumberOfValues();
1135  vtkm::Id totalNSupernodes = nOldSupernodes + nNewSupernodes;
1136  // Resize array to length totalNHypernodes and fill new values with NO_SUCH_ELEMENT (while keeping original values)
1137  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1138  hierarchicalTree.Supernodes,
1139  totalNSupernodes,
1141  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1142  hierarchicalTree.Superarcs,
1143  totalNSupernodes,
1145  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1146  hierarchicalTree.Hyperparents,
1147  totalNSupernodes,
1149  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1150  hierarchicalTree.Super2Hypernode,
1151  totalNSupernodes,
1153  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1154  hierarchicalTree.WhichRound,
1155  totalNSupernodes,
1157  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1158  hierarchicalTree.WhichIteration,
1159  totalNSupernodes,
1161 
1162  // we will need this here, since we need to set some new superparents here for supernodes added
1163  vtkm::Id nOldNodes = hierarchicalTree.RegularNodeGlobalIds.GetNumberOfValues();
1164  vtkm::Id nNewNodes = this->NewNodes.GetNumberOfValues();
1165  vtkm::Id totalNNodes = nOldNodes + nNewNodes;
1166  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1167  hierarchicalTree.Superparents,
1168  totalNNodes,
1170 
1171  // B. Copy in the supernodes, &c.
1172  auto copyNewSupernodesWorklet =
1174  nOldSupernodes);
1175  this->Invoke(copyNewSupernodesWorklet,
1176  this->NewSupernodes, // input and iteration index
1177  this->ContourTree.Supernodes, // input
1178  this->Mesh->SortOrder, // input
1179  this->HierarchicalTreeId, // input
1180  this->WhenTransferred, // input
1181  this->HierarchicalSuperparent, // input
1182  this->HierarchicalHyperparent, // input
1183  this->HierarchicalSuperId, // input
1184  this->HierarchicalHyperId, // input
1185  this->HierarchicalHyperarc, // input
1186  hierarchicalTree.Supernodes, // output
1187  hierarchicalTree.WhichRound, // output
1188  hierarchicalTree.WhichIteration, // output
1189  hierarchicalTree.Superarcs, // output
1190  this->HierarchicalRegularId, // input/output
1191  hierarchicalTree.Hyperparents, // input/output
1192  hierarchicalTree.Superparents // input/output
1193  );
1194 
1195  // loop to set the number of superchildren per hyperarc
1196  auto copyNewSupernodesSetSuperchildrenWorklet =
1198  hierarchicalTree.Supernodes.GetNumberOfValues());
1199  auto newSupernodesIndex = vtkm::cont::ArrayHandleIndex(this->NewSupernodes.GetNumberOfValues());
1200  this->Invoke(
1201  copyNewSupernodesSetSuperchildrenWorklet,
1202  newSupernodesIndex, // input array starting at 0 to NewSupernodes.GetNumberOfValues();
1203  hierarchicalTree.Superarcs, //input
1204  hierarchicalTree.Hyperparents, // input
1205  hierarchicalTree.Hypernodes, //input
1206  hierarchicalTree.Superchildren // output
1207  );
1208 
1209  // now loop through the hypernodes to set their lookup index from supernodes. What we are doing here is the following:
1210  // for (indexType newHypernode = hierarchicalTree.hypernodes.size() - newHypernodes.size(); newHypernode < hierarchicalTree.hypernodes.size(); newHypernode++)
1211  // hierarchicalTree.super2hypernode[hierarchicalTree.hypernodes[newHypernode]] = newHypernode;
1212  vtkm::Id startHypernodeIndex =
1213  hierarchicalTree.Hypernodes.GetNumberOfValues() - this->NewHypernodes.GetNumberOfValues();
1214  auto newHypernodeIndex = vtkm::cont::ArrayHandleCounting<vtkm::Id>(
1215  startHypernodeIndex, // start index
1216  1, // increment
1217  hierarchicalTree.Hypernodes.GetNumberOfValues() - startHypernodeIndex // number of values
1218  );
1219  auto permutedHypernodes =
1220  vtkm::cont::make_ArrayHandlePermutation(newHypernodeIndex, hierarchicalTree.Hypernodes);
1221  auto permutedSuper2hypernode =
1222  vtkm::cont::make_ArrayHandlePermutation(permutedHypernodes, hierarchicalTree.Super2Hypernode);
1223  if (newHypernodeIndex.GetNumberOfValues())
1224  { // TODO/FIXME: Can we detect this earlier and save computation time?
1225  vtkm::cont::Algorithm::Copy(newHypernodeIndex, permutedSuper2hypernode);
1226  }
1227 
1228 #ifdef DEBUG_PRINT
1229  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("New Supernodes Copied", __FILE__, __LINE__));
1231  hierarchicalTree.DebugPrint("New Supernodes Copied", __FILE__, __LINE__));
1232 #endif
1233 } // CopyNewSupernodes()
1234 
1235 
1236 
1247 template <typename MeshType, typename FieldType>
1248 template <typename StorageTag>
1251  const vtkm::cont::ArrayHandle<FieldType, StorageTag>& meshDataValues,
1252  const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler* localToGlobalIdRelabeler)
1253 { // CopyNewNodes()
1254  // A. We resize the hierarchy to fit
1255  vtkm::Id nOldNodes = hierarchicalTree.RegularNodeGlobalIds.GetNumberOfValues();
1256  vtkm::Id nNewNodes = this->NewNodes.GetNumberOfValues();
1257  vtkm::Id totalNNodes = nOldNodes + nNewNodes;
1258 
1259  // A. We start by finding & copying the global IDs for every regular node
1260  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1261  hierarchicalTree.RegularNodeGlobalIds,
1262  totalNNodes,
1264  // NOTE: The original code created a separate array newNodesGloablId that was set
1265  // to NO_SUCH_ELEMENT first but we should only need the fancy array here and save the memory
1266  auto newNodesGloablId =
1267  this->Mesh
1268  ->template GetGlobalIdsFromMeshIndices<vtkm::worklet::contourtree_augmented::IdArrayType>(
1269  this->NewNodes, localToGlobalIdRelabeler); // this is a fancy array
1271  newNodesGloablId, // array to copy
1272  0, // start index
1273  newNodesGloablId.GetNumberOfValues(), // number of values to copy (we need the whole array)
1274  hierarchicalTree.RegularNodeGlobalIds, // array to copy to
1275  nOldNodes // index where to start copying values to
1276  );
1277 
1278 #ifdef DEBUG_PRINT
1279  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Global IDs Copied", __FILE__, __LINE__));
1281  hierarchicalTree.DebugPrint("Global IDs Copied", __FILE__, __LINE__));
1282 #endif
1283 
1284  // B. Next, we transfer the data values
1285  hierarchicalTree.DataValues.Allocate(totalNNodes, vtkm::CopyFlag::On);
1286 
1287  auto meshValuesPermuted = vtkm::cont::make_ArrayHandlePermutation(this->NewNodes, meshDataValues);
1288  // copy all of mesh->DataValue(newNodes[newNode]) to the end of hierarchicalTree.DataValues starting at nOldNodes
1289  vtkm::cont::Algorithm::CopySubRange(meshValuesPermuted,
1290  0,
1291  meshValuesPermuted.GetNumberOfValues(),
1292  hierarchicalTree.DataValues,
1293  nOldNodes);
1294 
1295 #ifdef DEBUG_PRINT
1296  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Data Values Copied", __FILE__, __LINE__));
1298  hierarchicalTree.DebugPrint("Data Values Copied", __FILE__, __LINE__));
1299 #endif
1300 
1301  // C. Then we add the new array indices to the sort and resort it
1302  // Resize and initialize hierarchicalTree.RegularNodeSortOrder with NO_SUCH_ELEMENT
1303  // TODO: We should be able to shortcut this since the last values are set next in the CopySubrange
1304  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1305  hierarchicalTree.RegularNodeSortOrder,
1306  totalNNodes,
1308  {
1309  // Do the following: std::iota(hierarchicalTree.regularNodeSortOrder.begin() + nOldNodes, hierarchicalTree.regularNodeSortOrder.end(), nOldNodes);
1310  auto tempCountingArray = vtkm::cont::ArrayHandleCounting<vtkm::Id>(
1311  nOldNodes, 1, hierarchicalTree.RegularNodeSortOrder.GetNumberOfValues() - nOldNodes);
1312  vtkm::cont::Algorithm::CopySubRange(tempCountingArray,
1313  0,
1314  tempCountingArray.GetNumberOfValues(),
1315  hierarchicalTree.RegularNodeSortOrder,
1316  nOldNodes);
1317  }
1318  {
1319  auto permuteComparator =
1321  hierarchicalTree.RegularNodeGlobalIds);
1322  vtkm::cont::Algorithm::Sort(hierarchicalTree.RegularNodeSortOrder, permuteComparator);
1323  }
1324 #ifdef DEBUG_PRINT
1325  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("Sort Order Reset", __FILE__, __LINE__));
1327  hierarchicalTree.DebugPrint("Sort Order Reset", __FILE__, __LINE__));
1328  // hierarchicalTree.PrintDotSuperStructure("CopyNewNodes Hierarchical Tree");
1329 #endif
1330 
1331  // D. now loop through the supernodes to set their lookup index from regular IDs
1332  // Resize and initialize hierarchicalTree.Regular2Supernode with NO_SUCH_ELEMENT
1333  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1334  hierarchicalTree.Regular2Supernode,
1335  totalNNodes,
1337  {
1338  // The code in this block does the following in serial
1339  // for (indexType newSupernode = hierarchicalTree.supernodes.size() - newSupernodes.size(); newSupernode < hierarchicalTree.supernodes.size(); newSupernode++)
1340  // hierarchicalTree.regular2supernode[hierarchicalTree.supernodes[newSupernode]] = newSupernode;
1341  vtkm::Id tempStartIndex =
1342  hierarchicalTree.Supernodes.GetNumberOfValues() - this->NewSupernodes.GetNumberOfValues();
1343  vtkm::Id tempNumValues = hierarchicalTree.Supernodes.GetNumberOfValues() - tempStartIndex;
1344  auto tempNewSupernodeIndex = vtkm::cont::ArrayHandleCounting<vtkm::Id>(
1345  tempStartIndex, 1, tempNumValues); // start, step, count
1346  auto regular2SupernodePermuted = vtkm::cont::make_ArrayHandlePermutation(
1347  vtkm::cont::make_ArrayHandlePermutation(tempNewSupernodeIndex, hierarchicalTree.Supernodes),
1348  hierarchicalTree.Regular2Supernode);
1349  if (tempNewSupernodeIndex.GetNumberOfValues())
1350  { // TODO/FIXME: Can we detect this earlier and save computation time?
1351  vtkm::cont::Algorithm::Copy(tempNewSupernodeIndex, regular2SupernodePermuted);
1352  }
1353  }
1354 
1355  // E. Now we sort out the superparents
1356  auto copyNewNodesSetSuperparentsWorklet =
1358  nOldNodes);
1359  auto findSuperArcForUnknownNode = hierarchicalTree.GetFindSuperArcForUnknownNode();
1360  this->Invoke(copyNewNodesSetSuperparentsWorklet,
1361  this->NewNodes, // input and iteration index
1362  this->Mesh->SortIndices, // input
1363  this->Mesh->SortOrder, // input
1364  this->ContourTree.Superparents, // input
1365  this->ContourTree.Superarcs, // input
1366  this->ContourTree.Supernodes, // input
1367  this->HierarchicalRegularId, // input
1368  this->HierarchicalTreeId, // input
1369  hierarchicalTree.RegularNodeGlobalIds, // input
1370  hierarchicalTree.DataValues, // input
1371  findSuperArcForUnknownNode, // input
1372  hierarchicalTree.Superparents // output
1373  );
1374 
1375 #ifdef DEBUG_PRINT
1376  VTKM_LOG_S(vtkm::cont::LogLevel::Info, DebugPrint("New Nodes Copied", __FILE__, __LINE__));
1378  hierarchicalTree.DebugPrint("New Nodes Copied", __FILE__, __LINE__));
1379 #endif
1380 
1381 } // CopyNewNodes()
1382 
1383 
1393 template <typename MeshType, typename FieldType>
1396  vtkm::Id theRound)
1397 { // CopyIterationDetails()
1398 
1399 #ifdef DEBUG_PRINT
1401  hierarchicalTree.DebugPrint("Starting CopyIterationDetails()", __FILE__, __LINE__));
1402 #endif
1403 
1404  // update the round counts
1406  theRound, this->NewNodes.GetNumberOfValues(), hierarchicalTree.NumRegularNodesInRound);
1408  theRound, this->NewSupernodes.GetNumberOfValues(), hierarchicalTree.NumSupernodesInRound);
1410  theRound, this->NewHypernodes.GetNumberOfValues(), hierarchicalTree.NumHypernodesInRound);
1411  // last iteration is just setting attachment points (but we are including this now) (previously added -1)
1413  theRound, this->NumTransferIterations, hierarchicalTree.NumIterations);
1414 
1415 #ifdef DEBUG_PRINT
1417  hierarchicalTree.DebugPrint("Round Counts Updated", __FILE__, __LINE__));
1418 #endif
1419 
1420  // calculate the number of old & total super and hyper nodes
1421  vtkm::Id nTotalSupernodes = hierarchicalTree.Supernodes.GetNumberOfValues();
1422  vtkm::Id nNewSupernodes = this->NewSupernodes.GetNumberOfValues();
1423  vtkm::Id nOldSupernodes = nTotalSupernodes - nNewSupernodes;
1424  vtkm::Id nTotalHypernodes = hierarchicalTree.Hypernodes.GetNumberOfValues();
1425  vtkm::Id nNewHypernodes = this->NewHypernodes.GetNumberOfValues();
1426  vtkm::Id nOldHypernodes = nTotalHypernodes - nNewHypernodes;
1427 
1428 #ifdef DEBUG_PRINT
1430  hierarchicalTree.DebugPrint("Node Counts Retrieved", __FILE__, __LINE__));
1432  DebugPrint("About to Transfer Iteration Counts", __FILE__, __LINE__));
1433 #endif
1434 
1435  // and set the per round iteration counts. There may be smarter ways of doing this, but . . .
1436  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1437  hierarchicalTree.FirstSupernodePerIteration[static_cast<std::size_t>(theRound)],
1438  this->NumTransferIterations + 1,
1440  {
1441  auto copyFirstSupernodePerIterationWorklet =
1443  nOldSupernodes);
1444  auto newSupernodeIndex = vtkm::cont::ArrayHandleCounting<vtkm::Id>(
1445  nOldSupernodes, 1, nTotalSupernodes - nOldSupernodes); // fancy iteration index
1446  this->Invoke(
1447  copyFirstSupernodePerIterationWorklet,
1448  newSupernodeIndex, // input fancy iteration index
1449  hierarchicalTree.WhichIteration, // input
1450  hierarchicalTree.FirstSupernodePerIteration[static_cast<std::size_t>(theRound)] // output.
1451  );
1452 
1453  // force the extra one to be one-off-the end for safety
1455  this->NumTransferIterations, // index to set
1456  hierarchicalTree.Supernodes.GetNumberOfValues(), // value to set
1457  hierarchicalTree.FirstSupernodePerIteration[theRound] // array to modify
1458  );
1459  }
1460 
1461 #ifdef DEBUG_PRINT_GRAFT_RESIDUE
1463  hierarchicalTree.DebugPrint("Supernode Iteration Counts Set", __FILE__, __LINE__));
1464 #endif
1465 
1466  // we add one so we don't need special cases when establishing subranges
1467  // There's a tricky case to be dealt with due to attachment points - the last (extra) iteration transfers supernodes
1468  // with a "virtual" superarc but no hyperarc. This can only occur in the final iteration, in which case the correct value is
1469  // the "off the end" sentinel. But it is also possible for there to be no attachment points, in which case the final iteration
1470  // will have some other value. Also, we need to set the "off the end" for the extra entry in any event.
1471  // THEREFORE, instead of instantiating to NO_SUCH_ELEMENT for safety, we instantiate to the hypernodes.size()
1472  vtkm::worklet::contourtree_augmented::ResizeVector<vtkm::Id>(
1473  hierarchicalTree.FirstHypernodePerIteration[static_cast<std::size_t>(theRound)],
1474  this->NumTransferIterations + 1,
1475  hierarchicalTree.Hypernodes.GetNumberOfValues());
1476  // copy the approbriat hierarchicalTree.FirstHypernodePerIteration values
1477  {
1478  auto copyFirstHypernodePerIterationWorklet =
1480  nOldHypernodes);
1481  auto newHypernodeIndex = vtkm::cont::ArrayHandleCounting<vtkm::Id>(
1482  nOldHypernodes, 1, nTotalHypernodes - nOldHypernodes); // fancy iteration index
1483  this->Invoke(
1484  copyFirstHypernodePerIterationWorklet,
1485  newHypernodeIndex, // input fancy iteration index
1486  hierarchicalTree.Hypernodes, // input
1487  hierarchicalTree.WhichIteration, //input
1488  hierarchicalTree.FirstHypernodePerIteration[static_cast<std::size_t>(theRound)] //output
1489  );
1490  }
1491 
1492 #ifdef DEBUG_PRINT
1494  hierarchicalTree.DebugPrint("Hypernode Iteration Counts Set", __FILE__, __LINE__));
1496  DebugPrint("Iteration Details Copied", __FILE__, __LINE__));
1497 #endif
1498 
1499 } // CopyIterationDetails()
1500 
1501 
1502 // debug routine
1503 template <typename MeshType, typename FieldType>
1504 inline std::string TreeGrafter<MeshType, FieldType>::DebugPrint(const char* message,
1505  const char* fileName,
1506  long lineNum)
1507 { // DebugPrint
1508  std::stringstream resultStream;
1509  resultStream << std::endl;
1510  resultStream << "[CUTHERE]---------------------------------------------" << std::endl;
1511  resultStream << std::setw(30) << std::left << fileName << ":" << std::right << std::setw(4)
1512  << lineNum << " ";
1513  resultStream << std::left << std::string(message) << std::endl;
1514 
1515  resultStream << "------------------------------------------------------" << std::endl;
1516  resultStream << "Tree Grafter Contains: " << std::endl;
1517  resultStream << "------------------------------------------------------" << std::endl;
1518 
1519  // Regular Vertex Arrays
1520  vtkm::worklet::contourtree_augmented::PrintHeader(this->HierarchicalTreeId.GetNumberOfValues(),
1521  resultStream);
1523  "ID in Hierarchical Tree", this->HierarchicalTreeId, -1, resultStream);
1524  resultStream << std::endl;
1525 
1526  // Per Supernode Arrays
1527  vtkm::worklet::contourtree_augmented::PrintHeader(this->HierarchicalRegularId.GetNumberOfValues(),
1528  resultStream);
1530  "Hierarchical Regular ID", this->HierarchicalRegularId, -1, resultStream);
1532  "Hierarchical Superparent", this->HierarchicalSuperparent, -1, resultStream);
1534  "Hierarchical Super ID", this->HierarchicalSuperId, -1, resultStream);
1536  "Hierarchical Hyperparent", this->HierarchicalHyperparent, -1, resultStream);
1538  "Hierarchical Hyper ID", this->HierarchicalHyperId, -1, resultStream);
1540  "Hierarchical Hyperarc", this->HierarchicalHyperarc, -1, resultStream);
1542  "When Transferred", this->WhenTransferred, -1, resultStream);
1544  "Supernode Type", this->SupernodeType, -1, resultStream);
1546  "Up Neighbour", this->UpNeighbour, -1, resultStream);
1548  "Down Neighbour", this->DownNeighbour, -1, resultStream);
1549  resultStream << std::endl;
1550 
1551  // Active Supernode Arrays
1552  vtkm::worklet::contourtree_augmented::PrintHeader(this->ActiveSuperarcs.GetNumberOfValues(),
1553  resultStream);
1555  "Active Superarcs", this->ActiveSuperarcs, -1, resultStream);
1556 
1557  // Arrays for transfer to hierarchical tree
1558  vtkm::worklet::contourtree_augmented::PrintHeader(this->NewHypernodes.GetNumberOfValues(),
1559  resultStream);
1561  "New Hypernodes", this->NewHypernodes, -1, resultStream);
1562 
1563  vtkm::worklet::contourtree_augmented::PrintHeader(this->NewSupernodes.GetNumberOfValues(),
1564  resultStream);
1566  "New Supernodes", this->NewSupernodes, -1, resultStream);
1567 
1568  vtkm::worklet::contourtree_augmented::PrintHeader(this->NewNodes.GetNumberOfValues(),
1569  resultStream);
1570  vtkm::worklet::contourtree_augmented::PrintIndices("New Nodes", this->NewNodes, -1, resultStream);
1571 
1572  resultStream << "------------------------------------------------------" << std::endl;
1573  resultStream << std::endl;
1574 
1575  resultStream << std::flush;
1576  return resultStream.str();
1577 } // DebugPrint
1578 
1579 
1580 } // namespace contourtree_distributed
1581 } // namespace worklet
1582 } // namespace vtkm
1583 
1584 #endif
vtkm::worklet::contourtree_distributed::tree_grafter::FindCriticalPointsFindLeafsWorklet
Definition: FindCriticalPointsFindLeafsWorklet.h:70
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::Supernodes
vtkm::worklet::contourtree_augmented::IdArrayType Supernodes
Definition: HierarchicalContourTree.h:124
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::Superparents
vtkm::worklet::contourtree_augmented::IdArrayType Superparents
Definition: HierarchicalContourTree.h:120
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::worklet::contourtree_distributed::HierarchicalContourTree::Superarcs
vtkm::worklet::contourtree_augmented::IdArrayType Superarcs
Definition: HierarchicalContourTree.h:126
vtkm::cont::ArrayHandle< vtkm::Id >
vtkm::worklet::contourtree_distributed::TreeGrafter::ListNewSupernodes
void ListNewSupernodes(vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree)
Makes a list of new supernodes, and maps their old IDs to their new ones.
Definition: TreeGrafter.h:902
vtkm::worklet::contourtree_distributed::TreeGrafter::FindCriticalPoints
void FindCriticalPoints()
find the critical points in what's left
Definition: TreeGrafter.h:630
vtkm::worklet::contourtree_distributed::TreeGrafter::Mesh
MeshType * Mesh
Definition: TreeGrafter.h:112
vtkm::cont::Algorithm::ScanInclusive
static VTKM_CONT T ScanInclusive(vtkm::cont::DeviceAdapterId devId, const vtkm::cont::ArrayHandle< T, CIn > &input, vtkm::cont::ArrayHandle< T, COut > &output)
Definition: Algorithm.h:731
CopyNewSupernodesWorklet.h
vtkm::worklet::contourtree_distributed::TreeGrafter::NewSupernodes
vtkm::worklet::contourtree_augmented::IdArrayType NewSupernodes
Definition: TreeGrafter.h:149
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::worklet::contourtree_distributed::TreeGrafter::DebugPrint
std::string DebugPrint(const char *message, const char *fileName, long lineNum)
prints the contents of the object in a standard format
Definition: TreeGrafter.h:1504
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::WhichRound
vtkm::worklet::contourtree_augmented::IdArrayType WhichRound
Definition: HierarchicalContourTree.h:135
HierarchicalContourTree.h
Types.h
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_augmented::ContourTree
Definition: augmented/ContourTree.h:106
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
ListNewNodesCopyIdsWorklet.h
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::DebugPrint
VTKM_CONT std::string DebugPrint(std::string message, const char *fileName, long lineNum) const
debug routine
Definition: HierarchicalContourTree.h:785
vtkm::worklet::contourtree_distributed::TreeGrafter::UpNeighbour
vtkm::worklet::contourtree_augmented::IdArrayType UpNeighbour
Definition: TreeGrafter.h:141
FindCriticalPointsFindSaddlesWorklet.h
vtkm::worklet::contourtree_distributed::InteriorForest
The contour tree of a data block restricted to the interior of a data block.
Definition: InteriorForest.h:84
vtkm::worklet::contourtree_distributed::tree_grafter::HyperNodeWhenComparator
Definition: HyperNodeWhenComparator.h:112
InitActiceSuperarcsWorklet.h
vtkm::worklet::contourtree_distributed::tree_grafter::FindCriticalPointsFindSaddlesWorklet
Definition: FindCriticalPointsFindSaddlesWorklet.h:70
vtkm::worklet::contourtree_distributed::TreeGrafter::NewNodes
vtkm::worklet::contourtree_augmented::IdArrayType NewNodes
Definition: TreeGrafter.h:148
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::TreeGrafter::Invoke
vtkm::cont::Invoker Invoke
Used internally to Invoke worklets.
Definition: TreeGrafter.h:270
vtkm::worklet::contourtree_distributed::TreeGrafter::CopyIterationDetails
void CopyIterationDetails(vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree, vtkm::Id theRound)
Transfers the details of nodes used in each iteration.
Definition: TreeGrafter.h:1394
FindCriticalPointsSetUpDownNeighboursWorklet.h
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::worklet::contourtree_distributed::tree_grafter::NewNodePredicate
Definition: NewNodePredicate.h:68
InitActiceSuperarcIdWorklet.h
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
vtkm::worklet::contourtree_distributed::tree_grafter::CalculateAttachementCounterWorklet
Definition: CalculateAttachementCounterWorklet.h:70
vtkm::worklet::contourtree_distributed::TreeGrafter::GraftInteriorForests
void GraftInteriorForests(vtkm::Id theRound, vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree, const vtkm::cont::ArrayHandle< FieldType, StorageTag > &meshDataValues, const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler *localToGlobalIdRelabeler=nullptr)
routine to graft the InteriorForest residue from the BoundaryTree computation into the tree.
Definition: TreeGrafter.h:277
PrintVectors.h
vtkm::worklet::contourtree_distributed::tree_grafter::IdentifyLeafHyperarcsWorklet
Worklet implementing the TreeGrafter.IdentifyLeafHyperarcs function.
Definition: IdentifyLeafHyperarcsWorklet.h:85
vtkm::worklet::contourtree_distributed::TreeGrafter::InitializeActiveSuperarcs
void InitializeActiveSuperarcs()
sets up an active superarc set
Definition: TreeGrafter.h:531
vtkm::worklet::contourtree_distributed::InteriorForest::IsNecessary
vtkm::worklet::contourtree_augmented::IdArrayType IsNecessary
Definition: InteriorForest.h:91
PermuteComparator.h
vtkm::worklet::contourtree_distributed::TreeGrafter::HierarchicalHyperId
vtkm::worklet::contourtree_augmented::IdArrayType HierarchicalHyperId
Definition: TreeGrafter.h:132
vtkm::worklet::contourtree_distributed::tree_grafter::CopyFirstHypernodePerIterationWorklet
Worklet implementing the copy of the first supernode per iteration in TreeGrafter::CopyIterationDetai...
Definition: CopyFirstHypernodePerIterationWorklet.h:70
vtkm::worklet::contourtree_distributed::tree_grafter::SuperNodeWhenComparator
Definition: SuperNodeWhenComparator.h:165
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::GetFindRegularByGlobal
VTKM_CONT FindRegularByGlobal GetFindRegularByGlobal() const
routine to create a FindRegularByGlobal object that we can use as an input for worklets to call the f...
Definition: HierarchicalContourTree.h:174
vtkm::Id
vtkm::Int32 Id
Represents an ID (index into arrays).
Definition: Types.h:191
vtkm::worklet::contourtree_distributed::TreeGrafter::HierarchicalSuperId
vtkm::worklet::contourtree_augmented::IdArrayType HierarchicalSuperId
Definition: TreeGrafter.h:128
SuperNodeWhenComparator.h
vtkm::worklet::contourtree_distributed::tree_grafter::CopyNewHypernodesWorklet
Definition: CopyNewHypernodesWorklet.h:70
vtkm::worklet::contourtree_distributed::TreeGrafter::HierarchicalHyperparent
vtkm::worklet::contourtree_augmented::IdArrayType HierarchicalHyperparent
Definition: TreeGrafter.h:134
vtkm::worklet::contourtree_distributed::tree_grafter::ListNewNodesCopyIdsWorklet
Definition: ListNewNodesCopyIdsWorklet.h:69
HyperNodeWhenComparator.h
vtkm::worklet::contourtree_distributed::TreeGrafter::HierarchicalHyperarc
vtkm::worklet::contourtree_augmented::IdArrayType HierarchicalHyperarc
Definition: TreeGrafter.h:136
CopyNewHypernodesWorklet.h
NewHypernodePredicate.h
vtkm::Add
Definition: Types.h:222
vtkm::worklet::contourtree_distributed::TreeGrafter::HierarchicalTreeId
vtkm::worklet::contourtree_augmented::IdArrayType HierarchicalTreeId
Definition: TreeGrafter.h:117
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::RegularNodeGlobalIds
vtkm::worklet::contourtree_augmented::IdArrayType RegularNodeGlobalIds
Definition: HierarchicalContourTree.h:108
vtkm::worklet::contourtree_distributed::TreeGrafter::CopyNewSupernodes
void CopyNewSupernodes(vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree, vtkm::Id theRound)
Copies in the supernodes, now that we have correct regular IDs.
Definition: TreeGrafter.h:1128
vtkm::worklet::contourtree_distributed::TreeGrafter::CopyNewHypernodes
void CopyNewHypernodes(vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree)
Copies in the hypernodes, now that we have correct super IDs.
Definition: TreeGrafter.h:1072
vtkm::worklet::contourtree_distributed::TreeGrafter::IdentifyLeafHyperarcs
void IdentifyLeafHyperarcs()
routine to identify one iteration worth of leaves
Definition: TreeGrafter.h:760
vtkm::cont::LogLevel::Info
@ Info
Information messages (detected hardware, etc) and temporary debugging output.
vtkm::worklet::contourtree_distributed::tree_grafter::InitActiceSuperarcsWorklet
Definition: InitActiceSuperarcsWorklet.h:69
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::Hyperparents
vtkm::worklet::contourtree_augmented::IdArrayType Hyperparents
Definition: HierarchicalContourTree.h:128
vtkm::worklet::contourtree_distributed::TreeGrafter::SupernodeType
vtkm::worklet::contourtree_augmented::IdArrayType SupernodeType
Definition: TreeGrafter.h:120
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::FirstSupernodePerIteration
std::vector< vtkm::worklet::contourtree_augmented::IdArrayType > FirstSupernodePerIteration
vectors tracking the segments used in each iteration of the hypersweep
Definition: HierarchicalContourTree.h:169
FindCriticalPointsFindTerminalElementsWorklet.h
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::Superchildren
vtkm::worklet::contourtree_augmented::IdArrayType Superchildren
Definition: HierarchicalContourTree.h:145
vtkm::worklet::contourtree_distributed::tree_grafter::CopyNewSupernodesSetSuperchildrenWorklet
Worklet to loop to set the number of superchildren per hyperarc as part of TreeGrafter::CopyNewSupern...
Definition: CopyNewSupernodesSetSuperchildrenWorklet.h:70
CopyNewSupernodesSetSuperchildrenWorklet.h
vtkm::worklet::contourtree_distributed::TreeGrafter::DownNeighbour
vtkm::worklet::contourtree_augmented::IdArrayType DownNeighbour
Definition: TreeGrafter.h:142
IdentifyLeafHyperarcsWorklet.h
vtkm::cont::ArrayHandleCounting< vtkm::Id >
CopyNewNodesSetSuperparentsWorklet.h
vtkm::cont::Invoker
Allows launching any worklet without a dispatcher.
Definition: Invoker.h:41
vtkm::worklet::contourtree_distributed::TreeGrafter::WhenTransferred
vtkm::worklet::contourtree_augmented::IdArrayType WhenTransferred
Definition: TreeGrafter.h:138
InteriorForest.h
vtkm::worklet::contourtree_distributed::TreeGrafter::CopyNewNodes
void CopyNewNodes(vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree, const vtkm::cont::ArrayHandle< FieldType, StorageTag > &meshDataValues, const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler *localToGlobalIdRelabeler=nullptr)
Copies the regular nodes in, setting all arrays except superparents Must be called LAST since it depe...
Definition: TreeGrafter.h:1249
vtkm::worklet::contourtree_distributed::InteriorForest::DebugPrint
std::string DebugPrint(const char *message, const char *fileName, long lineNum) const
Definition: InteriorForest.h:126
vtkm::worklet::contourtree_distributed::TreeGrafter::CollapseRegularChains
void CollapseRegularChains()
pointer-double to collapse chains
Definition: TreeGrafter.h:722
vtkm::worklet::contourtree_distributed::TreeGrafter::ListNewNodes
void ListNewNodes(vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree, const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler *localToGlobalIdRelabeler=nullptr)
Makes a list of new nodes, and maps their old IDs to their new ones.
Definition: TreeGrafter.h:971
vtkm::worklet::contourtree_distributed::TreeGrafter::HierarchicalRegularId
vtkm::worklet::contourtree_augmented::IdArrayType HierarchicalRegularId
Definition: TreeGrafter.h:126
vtkm::worklet::contourtree_distributed::TreeGrafter
Graft the InteriorForest (i.e., the residue of a BRACT) onto a hierarchical tree.
Definition: TreeGrafter.h:108
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::TreeGrafter::InteriorForest
vtkm::worklet::contourtree_distributed::InteriorForest * InteriorForest
Definition: TreeGrafter.h:114
Types.h
CollapseRegularChainsWorklet.h
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::WhichIteration
vtkm::worklet::contourtree_augmented::IdArrayType WhichIteration
Definition: HierarchicalContourTree.h:136
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::Hypernodes
vtkm::worklet::contourtree_augmented::IdArrayType Hypernodes
Definition: HierarchicalContourTree.h:140
vtkm::worklet::contourtree_distributed::tree_grafter::GetHierarchicalIdsWorklet
Definition: GetHierarchicalIdsWorklet.h:69
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::NumHypernodesInRound
vtkm::worklet::contourtree_augmented::IdArrayType NumHypernodesInRound
Definition: HierarchicalContourTree.h:161
CopyFirstHypernodePerIterationWorklet.h
vtkm::worklet::contourtree_distributed::TreeGrafter::NewSupernodeId
vtkm::worklet::contourtree_augmented::IdArrayType NewSupernodeId
Definition: TreeGrafter.h:123
vtkm::CopyFlag::On
@ On
CopyFirstSupernodePerIterationWorklet.h
GetHierarchicalIdsWorklet.h
vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler
A utility class that converts Ids from local to global given a mesh.
Definition: IdRelabeler.h:79
VTKM_LOG_S
#define VTKM_LOG_S(level,...)
Writes a message using stream syntax to the indicated log level.
Definition: Logging.h:261
vtkm::worklet::contourtree_distributed::tree_grafter::InitActiceSuperarcIdWorklet
Definition: InitActiceSuperarcIdWorklet.h:69
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::HierarchicalContourTree::Hyperarcs
vtkm::worklet::contourtree_augmented::IdArrayType Hyperarcs
Definition: HierarchicalContourTree.h:142
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::DataValues
vtkm::cont::ArrayHandle< FieldType > DataValues
Definition: HierarchicalContourTree.h:110
vtkm::worklet::contourtree_distributed::TreeGrafter::GetHierarchicalIds
void GetHierarchicalIds(vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree, const vtkm::cont::ArrayHandle< FieldType, StorageTag > &meshDataValues, const vtkm::worklet::contourtree_augmented::mesh_dem::IdRelabeler *localToGlobalIdRelabeler=nullptr)
Routine to convert supernode IDs from global to IDs in the existing hierarchical tree.
Definition: TreeGrafter.h:434
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::Super2Hypernode
vtkm::worklet::contourtree_augmented::IdArrayType Super2Hypernode
Definition: HierarchicalContourTree.h:131
vtkm::cont::Algorithm::Reduce
static VTKM_CONT U Reduce(vtkm::cont::DeviceAdapterId devId, const vtkm::cont::ArrayHandle< T, CIn > &input, U initialValue)
Definition: Algorithm.h:656
vtkm::worklet::contourtree_distributed::tree_grafter::CopyNewSupernodesWorklet
Definition: CopyNewSupernodesWorklet.h:70
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::Regular2Supernode
vtkm::worklet::contourtree_augmented::IdArrayType Regular2Supernode
Definition: HierarchicalContourTree.h:118
vtkm::worklet::contourtree_distributed::TreeGrafter::ContourTree
vtkm::worklet::contourtree_augmented::ContourTree & ContourTree
Definition: TreeGrafter.h:113
vtkm::worklet::contourtree_distributed::tree_grafter::CollapseRegularChainsWorklet
Definition: CollapseRegularChainsWorklet.h:70
vtkm::worklet::contourtree_distributed::TreeGrafter::HierarchicalSuperparent
vtkm::worklet::contourtree_augmented::IdArrayType HierarchicalSuperparent
Definition: TreeGrafter.h:130
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::TreeGrafter::ActiveSuperarcs
vtkm::worklet::contourtree_augmented::EdgePairArray ActiveSuperarcs
Definition: TreeGrafter.h:145
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::GetFindSuperArcForUnknownNode
VTKM_CONT FindSuperArcForUnknownNode< FieldType > GetFindSuperArcForUnknownNode()
routine to create a FindSuperArcForUnknownNode object that we can use as an input for worklets to cal...
Definition: HierarchicalContourTree.h:181
SuperarcWasNotTransferredPredicate.h
GraftInteriorForestsSetTransferIterationWorklet.h
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::TreeGrafter::NumTransferIterations
vtkm::Id NumTransferIterations
Definition: TreeGrafter.h:153
NewNodePredicate.h
vtkm::worklet::contourtree_distributed::TreeGrafter::ListNewHypernodes
void ListNewHypernodes(vtkm::worklet::contourtree_distributed::HierarchicalContourTree< FieldType > &hierarchicalTree)
Makes a list of new hypernodes, and maps their old IDs to their new ones.
Definition: TreeGrafter.h:839
vtkm::worklet::contourtree_distributed::tree_grafter::PermuteComparator
Definition: tree_grafter/PermuteComparator.h:114
vtkm::worklet::contourtree_distributed::TreeGrafter::CompressActiveArrays
void CompressActiveArrays()
Definition: TreeGrafter.h:806
ContourTree.h
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::FirstHypernodePerIteration
std::vector< vtkm::worklet::contourtree_augmented::IdArrayType > FirstHypernodePerIteration
Definition: HierarchicalContourTree.h:170
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::NumIterations
vtkm::worklet::contourtree_augmented::IdArrayType NumIterations
how many iterations needed for the hypersweep at each level
Definition: HierarchicalContourTree.h:164
CalculateAttachementCounterWorklet.h
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::HierarchicalContourTree::NumRegularNodesInRound
vtkm::worklet::contourtree_augmented::IdArrayType NumRegularNodesInRound
arrays holding the logical size of the arrays at each level
Definition: HierarchicalContourTree.h:159
vtkm::worklet::contourtree_distributed::TreeGrafter::NewHypernodes
vtkm::worklet::contourtree_augmented::IdArrayType NewHypernodes
Definition: TreeGrafter.h:150
vtkm::worklet::contourtree_distributed::tree_grafter::CopyNewNodesSetSuperparentsWorklet
Definition: CopyNewNodesSetSuperparentsWorklet.h:70
vtkm::worklet::contourtree_distributed::tree_grafter::CopyFirstSupernodePerIterationWorklet
Worklet implementing the copy of the first supernode per iteration in TreeGrafter::CopyIterationDetai...
Definition: CopyFirstSupernodePerIterationWorklet.h:70
FindCriticalPointsFindLeafsWorklet.h
vtkm::cont::ArrayHandleIndex
An implicit array handle containing the its own indices.
Definition: ArrayHandleIndex.h:54
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::NumSupernodesInRound
vtkm::worklet::contourtree_augmented::IdArrayType NumSupernodesInRound
Definition: HierarchicalContourTree.h:160
vtkm::worklet::contourtree_distributed::HierarchicalContourTree::RegularNodeSortOrder
vtkm::worklet::contourtree_augmented::IdArrayType RegularNodeSortOrder
Definition: HierarchicalContourTree.h:115
vtkm::worklet::contourtree_distributed::tree_grafter::SuperarcWasNotTransferredPredicate
Definition: SuperarcWasNotTransferredPredicate.h:100
vtkm::worklet::contourtree_distributed::tree_grafter::NewHypernodePredicate
Definition: NewHypernodePredicate.h:68
vtkm::worklet::contourtree_augmented::PrintEdgePairArray
void PrintEdgePairArray(std::string label, const EdgePairArray &edgePairArray, vtkm::Id nIndices, std::ostream &outStream=std::cout)
Definition: augmented/PrintVectors.h:325