2019-08-28 18:34:42 +00:00
//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
2020-06-12 17:50:01 +00:00
//
2019-08-28 18:34:42 +00:00
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
// Copyright (c) 2018, The Regents of the University of California, through
// Lawrence Berkeley National Laboratory (subject to receipt of any required approvals
// from the U.S. Dept. of Energy). All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// (1) Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// (2) Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// (3) Neither the name of the University of California, Lawrence Berkeley National
// Laboratory, U.S. Dept. of Energy nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
// OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//
//=============================================================================
//
2020-09-15 17:57:20 +00:00
// Parallel Peak Pruning v. 2.0
2019-08-28 18:34:42 +00:00
//
2020-09-15 17:57:20 +00:00
// Started June 15, 2017
//
// Copyright Hamish Carr, University of Leeds
//
// HierarchicalContourTree.cpp - Hierarchical version of contour tree that captures all of the
// superarcs relevant for a particular block. It is constructed by grafting missing edges
// into the tree at all levels
//
//=======================================================================================
//
// COMMENTS:
//
// There are several significant differences from the ContourTree class, in particular the
// semantics of storage:
// i. Hyper arcs are processed inside to outside instead of outside to inside
// This is to allow the superarcs in higher blocks to be a prefix of those in lower blocks
// We can do this by inverting the loop order and processing each level separately, so
// we don't need to renumber (whew!)
// ii. If the superarc is -1, it USED to mean the root of the tree. Now it can also mean
// the root of a lower-level subtree. in this case, the superparent will show which
// existing superarc it inserts into.
//
//=======================================================================================
2019-08-28 18:34:42 +00:00
2020-06-12 17:50:01 +00:00
# ifndef vtk_m_worklet_contourtree_distributed_hierarchical_contour_tree_h
# define vtk_m_worklet_contourtree_distributed_hierarchical_contour_tree_h
2019-08-28 18:34:42 +00:00
2021-03-23 19:33:49 +00:00
# define VOLUME_PRINT_WIDTH 8
2020-06-12 17:50:01 +00:00
# include <vtkm/Types.h>
2021-07-31 02:23:23 +00:00
# include <vtkm/worklet/contourtree_augmented/ContourTree.h>
2019-08-28 18:34:42 +00:00
# include <vtkm/worklet/contourtree_augmented/Types.h>
2020-09-15 17:57:20 +00:00
# include <vtkm/worklet/contourtree_augmented/meshtypes/ContourTreeMesh.h>
2021-07-31 02:23:23 +00:00
# include <vtkm/worklet/contourtree_distributed/LoadArrays.h>
2020-09-15 17:57:20 +00:00
# include <vtkm/worklet/contourtree_distributed/hierarchical_contour_tree/FindRegularByGlobal.h>
# include <vtkm/worklet/contourtree_distributed/hierarchical_contour_tree/FindSuperArcForUnknownNode.h>
# include <vtkm/worklet/contourtree_distributed/hierarchical_contour_tree/InitalizeSuperchildrenWorklet.h>
# include <vtkm/worklet/contourtree_distributed/hierarchical_contour_tree/PermuteComparator.h>
2020-06-12 17:50:01 +00:00
2019-08-28 18:34:42 +00:00
namespace vtkm
{
namespace worklet
{
2020-06-12 17:50:01 +00:00
namespace contourtree_distributed
2019-08-28 18:34:42 +00:00
{
2020-06-12 17:50:01 +00:00
/// \brief Hierarchical Contour Tree data structure
///
2020-09-15 17:57:20 +00:00
/// This class contains all the structures to construct/store the HierarchicalContourTree.
/// Functions used on the Device are then implemented in the HierarchicalContourTreeDeviceData
/// class which stores the prepared array portals we need for those functions.
///
template < typename FieldType >
2020-06-12 17:50:01 +00:00
class HierarchicalContourTree
2019-08-28 18:34:42 +00:00
{
public :
2020-09-30 20:14:28 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
HierarchicalContourTree ( ) ;
// REGULAR arrays: i.e. over all nodes in the tree, including regular
// the full list of global IDs for the regular nodes
vtkm : : worklet : : contourtree_augmented : : IdArrayType RegularNodeGlobalIds ;
// we will also need to track the data values
vtkm : : cont : : ArrayHandle < FieldType > DataValues ;
// an array to support searching by global ID
// given a global ID, find its position in the regular node index
// To do so, we keep an index by global ID of their positions in the array
vtkm : : worklet : : contourtree_augmented : : IdArrayType RegularNodeSortOrder ;
// the supernode ID for each regular node: for most, this will be NO_SUCH_ELEMENT
// but this makes lookups for supernode ID a lot easier
vtkm : : worklet : : contourtree_augmented : : IdArrayType Regular2Supernode ;
// the superparent for each regular node
vtkm : : worklet : : contourtree_augmented : : IdArrayType Superparents ;
// SUPER arrays: i.e. over all supernodes in the tree
// the ID in the globalID array
vtkm : : worklet : : contourtree_augmented : : IdArrayType Supernodes ;
// where the supernode connects to
vtkm : : worklet : : contourtree_augmented : : IdArrayType Superarcs ;
// the hyperparent for each supernode
vtkm : : worklet : : contourtree_augmented : : IdArrayType Hyperparents ;
// the hypernode ID for each supernode: often NO_SUCH_ELEMENT
// but it makes lookups easier
vtkm : : worklet : : contourtree_augmented : : IdArrayType Super2Hypernode ;
// which iteration & round the vertex is transferred in
// the second of these is the same as "whenTransferred", but inverted order
vtkm : : worklet : : contourtree_augmented : : IdArrayType WhichRound ;
vtkm : : worklet : : contourtree_augmented : : IdArrayType WhichIteration ;
// HYPER arrays: i.e. over all hypernodes in the tree
// the ID in the supernode array
vtkm : : worklet : : contourtree_augmented : : IdArrayType Hypernodes ;
// where the hypernode connects to
vtkm : : worklet : : contourtree_augmented : : IdArrayType Hyperarcs ;
// the number of child supernodes on the superarc (including the start node)
// and not including any inserted in the hierarchy
vtkm : : worklet : : contourtree_augmented : : IdArrayType Superchildren ;
// how many rounds of fan-in were used to construct it
vtkm : : Id NumRounds ;
2021-07-31 02:23:23 +00:00
// use for debugging? -> This makes more sense in hyper sweeper?
// vtkm::Id NumOwnedRegularVertices;
2021-03-23 19:20:29 +00:00
2020-12-01 21:11:13 +00:00
// The following arrays store the numbers of reg/super/hyper nodes at each level of the hierarchy
2020-09-15 17:57:20 +00:00
// They are filled in from the top down, and are fundamentally CPU side control variables
// They will be needed for hypersweeps.
// May be for hypersweeps later on. SHOULD be primarily CPU side
/// arrays holding the logical size of the arrays at each level
vtkm : : worklet : : contourtree_augmented : : IdArrayType NumRegularNodesInRound ;
vtkm : : worklet : : contourtree_augmented : : IdArrayType NumSupernodesInRound ;
vtkm : : worklet : : contourtree_augmented : : IdArrayType NumHypernodesInRound ;
/// how many iterations needed for the hypersweep at each level
vtkm : : worklet : : contourtree_augmented : : IdArrayType NumIterations ;
/// vectors tracking the segments used in each iteration of the hypersweep
std : : vector < vtkm : : worklet : : contourtree_augmented : : IdArrayType > FirstSupernodePerIteration ;
std : : vector < vtkm : : worklet : : contourtree_augmented : : IdArrayType > FirstHypernodePerIteration ;
/// routine to create a FindRegularByGlobal object that we can use as an input for worklets to call the function
2020-09-30 20:14:28 +00:00
VTKM_CONT
2021-07-31 02:23:23 +00:00
FindRegularByGlobal GetFindRegularByGlobal ( ) const
2020-09-15 17:57:20 +00:00
{
return FindRegularByGlobal ( this - > RegularNodeSortOrder , this - > RegularNodeGlobalIds ) ;
}
/// routine to create a FindSuperArcForUnknownNode object that we can use as an input for worklets to call the function
2020-09-30 20:14:28 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
FindSuperArcForUnknownNode < FieldType > GetFindSuperArcForUnknownNode ( )
{
return FindSuperArcForUnknownNode < FieldType > ( this - > Superparents ,
this - > Supernodes ,
this - > Superarcs ,
this - > Superchildren ,
this - > WhichRound ,
this - > WhichIteration ,
this - > Hyperparents ,
this - > Hypernodes ,
this - > Hyperarcs ,
this - > RegularNodeGlobalIds ,
this - > DataValues ) ;
}
/// routine to initialize the hierarchical tree with the top level tree
2020-06-12 17:50:01 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
void Initialize ( vtkm : : Id numRounds ,
vtkm : : worklet : : contourtree_augmented : : ContourTree & tree ,
vtkm : : worklet : : contourtree_augmented : : ContourTreeMesh < FieldType > & mesh ) ;
/// utility routines for the path probes
2020-09-30 20:14:28 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
std : : string RegularString ( const vtkm : : Id regularId ) const ;
2020-09-30 20:14:28 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
std : : string SuperString ( const vtkm : : Id superId ) const ;
2020-09-30 20:14:28 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
std : : string HyperString ( const vtkm : : Id hyperId ) const ;
/// routine to probe a given node and trace it's hyperpath to the root
2020-09-30 20:14:28 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
std : : string ProbeHyperPath ( const vtkm : : Id regularId , const vtkm : : Id maxLength = - 1 ) const ;
/// routine to probe a given node and trace it's superpath to the root
2020-09-30 20:14:28 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
std : : string ProbeSuperPath ( const vtkm : : Id regularId , const vtkm : : Id maxLength = - 1 ) const ;
/// Outputs the Hierarchical Tree in Dot format for visualization
2020-09-30 20:14:28 +00:00
VTKM_CONT
2020-09-15 17:57:20 +00:00
std : : string PrintDotSuperStructure ( const char * label ) const ;
2021-07-31 02:23:23 +00:00
/// Load from file saved by PPP
VTKM_CONT
void Load ( const char * filename ) ;
2020-10-28 21:20:00 +00:00
/// Print hierarchical tree construction stats, usually used for logging
VTKM_CONT
std : : string PrintTreeStats ( ) const ;
2020-09-15 17:57:20 +00:00
/// debug routine
2020-09-30 20:14:28 +00:00
VTKM_CONT
2021-07-31 02:23:23 +00:00
std : : string DebugPrint ( std : : string message , const char * fileName , long lineNum ) const ;
2020-09-15 17:57:20 +00:00
2021-03-23 19:33:49 +00:00
// modified version of dumpSuper() that also gives volume counts
VTKM_CONT
2021-07-31 02:23:23 +00:00
std : : string DumpVolumes (
vtkm : : Id totalVolume ,
const vtkm : : worklet : : contourtree_augmented : : IdArrayType & intrinsicVolume ,
const vtkm : : worklet : : contourtree_augmented : : IdArrayType & dependentVolume ) const ;
2021-03-23 19:33:49 +00:00
2020-09-15 17:57:20 +00:00
private :
/// Used internally to Invoke worklets
vtkm : : cont : : Invoker Invoke ;
2019-08-28 18:34:42 +00:00
} ;
2020-09-15 17:57:20 +00:00
template < typename FieldType >
HierarchicalContourTree < FieldType > : : HierarchicalContourTree ( )
2021-07-31 02:23:23 +00:00
//: NumOwnedRegularVertices(static_cast<vtkm::Id>(0))
2020-09-15 17:57:20 +00:00
{ // constructor
NumRegularNodesInRound . ReleaseResources ( ) ;
NumSupernodesInRound . ReleaseResources ( ) ;
NumHypernodesInRound . ReleaseResources ( ) ;
NumIterations . ReleaseResources ( ) ;
} // constructor
/// routine to initialize the hierarchical tree with the top level tree
template < typename FieldType >
void HierarchicalContourTree < FieldType > : : Initialize (
vtkm : : Id numRounds ,
vtkm : : worklet : : contourtree_augmented : : ContourTree & tree ,
vtkm : : worklet : : contourtree_augmented : : ContourTreeMesh < FieldType > & mesh )
{ // Initialize(..)
// TODO: If any other arrays are only copied in this function but will not be modified then we could just assign instead of copy them and make them const
// set the initial logical size of the arrays: note that we need to keep level 0 separate, so have an extra level at the top
this - > NumRounds = numRounds ;
{
auto tempZeroArray = vtkm : : cont : : ArrayHandleConstant < vtkm : : Id > ( 0 , this - > NumRounds + 1 ) ;
vtkm : : cont : : Algorithm : : Copy ( tempZeroArray , this - > NumIterations ) ;
vtkm : : cont : : Algorithm : : Copy ( tempZeroArray , this - > NumRegularNodesInRound ) ;
2021-03-25 04:00:20 +00:00
vtkm : : worklet : : contourtree_augmented : : IdArraySetValue (
this - > NumRounds , tree . Nodes . GetNumberOfValues ( ) , this - > NumRegularNodesInRound ) ;
2020-09-15 17:57:20 +00:00
vtkm : : cont : : Algorithm : : Copy ( tempZeroArray , this - > NumSupernodesInRound ) ;
2021-03-25 04:00:20 +00:00
vtkm : : worklet : : contourtree_augmented : : IdArraySetValue (
this - > NumRounds , tree . Supernodes . GetNumberOfValues ( ) , this - > NumSupernodesInRound ) ;
2020-09-15 17:57:20 +00:00
vtkm : : cont : : Algorithm : : Copy ( tempZeroArray , this - > NumHypernodesInRound ) ;
2021-03-25 04:00:20 +00:00
vtkm : : worklet : : contourtree_augmented : : IdArraySetValue (
this - > NumRounds , tree . Hypernodes . GetNumberOfValues ( ) , this - > NumHypernodesInRound ) ;
2020-09-15 17:57:20 +00:00
}
2021-03-01 22:32:53 +00:00
// copy the iterations of the top level hypersweep - this is +1: one because we are counting inclusively
// HAC JAN 15, 2020: In order to make this consistent with grafting rounds for hybrid hypersweeps, we add one to the logical number of
// iterations instead of the prior version which stored an extra extra element (ie +2)
// WARNING! WARNING! WARNING! This is a departure from the treatment in the contour tree, where the last iteration to the NULL root was
// treated as an implicit round.
2021-03-25 04:00:20 +00:00
{
vtkm : : Id tempSizeVal = vtkm : : cont : : ArrayGetValue ( this - > NumRounds , this - > NumIterations ) + 1 ;
vtkm : : worklet : : contourtree_augmented : : IdArraySetValue (
this - > NumRounds , tree . NumIterations + 1 , this - > NumIterations ) ;
this - > FirstSupernodePerIteration . resize ( static_cast < std : : size_t > ( this - > NumRounds + 1 ) ) ;
this - > FirstSupernodePerIteration [ static_cast < std : : size_t > ( this - > NumRounds ) ] . Allocate (
tempSizeVal ) ;
this - > FirstHypernodePerIteration . resize ( static_cast < std : : size_t > ( this - > NumRounds + 1 ) ) ;
this - > FirstHypernodePerIteration [ static_cast < std : : size_t > ( this - > NumRounds ) ] . Allocate (
tempSizeVal ) ;
}
2020-12-01 21:11:13 +00:00
// now copy in the details. Use CopySubRagnge to ensure that the Copy does not shrink the size
// of the array as the arrays are in this case allocated above to the approbriate size
vtkm : : cont : : Algorithm : : CopySubRange (
tree . FirstSupernodePerIteration , // copy this
0 , // start at index 0
tree . FirstSupernodePerIteration . GetNumberOfValues ( ) , // copy all values
2020-09-15 17:57:20 +00:00
this - > FirstSupernodePerIteration [ static_cast < std : : size_t > ( this - > NumRounds ) ] ) ;
2020-12-01 21:11:13 +00:00
vtkm : : cont : : Algorithm : : CopySubRange (
2020-09-15 17:57:20 +00:00
tree . FirstHypernodePerIteration ,
2020-12-01 21:11:13 +00:00
0 , // start at index 0
tree . FirstHypernodePerIteration . GetNumberOfValues ( ) , // copy all values
2020-09-15 17:57:20 +00:00
this - > FirstHypernodePerIteration [ static_cast < std : : size_t > ( this - > NumRounds ) ] ) ;
// set the sizes for the arrays
this - > RegularNodeGlobalIds . Allocate ( tree . Nodes . GetNumberOfValues ( ) ) ;
this - > DataValues . Allocate ( mesh . SortedValues . GetNumberOfValues ( ) ) ;
this - > RegularNodeSortOrder . Allocate ( tree . Nodes . GetNumberOfValues ( ) ) ;
this - > Superparents . Allocate ( tree . Superparents . GetNumberOfValues ( ) ) ;
{
auto tempNSE = vtkm : : cont : : ArrayHandleConstant < vtkm : : Id > (
vtkm : : worklet : : contourtree_augmented : : NO_SUCH_ELEMENT , tree . Nodes . GetNumberOfValues ( ) ) ;
vtkm : : cont : : Algorithm : : Copy ( tempNSE , this - > Regular2Supernode ) ;
}
this - > Supernodes . Allocate ( tree . Supernodes . GetNumberOfValues ( ) ) ;
this - > Superarcs . Allocate ( tree . Superarcs . GetNumberOfValues ( ) ) ;
this - > Hyperparents . Allocate ( tree . Hyperparents . GetNumberOfValues ( ) ) ;
{
auto tempNSE = vtkm : : cont : : ArrayHandleConstant < vtkm : : Id > (
vtkm : : worklet : : contourtree_augmented : : NO_SUCH_ELEMENT , tree . Supernodes . GetNumberOfValues ( ) ) ;
vtkm : : cont : : Algorithm : : Copy ( tempNSE , this - > Super2Hypernode ) ;
}
this - > WhichRound . Allocate ( tree . Supernodes . GetNumberOfValues ( ) ) ;
this - > WhichIteration . Allocate ( tree . Supernodes . GetNumberOfValues ( ) ) ;
this - > Hypernodes . Allocate ( tree . Hypernodes . GetNumberOfValues ( ) ) ;
this - > Hyperarcs . Allocate ( tree . Hyperarcs . GetNumberOfValues ( ) ) ;
this - > Superchildren . Allocate ( tree . Hyperarcs . GetNumberOfValues ( ) ) ;
//copy the regular nodes
vtkm : : cont : : Algorithm : : Copy ( mesh . GlobalMeshIndex , this - > RegularNodeGlobalIds ) ;
vtkm : : cont : : Algorithm : : Copy ( mesh . SortedValues , this - > DataValues ) ;
// we want to be able to search by global mesh index. That means we need to have an index array, sorted indirectly on globalMeshIndex
vtkm : : cont : : Algorithm : : Copy (
vtkm : : cont : : ArrayHandleIndex ( RegularNodeSortOrder . GetNumberOfValues ( ) ) , RegularNodeSortOrder ) ;
vtkm : : cont : : Algorithm : : Sort ( RegularNodeSortOrder , PermuteComparator ( this - > RegularNodeGlobalIds ) ) ;
vtkm : : cont : : Algorithm : : Copy ( tree . Superparents , this - > Superparents ) ;
// copy in the supernodes
vtkm : : cont : : Algorithm : : Copy ( tree . Supernodes , this - > Supernodes ) ;
vtkm : : cont : : Algorithm : : Copy ( tree . Superarcs , this - > Superarcs ) ;
vtkm : : cont : : Algorithm : : Copy ( tree . Hyperparents , this - > Hyperparents ) ;
vtkm : : cont : : Algorithm : : Copy (
vtkm : : cont : : ArrayHandleConstant < vtkm : : Id > ( numRounds , this - > WhichRound . GetNumberOfValues ( ) ) ,
this - > WhichRound ) ;
vtkm : : cont : : Algorithm : : Copy ( tree . WhenTransferred , this - > WhichIteration ) ;
// now set the regular to supernode array up: it's already been set to NO_SUCH_ELEMENT
{
auto regular2SupernodePermuted =
vtkm : : cont : : make_ArrayHandlePermutation ( this - > Supernodes , this - > Regular2Supernode ) ;
vtkm : : cont : : Algorithm : : Copy ( vtkm : : cont : : ArrayHandleIndex ( this - > Supernodes . GetNumberOfValues ( ) ) ,
regular2SupernodePermuted ) ;
}
// copy in the hypernodes
vtkm : : cont : : Algorithm : : Copy ( tree . Hypernodes , this - > Hypernodes ) ;
vtkm : : cont : : Algorithm : : Copy ( tree . Hyperarcs , this - > Hyperarcs ) ;
// now set the supernode to hypernode array up: it's already been set to NO_SUCH_ELEMENT
{
auto super2HypernodePermuted =
vtkm : : cont : : make_ArrayHandlePermutation ( this - > Hypernodes , this - > Super2Hypernode ) ;
vtkm : : cont : : Algorithm : : Copy ( vtkm : : cont : : ArrayHandleIndex ( this - > Hypernodes . GetNumberOfValues ( ) ) ,
super2HypernodePermuted ) ;
}
{
auto initalizeSuperchildrenWorklet = InitalizeSuperchildrenWorklet ( ) ;
this - > Invoke ( initalizeSuperchildrenWorklet ,
this - > Hyperarcs , // Input
this - > Hypernodes , // Input
this - > Superchildren // Output
) ;
}
} // Initialize(..)
/// utility routine for the path probes
template < typename FieldType >
std : : string HierarchicalContourTree < FieldType > : : RegularString ( const vtkm : : Id regularId ) const
{ // RegularString()
std : : stringstream resultStream ;
// this can get called before the regular ID is fully stored
if ( regularId > = this - > DataValues . GetNumberOfValues ( ) )
{
resultStream < < " Regular ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( regularId , resultStream ) ;
resultStream < < " Value: N/A Global ID: N/A Regular ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( regularId , resultStream ) ;
resultStream < < " SNode ID: N/A Superparent: N/A " ;
}
else
{
resultStream < < " Regular ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( regularId , resultStream ) ;
2021-03-25 04:00:20 +00:00
resultStream < < " Value: " < < vtkm : : cont : : ArrayGetValue ( regularId , this - > DataValues ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Global ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( regularId , this - > RegularNodeGlobalIds ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Regular ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( regularId , resultStream ) ;
resultStream < < " SNode ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( regularId , this - > Regular2Supernode ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Superparents: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( regularId , this - > Superparents ) ) ;
2020-09-15 17:57:20 +00:00
}
return resultStream . str ( ) ;
} // RegularString()
/// utility routine for the path probes
template < typename FieldType >
std : : string HierarchicalContourTree < FieldType > : : SuperString ( const vtkm : : Id superId ) const
{ // SuperString()
std : : stringstream resultStream ;
if ( vtkm : : worklet : : contourtree_augmented : : NoSuchElement ( superId ) )
{
resultStream < < " Super ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( superId , resultStream ) ;
}
else
{
2021-03-25 04:00:20 +00:00
vtkm : : Id unmaskedSuperId = vtkm : : worklet : : contourtree_augmented : : MaskedIndex ( superId ) ;
vtkm : : Id tempSupernodeOfSuperId = vtkm : : cont : : ArrayGetValue ( unmaskedSuperId , this - > Supernodes ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Super ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( superId , resultStream ) ;
resultStream < < " Value: "
2021-03-25 04:00:20 +00:00
< < vtkm : : cont : : ArrayGetValue ( tempSupernodeOfSuperId , this - > DataValues ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Global ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( tempSupernodeOfSuperId , this - > RegularNodeGlobalIds ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Regular Id: " ;
2021-03-25 04:00:20 +00:00
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( tempSupernodeOfSuperId , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Superarc: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( unmaskedSuperId , this - > Superarcs ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " HNode ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( unmaskedSuperId , this - > Super2Hypernode ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Hyperparent: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( unmaskedSuperId , this - > Hyperparents ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Round: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( unmaskedSuperId , this - > WhichRound ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Iteration: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( unmaskedSuperId , this - > WhichIteration ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
}
return resultStream . str ( ) ;
} // SuperString()
/// utility routine for the path probes
template < typename FieldType >
std : : string HierarchicalContourTree < FieldType > : : HyperString ( const vtkm : : Id hyperId ) const
{ // HyperString()
std : : stringstream resultStream ;
if ( vtkm : : worklet : : contourtree_augmented : : NoSuchElement ( hyperId ) )
{
resultStream < < " Hyper ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( hyperId , resultStream ) ;
}
else
{
2021-03-25 04:00:20 +00:00
vtkm : : Id unmaskedHyperId = vtkm : : worklet : : contourtree_augmented : : MaskedIndex ( hyperId ) ;
vtkm : : Id hypernodeOfHyperId = vtkm : : cont : : ArrayGetValue ( unmaskedHyperId , this - > Hypernodes ) ;
vtkm : : Id supernodeOfHyperId = vtkm : : cont : : ArrayGetValue ( hypernodeOfHyperId , this - > Supernodes ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Hyper Id: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( hyperId , resultStream ) ;
2021-03-25 04:00:20 +00:00
resultStream < < " Value: " < < vtkm : : cont : : ArrayGetValue ( supernodeOfHyperId , this - > DataValues ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Global ID: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( supernodeOfHyperId , this - > RegularNodeGlobalIds ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Regular ID: " ;
2021-03-25 04:00:20 +00:00
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( supernodeOfHyperId , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Super ID: " ;
2021-03-25 04:00:20 +00:00
vtkm : : worklet : : contourtree_augmented : : PrintIndexType ( hypernodeOfHyperId , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Hyperarc: " ;
vtkm : : worklet : : contourtree_augmented : : PrintIndexType (
2021-03-25 04:00:20 +00:00
vtkm : : cont : : ArrayGetValue ( unmaskedHyperId , this - > Hyperarcs ) , resultStream ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Superchildren: "
2021-03-25 04:00:20 +00:00
< < vtkm : : cont : : ArrayGetValue ( unmaskedHyperId , this - > Superchildren ) ;
2020-09-15 17:57:20 +00:00
}
return resultStream . str ( ) ;
} // HyperString()
/// routine to probe a given node and trace it's hyperpath to the root
template < typename FieldType >
std : : string HierarchicalContourTree < FieldType > : : ProbeHyperPath ( const vtkm : : Id regularId ,
const vtkm : : Id maxLength ) const
{ // ProbeHyperPath()
std : : stringstream resultStream ;
resultStream < < " Probing HyperPath \n " ;
resultStream < < " Node: " < < this - > RegularString ( regularId ) < < std : : endl ;
// find the superparent
2021-03-25 04:00:20 +00:00
vtkm : : Id superparent = vtkm : : cont : : ArrayGetValue ( regularId , this - > Superparents ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Superparent: " < < SuperString ( superparent ) < < std : : endl ;
// and the hyperparent
2021-03-25 04:00:20 +00:00
vtkm : : Id hyperparent = vtkm : : cont : : ArrayGetValue ( superparent , this - > Hyperparents ) ;
2020-09-15 17:57:20 +00:00
// now trace the path inwards: terminate on last round when we have null hyperarc
vtkm : : Id length = 0 ;
while ( true )
{ // loop inwards
length + + ;
if ( length > maxLength & & maxLength > 0 )
{
break ;
}
resultStream < < " Hyperparent: " < < this - > HyperString ( hyperparent ) < < std : : endl ;
// retrieve the target of the hyperarc
2021-03-25 04:00:20 +00:00
vtkm : : Id hypertarget = vtkm : : cont : : ArrayGetValue ( hyperparent , this - > Hyperarcs ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Hypertarget: "
< < SuperString ( vtkm : : worklet : : contourtree_augmented : : MaskedIndex ( hypertarget ) )
< < std : : endl ;
// mask the hypertarget
vtkm : : Id maskedHypertarget = vtkm : : worklet : : contourtree_augmented : : MaskedIndex ( hypertarget ) ;
// test for null superarc: can only be root or attachment point
if ( vtkm : : worklet : : contourtree_augmented : : NoSuchElement ( hypertarget ) )
{ // root or attachment point
// we're done
break ;
} // root or attachment point
else
{ // ordinary supernode
2021-03-25 04:00:20 +00:00
hyperparent = vtkm : : cont : : ArrayGetValue ( maskedHypertarget , this - > Hyperparents ) ;
2020-09-15 17:57:20 +00:00
} // ordinary supernode
// now take the new superparent's hyperparent/hypertarget
2021-03-25 04:00:20 +00:00
hypertarget = vtkm : : cont : : ArrayGetValue ( hyperparent , this - > Hyperarcs ) ;
2020-09-15 17:57:20 +00:00
} // loop inwards
resultStream < < " Probe Complete " < < std : : endl < < std : : endl ;
return resultStream . str ( ) ;
} // ProbeHyperPath()
/// routine to probe a given node and trace it's superpath to the root
template < typename FieldType >
std : : string HierarchicalContourTree < FieldType > : : ProbeSuperPath ( const vtkm : : Id regularId ,
const vtkm : : Id maxLength ) const
{
std : : stringstream resultStream ;
// find the superparent
2021-03-25 04:00:20 +00:00
vtkm : : Id superparent = vtkm : : cont : : ArrayGetValue ( regularId , this - > Superparents ) ;
2020-09-15 17:57:20 +00:00
// now trace the path inwards: terminate on last round when we have null hyperarc
vtkm : : Id length = 0 ;
while ( true )
{ // loop inwards
length + + ;
if ( length > maxLength & & maxLength > 0 )
{
break ;
}
// retrieve the target of the superarc
2021-03-25 04:00:20 +00:00
vtkm : : Id supertarget = vtkm : : cont : : ArrayGetValue ( superparent , this - > Superarcs ) ;
2020-09-15 17:57:20 +00:00
resultStream < < " Superparent: " < < this - > SuperString ( superparent ) < < std : : endl ;
resultStream < < " Supertarget: "
< < this - > SuperString (
vtkm : : worklet : : contourtree_augmented : : MaskedIndex ( supertarget ) )
< < std : : endl ;
// mask the supertarget
vtkm : : Id maskedSupertarget = vtkm : : worklet : : contourtree_augmented : : MaskedIndex ( supertarget ) ;
// and retrieve it's supertarget
2021-03-25 04:00:20 +00:00
vtkm : : Id nextSupertarget = vtkm : : cont : : ArrayGetValue ( maskedSupertarget , this - > Superarcs ) ;
2020-09-15 17:57:20 +00:00
vtkm : : Id maskedNextSupertarget =
vtkm : : worklet : : contourtree_augmented : : MaskedIndex ( nextSupertarget ) ;
resultStream < < " Next target: " < < this - > SuperString ( nextSupertarget ) < < std : : endl ;
// test for null superarc: can only be root or attachment point
if ( vtkm : : worklet : : contourtree_augmented : : NoSuchElement ( nextSupertarget ) )
{ // root or attachment point
// test round: if it's the last one, only the root has a null edge
2021-03-25 04:00:20 +00:00
if ( vtkm : : cont : : ArrayGetValue ( maskedNextSupertarget , this - > WhichRound ) = = this - > NumRounds )
2020-09-15 17:57:20 +00:00
// we're done
break ;
else // attachment point
superparent = maskedNextSupertarget ;
} // root or attachment point
else
{ // ordinary supernode
superparent = maskedSupertarget ;
} // ordinary supernode
} // loop inwards
resultStream < < " Probe Complete " < < std : : endl < < std : : endl ;
return resultStream . str ( ) ;
}
/// Outputs the Hierarchical Tree in Dot format for visualization
template < typename FieldType >
std : : string HierarchicalContourTree < FieldType > : : PrintDotSuperStructure ( const char * label ) const
{ // PrintDotSuperStructure
// make a copy of the label
std : : string filename ( " temp/ " ) ;
filename + = label ;
// replace spaces with underscores
for ( unsigned int strChar = 0 ; strChar < filename . length ( ) ; strChar + + )
if ( filename [ strChar ] = = ' ' )
filename [ strChar ] = ' _ ' ;
// add the .gv suffix
filename + = " .gv " ;
// generate an output stream
std : : ofstream outstream ( filename ) ;
// print the header information
outstream < < " digraph RegularTree \n \t { \n " ;
outstream < < " \t size= \" 6.5, 9 \" \n \t ratio= \" fill \" \n " ;
outstream < < " \t label= \" " < < label < < " \" \n \t labelloc=t \n \t fontsize=30 \n " ;
// create the NULL (root) node
outstream < < " \t // NULL node to use as a root for the tree \n " ;
outstream < < " \t NULL [style=filled,fillcolor=white,shape=point,label= \" NULL \" ]; \n " ;
outstream < < " \t // Supernodes \n " ;
// loop through all supernodes
2021-03-25 04:00:20 +00:00
// We use regular ReadPortals here since this requires access to many values anyways
2020-10-01 07:47:41 +00:00
auto supernodesPortal = this - > Supernodes . ReadPortal ( ) ;
auto hypernodesPortal = this - > Hypernodes . ReadPortal ( ) ;
auto hyperparentsPortal = this - > Hyperparents . ReadPortal ( ) ;
auto hyperarcsPortal = this - > Hyperarcs . ReadPortal ( ) ;
auto regularNodeGlobalIdsPortal = this - > RegularNodeGlobalIds . ReadPortal ( ) ;
auto whichIterationPortal = this - > WhichIteration . ReadPortal ( ) ;
auto whichRoundPortal = this - > whichRound . ReadPortal ( ) ;
auto superarcsPortal = this - > Superarcs . ReadPortal ( ) ;
auto superparentsPortal = this - > Superparents . ReadPortal ( ) ;
for ( vtkm : : Id supernode = 0 ; supernode < this - > Supernodes . GetNumberOfValues ( ) ; supernode + + )
2020-09-15 17:57:20 +00:00
{ // per supernode
2020-10-01 07:47:41 +00:00
vtkm : : Id regularID = supernodesPortal . Get ( supernode ) ;
2020-09-15 17:57:20 +00:00
// print the supernode, making hypernodes double octagons
outstream
< < " SN " < < std : : setw ( 1 ) < < supernode
< < " [style=filled,fillcolor=white,shape= " < < std : : setw ( 1 )
2020-10-01 07:47:41 +00:00
< < ( ( hypernodesPortal . Get ( hyperparentsPortal . Get ( supernode ) ) = = supernode )
2020-09-15 17:57:20 +00:00
? " doublecircle "
: " circle " ) // hypernodes are double-circles
< < " ,label= \" sn " < < std : : setw ( 4 ) < < supernode < < " h " < < std : : setw ( 1 )
2020-10-01 07:47:41 +00:00
< < ( ( hypernodesPortal . Get ( hyperparentsPortal . Get ( supernode ) ) = = supernode )
2020-09-15 17:57:20 +00:00
? " n "
: " p " ) // hypernodes show "hn001" (their own ID), supernodes show "hp001" (their hyperparent)
2020-10-01 07:47:41 +00:00
< < std : : setw ( 4 ) < < hyperparentsPortal . Get ( supernode ) < < " \\ nm " < < std : : setw ( 1 ) < < regularID
< < " g " < < std : : setw ( 4 ) < < regularNodeGlobalIdsPortal . Get ( regularID ) < < " \\ nrd "
< < std : : setw ( 1 ) < < whichIterationPortal . Get ( supernode ) < < " it " < < std : : setw ( 4 )
< < contourtree_augmented : : MaskedIndex ( whichIterationPortal . Get ( supernode ) ) < < " \" ]; \n " ;
2020-09-15 17:57:20 +00:00
} // per supernode
outstream < < " \t // Superarc nodes \n " ;
// now repeat to create nodes for the middle of each superarc (to represent the superarcs themselves)
2020-10-01 07:47:41 +00:00
for ( vtkm : : Id superarc = 0 ; superarc < this - > Superarcs . GetNumberOfValues ( ) ; superarc + + )
2020-09-15 17:57:20 +00:00
{ // per superarc
// print the superarc vertex
outstream
< < " \t SA " < < std : : setw ( 1 ) < < superarc
< < " [shape=circle,fillcolor=white,fixedsize=true,height=0.5,width=0.5,label= \" \" ]; \n " ;
} // per superarc
outstream < < " \t // Superarc edges \n " ;
// loop through all superarcs to draw them
2020-10-01 07:54:15 +00:00
for ( vtkm : : Id superarc = 0 ; superarc < this - > Superarcs . GetNumberOfValues ( ) ; superarc + + )
2020-09-15 17:57:20 +00:00
{ // per superarc
// retrieve ID of target supernode
vtkm : : Id superarcFrom = superarc ;
2020-10-01 07:47:41 +00:00
vtkm : : Id superarcTo = superarcsPortal . Get ( superarcFrom ) ;
2020-09-15 17:57:20 +00:00
// if this is true, it may be the last pruned vertex
if ( contourtree_augmented : : NoSuchElement ( superarcTo ) )
{ // no superarc
// if it occurred on the final round, it's the global root and is shown as the NULL node
2020-10-01 07:47:41 +00:00
if ( whichRoundPortal . Get ( superarcFrom ) = = this - > NRounds )
2020-09-15 17:57:20 +00:00
{ // root node
outstream < < " \t SN " < < std : : setw ( 1 ) < < superarcFrom < < " -> SA " < < std : : setw ( 1 ) < < superarc
< < " [label= \" S " < < std : : setw ( 1 ) < < superarc < < " \" ,style=dotted] \n " ;
outstream < < " \t SN " < < std : : setw ( 1 ) < < superarc < < " -> NULL[label= \" S " < < std : : setw ( 1 )
< < superarc < < " \" ,style=dotted] \n " ;
} // root node
else
{ // attachment point
// otherwise, the target is actually a superarc vertex not a supernode vertex
// so we use the regular ID to retrieve the superparent which tells us which superarc we insert into
2020-10-01 07:47:41 +00:00
vtkm : : Id regularFrom = supernodesPortal . Get ( superarcFrom ) ;
superarcTo = superparentsPortal . Get ( regularFrom ) ;
2020-09-15 17:57:20 +00:00
// output a suitable edge
outstream < < " \t SN " < < std : : setw ( 1 ) < < superarcFrom < < " -> SA " < < std : : setw ( 1 )
< < superarcTo < < " [label= \" S " < < std : : setw ( 1 ) < < superarc < < " \" ,style=dotted] \n " ;
} // attachment point
} // no superarc
else
{ // there is a superarc
// retrieve the ascending flag
bool ascendingSuperarc = contourtree_augmented : : IsAscending ( superarcTo ) ;
// strip out the flags
superarcTo = contourtree_augmented : : MaskedIndex ( superarcTo ) ;
// how we print depends on whether the superarc ascends
outstream < < " \t SN " < < std : : setw ( 1 ) < < ( ascendingSuperarc ? superarcTo : superarcFrom )
< < " -> SA " < < std : : setw ( 1 ) < < superarc < < " [label= \" S " < < std : : setw ( 1 ) < < superarc
< < " \" " < < ( ascendingSuperarc ? " ,dir= \" back \" " : " " ) < < " ,arrowhead= \" none \" ] \n " ;
outstream < < " \t SA " < < std : : setw ( 1 ) < < superarc < < " -> SN " < < std : : setw ( 1 )
< < ( ascendingSuperarc ? superarcFrom : superarcTo ) < < " [label= \" S " < < std : : setw ( 1 )
< < superarc < < " \" " < < ( ascendingSuperarc ? " ,dir= \" back \" " : " " )
< < " ,arrowhead= \" none \" ] \n " ;
} // there is a superarc
} // per superarc
outstream < < " \t // Hyperarcs \n " ;
// now loop through the hyperarcs to draw them
2020-10-01 07:54:15 +00:00
for ( vtkm : : Id hyperarc = 0 ; hyperarc < this - > Hyperarcs . GetNumberOfValues ( ) ; hyperarc + + )
2020-09-15 17:57:20 +00:00
{ // per hyperarc
// retrieve ID of target hypernode
2020-10-01 07:47:41 +00:00
vtkm : : Id hyperarcFrom = hypernodesPortal . Get ( hyperarc ) ;
vtkm : : Id hyperarcTo = hyperarcsPortal . Get ( hyperarc ) ;
2020-09-15 17:57:20 +00:00
// if this is true, it is the last pruned vertex & needs a hyperarc to the root
if ( contourtree_augmented : : NoSuchElement ( hyperarcTo ) )
outstream < < " \t SN " < < std : : setw ( 1 ) < < hyperarcFrom < < " -> NULL[label= \" H " < < std : : setw ( 1 )
< < hyperarc < < " \" ,penwidth=5.0,style=dotted] \n " ;
else
{ // not the last one
// otherwise, retrieve the ascending flag
bool ascendingHyperarc = contourtree_augmented : : IsAscending ( hyperarcTo ) ;
// strip out the flags
hyperarcTo = contourtree_augmented : : MaskedIndex ( hyperarcTo ) ;
// how we print depends on whether the hyperarc ascends
outstream < < " \t SN " < < std : : setw ( 1 ) < < ( ascendingHyperarc ? hyperarcTo : hyperarcFrom )
< < " -> SN " < < std : : setw ( 1 ) < < ( ascendingHyperarc ? hyperarcFrom : hyperarcTo )
< < " [label= \" H " < < std : : setw ( 1 ) < < hyperarc < < " \" ,penwidth=5.0,dir= \" back \" ] \n " ;
} // not the last one
} // per hyperarc
// print the footer information
outstream < < " \t } \n " ;
return std : : string ( " HierarchicalContourTree<FieldType>::PrintDotSuperStructure() Complete " ) ;
} // PrintDotSuperStructure
2021-07-31 02:23:23 +00:00
template < typename FieldType >
void HierarchicalContourTree < FieldType > : : Load ( const char * filename )
{
std : : ifstream is ( filename ) ;
ReadIndexArray ( is , this - > RegularNodeGlobalIds ) ;
ReadDataArray < FieldType > ( is , this - > DataValues ) ;
ReadIndexArray ( is , this - > RegularNodeSortOrder ) ;
ReadIndexArray ( is , this - > Regular2Supernode ) ;
ReadIndexArray ( is , this - > Superparents ) ;
ReadIndexArray ( is , this - > Supernodes ) ;
ReadIndexArray ( is , this - > Superarcs ) ;
ReadIndexArray ( is , this - > Hyperparents ) ;
ReadIndexArray ( is , this - > Super2Hypernode ) ;
ReadIndexArray ( is , this - > WhichRound ) ;
ReadIndexArray ( is , this - > WhichIteration ) ;
ReadIndexArray ( is , this - > Hypernodes ) ;
ReadIndexArray ( is , this - > Hyperarcs ) ;
ReadIndexArray ( is , this - > Superchildren ) ;
int nRounds ;
is . read ( reinterpret_cast < char * > ( & nRounds ) , sizeof ( nRounds ) ) ;
//std::cout << "nRounds = " << nRounds << std::endl;
this - > NumRounds = nRounds ;
//this->NumOwnedRegularVertices = 0;
ReadIndexArray ( is , this - > NumRegularNodesInRound ) ;
ReadIndexArray ( is , this - > NumSupernodesInRound ) ;
ReadIndexArray ( is , this - > NumHypernodesInRound ) ;
ReadIndexArray ( is , this - > NumIterations ) ;
ReadIndexArrayVector ( is , this - > FirstSupernodePerIteration ) ;
ReadIndexArrayVector ( is , this - > FirstHypernodePerIteration ) ;
}
2020-09-15 17:57:20 +00:00
/// debug routine
template < typename FieldType >
2021-07-31 02:23:23 +00:00
std : : string HierarchicalContourTree < FieldType > : : DebugPrint ( std : : string message ,
2020-09-15 17:57:20 +00:00
const char * fileName ,
long lineNum ) const
2020-10-28 21:20:00 +00:00
{ // DebugPrint
2020-09-15 17:57:20 +00:00
std : : stringstream resultStream ;
resultStream < < std : : endl ;
resultStream < < " [CUTHERE]------------------------------- " < < std : : endl ;
resultStream < < std : : setw ( 30 ) < < std : : left < < fileName < < " : " < < std : : right < < std : : setw ( 4 )
< < lineNum < < std : : endl ;
resultStream < < std : : left < < std : : string ( message ) < < std : : endl ;
resultStream < < " Hierarchical Contour Tree Contains: " < < std : : endl ;
resultStream < < " ---------------------------------------- " < < std : : endl ;
resultStream < < std : : endl ;
vtkm : : worklet : : contourtree_augmented : : PrintHeader ( this - > RegularNodeGlobalIds . GetNumberOfValues ( ) ,
resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Regular Nodes (global ID) " , this - > RegularNodeGlobalIds , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintValues (
" Data Values " , this - > DataValues , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Regular Node Sort Order " , this - > RegularNodeSortOrder , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Superparents (unsorted) " , this - > Superparents , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Supernode ID (if any) " , this - > Regular2Supernode , - 1 , resultStream ) ;
resultStream < < std : : endl ;
vtkm : : worklet : : contourtree_augmented : : PrintHeader ( this - > Supernodes . GetNumberOfValues ( ) ,
resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Supernodes (regular index) " , this - > Supernodes , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Superarcs (supernode index) " , this - > Superarcs , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Hyperparents (hypernode index) " , this - > Hyperparents , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Hypernode ID (if any) " , this - > Super2Hypernode , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Which Round " , this - > WhichRound , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Which Iteration " , this - > WhichIteration , - 1 , resultStream ) ;
resultStream < < std : : endl ;
vtkm : : worklet : : contourtree_augmented : : PrintHeader ( this - > Hypernodes . GetNumberOfValues ( ) ,
resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Hypernodes (supernode index) " , this - > Hypernodes , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Hyperarcs (supernode index) " , this - > Hyperarcs , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" Superchildren " , this - > Superchildren , - 1 , resultStream ) ;
resultStream < < std : : endl ;
resultStream < < " nRounds: " < < this - > NumRounds < < std : : endl ;
vtkm : : worklet : : contourtree_augmented : : PrintHeader (
this - > NumRegularNodesInRound . GetNumberOfValues ( ) , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" nRegular Nodes In Round " , this - > NumRegularNodesInRound , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" nSupernodes In Round " , this - > NumSupernodesInRound , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" nHypernodes In Round " , this - > NumHypernodesInRound , - 1 , resultStream ) ;
2021-07-31 02:23:23 +00:00
//resultStream << "Owned Regular Vertices: " << this->NumOwnedRegularVertices << std::endl;
2020-09-15 17:57:20 +00:00
vtkm : : worklet : : contourtree_augmented : : PrintHeader ( this - > NumIterations . GetNumberOfValues ( ) ,
resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" nIterations " , this - > NumIterations , - 1 , resultStream ) ;
for ( vtkm : : Id whichRound = 0 ; whichRound < this - > NumIterations . GetNumberOfValues ( ) ; whichRound + + )
{ // per round
resultStream < < " Round " < < whichRound < < std : : endl ;
vtkm : : worklet : : contourtree_augmented : : PrintHeader (
this - > FirstSupernodePerIteration [ static_cast < std : : size_t > ( whichRound ) ] . GetNumberOfValues ( ) ,
resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" First Supernode Per Iteration " ,
this - > FirstSupernodePerIteration [ static_cast < std : : size_t > ( whichRound ) ] ,
- 1 ,
resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" First Hypernode Per Iteration " ,
this - > FirstHypernodePerIteration [ static_cast < std : : size_t > ( whichRound ) ] ,
- 1 ,
resultStream ) ;
resultStream < < std : : endl ;
} // per round
return resultStream . str ( ) ;
2020-10-28 21:20:00 +00:00
} // DebugPrint
template < typename FieldType >
std : : string HierarchicalContourTree < FieldType > : : PrintTreeStats ( ) const
{ // PrintTreeStats
std : : stringstream resultStream ;
resultStream < < std : : setw ( 42 ) < < std : : left < < " NumRounds "
< < " : " < < this - > NumRounds < < std : : endl ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" NumIterations " , this - > NumIterations , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
" NumRegularNodesInRound " , this - > NumRegularNodesInRound , - 1 , resultStream ) ;
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
2020-10-30 21:43:43 +00:00
" NumSupernodesInRound " , this - > NumSupernodesInRound , - 1 , resultStream ) ;
2020-10-28 21:20:00 +00:00
vtkm : : worklet : : contourtree_augmented : : PrintIndices (
2020-10-30 21:43:43 +00:00
" NumHypernodesInRound " , this - > NumHypernodesInRound , - 1 , resultStream ) ;
2020-10-28 21:20:00 +00:00
return resultStream . str ( ) ;
} // PrintTreeStats
2020-09-15 17:57:20 +00:00
2019-08-28 18:34:42 +00:00
2021-03-23 19:33:49 +00:00
// modified version of dumpSuper() that also gives volume counts
template < typename FieldType >
std : : string HierarchicalContourTree < FieldType > : : DumpVolumes (
vtkm : : Id totalVolume ,
const vtkm : : worklet : : contourtree_augmented : : IdArrayType & intrinsicVolume ,
2021-07-31 02:23:23 +00:00
const vtkm : : worklet : : contourtree_augmented : : IdArrayType & dependentVolume ) const
2021-03-23 19:33:49 +00:00
{ // DumpVolumes()
// a local string stream to build the output
std : : stringstream outStream ;
// header info
outStream < < " ============ " < < std : : endl ;
outStream < < " Contour Tree " < < std : : endl ;
2021-03-25 04:00:20 +00:00
// loop through all superarcs.
// We use regular ReadPortals here since this requires access to many values anyways
2021-03-23 19:33:49 +00:00
auto supernodesPortal = this - > Supernodes . ReadPortal ( ) ;
auto regularNodeGlobalIdsPortal = this - > RegularNodeGlobalIds . ReadPortal ( ) ;
auto superarcsPortal = this - > Superarcs . ReadPortal ( ) ;
auto intrinsicVolumePortal = intrinsicVolume . ReadPortal ( ) ;
auto dependentVolumePortal = dependentVolume . ReadPortal ( ) ;
for ( vtkm : : Id supernode = 0 ; supernode < this - > Supernodes . GetNumberOfValues ( ) ; supernode + + )
{ // per supernode
// convert all the way down to global regular IDs
vtkm : : Id fromRegular = supernodesPortal . Get ( supernode ) ;
vtkm : : Id fromGlobal = regularNodeGlobalIdsPortal . Get ( fromRegular ) ;
// retrieve the superarc target
vtkm : : Id toSuper = superarcsPortal . Get ( supernode ) ;
// if it is NO_SUCH_ELEMENT, it is the root or an attachment point
// for an augmented tree, it can only be the root
// in any event, we don't want to print them
if ( vtkm : : worklet : : contourtree_augmented : : NoSuchElement ( toSuper ) )
{
continue ;
}
// now break out the ascending flag & the underlying ID
bool superarcAscends = vtkm : : worklet : : contourtree_augmented : : IsAscending ( toSuper ) ;
toSuper = vtkm : : worklet : : contourtree_augmented : : MaskedIndex ( toSuper ) ;
vtkm : : Id toRegular = supernodesPortal . Get ( toSuper ) ;
vtkm : : Id toGlobal = regularNodeGlobalIdsPortal . Get ( toRegular ) ;
// compute the weights
vtkm : : Id weight = dependentVolumePortal . Get ( supernode ) ;
// -1 because the validation output does not count the supernode for the superarc
vtkm : : Id arcWeight = intrinsicVolumePortal . Get ( supernode ) - 1 ;
vtkm : : Id counterWeight = totalVolume - weight + arcWeight ;
// orient with high end first
if ( superarcAscends )
{ // ascending superarc
outStream < < " H: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < toGlobal ;
outStream < < " L: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < fromGlobal ;
outStream < < " VH: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < weight ;
outStream < < " VR: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < arcWeight ;
outStream < < " VL: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < counterWeight ;
outStream < < std : : endl ;
} // ascending superarc
else
{ // descending superarc
outStream < < " H: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < fromGlobal ;
outStream < < " L: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < toGlobal ;
outStream < < " VH: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < counterWeight ;
outStream < < " VR: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < arcWeight ;
outStream < < " VL: " < < std : : setw ( VOLUME_PRINT_WIDTH ) < < weight ;
outStream < < std : : endl ;
} // descending superarc
} // per supernode
// return the string
return outStream . str ( ) ;
} // DumpVolumes()
2020-06-12 17:50:01 +00:00
} // namespace contourtree_distributed
2019-08-28 18:34:42 +00:00
} // namespace worklet
} // namespace vtkm
# endif