vtk-m/vtkm/worklet/contourtree_augmented/Types.h
2021-11-03 12:24:39 -07:00

336 lines
11 KiB
C++

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// 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.
//
//=============================================================================
//
// This code is an extension of the algorithm presented in the paper:
// Parallel Peak Pruning for Scalable SMP Contour Tree Computation.
// Hamish Carr, Gunther Weber, Christopher Sewell, and James Ahrens.
// Proceedings of the IEEE Symposium on Large Data Analysis and Visualization
// (LDAV), October 2016, Baltimore, Maryland.
//
// The PPP2 algorithm and software were jointly developed by
// Hamish Carr (University of Leeds), Gunther H. Weber (LBNL), and
// Oliver Ruebel (LBNL)
//==============================================================================
#ifndef vtk_m_worklet_contourtree_augmented_types_h
#define vtk_m_worklet_contourtree_augmented_types_h
#include <vtkm/Types.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/CellSetStructured.h>
namespace vtkm
{
namespace worklet
{
namespace contourtree_augmented
{
// constexpr for bit flags
// clang-format off
constexpr vtkm::Id NO_SUCH_ELEMENT = std::numeric_limits<vtkm::Id>::min();
constexpr vtkm::Id TERMINAL_ELEMENT = std::numeric_limits<vtkm::Id>::max() / 2 + 1; //0x40000000 || 0x4000000000000000
constexpr vtkm::Id IS_SUPERNODE = std::numeric_limits<vtkm::Id>::max() / 4 + 1; //0x20000000 || 0x2000000000000000
constexpr vtkm::Id IS_HYPERNODE = std::numeric_limits<vtkm::Id>::max() / 8 + 1; //0x10000000 || 0x1000000000000000
constexpr vtkm::Id IS_ASCENDING = std::numeric_limits<vtkm::Id>::max() / 16 + 1; //0x08000000 || 0x0800000000000000
constexpr vtkm::Id INDEX_MASK = std::numeric_limits<vtkm::Id>::max() / 16; //0x07FFFFFF || 0x07FFFFFFFFFFFFFF
constexpr vtkm::Id CV_OTHER_FLAG = std::numeric_limits<vtkm::Id>::max() / 8 + 1; //0x10000000 || 0x1000000000000000
constexpr vtkm::Id ELEMENT_EXISTS = std::numeric_limits<vtkm::Id>::max() / 4 + 1; //0x20000000 || 0x2000000000000000 , same as IS_SUPERNODE
// flags for testing regular vertices
constexpr vtkm::Id IS_LOWER_LEAF = static_cast<vtkm::Id>(0);
constexpr vtkm::Id IS_UPPER_LEAF = static_cast<vtkm::Id>(1);
constexpr vtkm::Id IS_REGULAR = static_cast<vtkm::Id>(2);
constexpr vtkm::Id IS_SADDLE = static_cast<vtkm::Id>(3);
constexpr vtkm::Id IS_ATTACHMENT = static_cast<vtkm::Id>(4);
// clang-format on
using IdArrayType = vtkm::cont::ArrayHandle<vtkm::Id>;
using EdgePair = vtkm::Pair<vtkm::Id, vtkm::Id>; // here EdgePair.first=low and EdgePair.second=high
using EdgePairArray = vtkm::cont::ArrayHandle<EdgePair>; // Array of edge pairs
// inline functions for retrieving flags or index
VTKM_EXEC_CONT
inline bool NoSuchElement(vtkm::Id flaggedIndex)
{ // NoSuchElement()
return ((flaggedIndex & (vtkm::Id)NO_SUCH_ELEMENT) != 0);
} // NoSuchElement()
VTKM_EXEC_CONT
inline bool IsTerminalElement(vtkm::Id flaggedIndex)
{ // IsTerminalElement()
return ((flaggedIndex & TERMINAL_ELEMENT) != 0);
} // IsTerminalElement()
VTKM_EXEC_CONT
inline bool IsSupernode(vtkm::Id flaggedIndex)
{ // IsSupernode()
return ((flaggedIndex & IS_SUPERNODE) != 0);
} // IsSupernode()
VTKM_EXEC_CONT
inline bool IsHypernode(vtkm::Id flaggedIndex)
{ // IsHypernode()
return ((flaggedIndex & IS_HYPERNODE) != 0);
} // IsHypernode()
VTKM_EXEC_CONT
inline bool IsAscending(vtkm::Id flaggedIndex)
{ // IsAscending()
return ((flaggedIndex & IS_ASCENDING) != 0);
} // IsAscending()
VTKM_EXEC_CONT
inline vtkm::Id MaskedIndex(vtkm::Id flaggedIndex)
{ // MaskedIndex()
return (flaggedIndex & INDEX_MASK);
} // MaskedIndex()
/// Used in the context of CombinedVector class used in ContourTreeMesh to merge the mesh of contour trees
VTKM_EXEC_CONT
inline bool IsThis(vtkm::Id flaggedIndex)
{ // IsThis
return ((flaggedIndex & CV_OTHER_FLAG) == 0);
} // IsThis
/// Helper function to set a single array valye with CopySubRange to avoid pulling the array to the control environment
VTKM_CONT
inline void IdArraySetValue(vtkm::Id index, vtkm::Id value, IdArrayType& arr)
{ // IdArraySetValue
vtkm::cont::Algorithm::CopySubRange(
vtkm::cont::ArrayHandleConstant<vtkm::Id>(value, 1), 0, 1, arr, index);
} // IdArraySetValues
/// Helper function used to resize a 1D ArrayHandle and initalize new values with a
/// given fillValue. For resizing ArrayHandles without initalizing new values VTKm
/// supports the vtkm::CopyFlag::On setting as part of the ArrayHandle.Allocate
/// method.
/// @param[in] thearray The 1D array to be resized
/// @param[in] newSize The new size the array should be changed to
/// @param[in] fillValue The value to be used to fill the array
template <typename ValueType>
void ResizeVector(vtkm::cont::ArrayHandle<ValueType>& thearray,
vtkm::Id newSize,
ValueType fillValue)
{
vtkm::Id oldSize = thearray.GetNumberOfValues();
// Simply return if the size of the array does not change
if (oldSize == newSize)
{
return;
}
// Resize the array but keep the original values
thearray.Allocate(newSize, vtkm::CopyFlag::On);
// Add the fill values to the array if we increased the size of the array
if (oldSize < newSize)
{
vtkm::cont::Algorithm::CopySubRange(
vtkm::cont::ArrayHandleConstant<ValueType>(fillValue, newSize - oldSize), // copy
0, // start copying from first index
newSize - oldSize, // num values to copy
thearray, // target array to copy to
oldSize // start copy to after oldSize
);
}
}
template <typename T>
struct MaskedIndexFunctor
{
VTKM_EXEC_CONT
MaskedIndexFunctor() {}
VTKM_EXEC_CONT
vtkm::Id operator()(T x) const { return MaskedIndex(x); }
};
inline std::string FlagString(vtkm::Id flaggedIndex)
{ // FlagString()
std::string fString("");
fString += (NoSuchElement(flaggedIndex) ? "n" : ".");
fString += (IsTerminalElement(flaggedIndex) ? "t" : ".");
fString += (IsSupernode(flaggedIndex) ? "s" : ".");
fString += (IsHypernode(flaggedIndex) ? "h" : ".");
fString += (IsAscending(flaggedIndex) ? "a" : ".");
return fString;
} // FlagString()
class EdgeDataHeight
{
public:
// RegularNodeID (or sortIndex)
Id I;
// RegularNodeID (or sortIndex)
Id J;
// RegularNodeID (or sortIndex)
Id SubtreeMin;
// RegularNodeID (or sortIndex)
Id SubtreeMax;
bool UpEdge;
Float64 SubtreeHeight;
VTKM_EXEC
bool operator<(const EdgeDataHeight& b) const
{
if (this->I == b.I)
{
if (this->UpEdge == b.UpEdge)
{
if (this->SubtreeHeight == b.SubtreeHeight)
{
if (this->SubtreeMin == b.SubtreeMin)
{
return this->SubtreeMax > b.SubtreeMax;
}
else
{
return this->SubtreeMin < b.SubtreeMin;
}
}
else
{
return this->SubtreeHeight > b.SubtreeHeight;
}
}
else
{
return this->UpEdge < b.UpEdge;
}
}
else
{
return this->I < b.I;
}
}
};
class EdgeDataVolume
{
public:
// RegularNodeID (or sortIndex)
Id I;
// RegularNodeID (or sortIndex)
Id J;
bool UpEdge;
Id SubtreeVolume;
VTKM_EXEC
bool operator<(const EdgeDataVolume& b) const
{
if (this->I == b.I)
{
if (this->UpEdge == b.UpEdge)
{
if (this->SubtreeVolume == b.SubtreeVolume)
{
if (this->UpEdge == true)
{
return this->J > b.J;
}
else
{
return this->J < b.J;
}
}
else
{
return this->SubtreeVolume > b.SubtreeVolume;
}
}
else
{
return this->UpEdge < b.UpEdge;
}
}
else
{
return this->I < b.I;
}
}
};
///
/// Helper struct to collect sizing information from a dataset.
/// The struct is used in the contour tree filter implementation
/// to determine the rows, cols, slices parameters from the
/// datasets so we can call the contour tree worklet properly.
///
struct GetPointDimensions
{
//@{
/// Get the number of rows, cols, and slices of a vtkm::cont::CellSetStructured
/// @param[in] cells The input vtkm::cont::CellSetStructured
/// @param[out] pointDimensions mesh size (#cols, #rows #slices in old notation) with last dimension having a value of 1 for 2D data
void operator()(const vtkm::cont::CellSetStructured<2>& cells, vtkm::Id3& pointDimensions) const
{
vtkm::Id2 pointDimensions2D = cells.GetPointDimensions();
pointDimensions[0] = pointDimensions2D[0];
pointDimensions[1] = pointDimensions2D[1];
pointDimensions[2] = 1;
}
void operator()(const vtkm::cont::CellSetStructured<3>& cells, vtkm::Id3& pointDimensions) const
{
pointDimensions = cells.GetPointDimensions();
}
//@}
/// Raise ErrorBadValue if the input cell set is not a vtkm::cont::CellSetStructured<2> or <3>
template <typename T>
void operator()(const T&, vtkm::Id3&) const
{
throw vtkm::cont::ErrorBadValue("Expected 2D or 3D structured cell cet! ");
}
};
} // namespace contourtree_augmented
} // worklet
} // vtkm
#endif