Merge topic 'guide-fancy-arrays'

3e6963092 Add guide chapter on fancy array handles

Acked-by: Kitware Robot <kwrobot@kitware.com>
Acked-by: Vicente Bolea <vicente.bolea@kitware.com>
Merge-request: !3231
This commit is contained in:
Kenneth Moreland 2024-06-21 18:45:30 +00:00 committed by Kitware Robot
commit c6ad00aefd
35 changed files with 2076 additions and 66 deletions

@ -365,8 +365,7 @@ The third array identifies an offset into the second array where the point indic
An explicit cell set can also identify the number of indices defined for each cell by subtracting consecutive entries in the offsets array.
It is often the case when creating a :class:`vtkm::cont::CellSetExplicit` that you have an array containing the number of indices rather than the offsets.
Such an array can be converted to an offsets array that can be used with :class:`vtkm::cont::CellSetExplicit` by using the :func:`vtkm::cont::ConvertNumComponentsToOffsets` convenience function.
.. doxygenfunction:: vtkm::cont::ConvertNumComponentsToOffsets(const vtkm::cont::UnknownArrayHandle&, vtkm::cont::ArrayHandle<vtkm::Id>&, vtkm::Id&, vtkm::cont::DeviceAdapterId)
See the documentation for :class:`vtkm::cont::ArrayHandleGroupVecVariable` in :secref:`fancy-array-handles:Grouped Vector Arrays` for examples of using :func:`vtkm::cont::ConvertNumComponentsToOffsets`.
:class:`vtkm::cont::CellSetExplicit` is a powerful representation for a cell set
because it can represent an arbitrary collection of cells. However, because

@ -10,7 +10,19 @@
set(examples
GuideExampleArrayHandle.cxx
GuideExampleArrayHandleCast.cxx
GuideExampleArrayHandleCompositeVector.cxx
GuideExampleArrayHandleConstant.cxx
GuideExampleArrayHandleCoordinateSystems.cxx
GuideExampleArrayHandleCounting.cxx
GuideExampleArrayHandleExtractComponent.cxx
GuideExampleArrayHandleGroupVec.cxx
GuideExampleArrayHandlePermutation.cxx
GuideExampleArrayHandleRandom.cxx
GuideExampleArrayHandleRuntimeVec.cxx
GuideExampleArrayHandleSwizzle.cxx
GuideExampleArrayHandleView.cxx
GuideExampleArrayHandleZip.cxx
GuideExampleCellShapes.cxx
GuideExampleColorTables.cxx
GuideExampleCoreDataTypes.cxx
@ -28,6 +40,7 @@ set(examples
GuideExampleTuple.cxx
)
set(examples_device
GuideExampleArrayHandleDiscard.cxx
GuideExampleCellEdgesFaces.cxx
GuideExampleCellLocator.cxx
GuideExampleCellOperations.cxx

@ -0,0 +1,83 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleCast.h>
#include <vector>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename OriginalType, typename ArrayHandleType>
void CheckArray(const ArrayHandleType array)
{
vtkm::Id length = array.GetNumberOfValues();
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == length, "Portal has wrong size.");
for (vtkm::Id index = 0; index < length; index++)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(index), TestValue(index, OriginalType())),
"Array has wrong value.");
VTKM_TEST_ASSERT(
!test_equal(portal.Get(index),
TestValue(index, typename ArrayHandleType::ValueType())),
"Array has wrong value.");
}
}
////
//// BEGIN-EXAMPLE ArrayHandleCast
////
template<typename T>
VTKM_CONT void Foo(const std::vector<T>& inputData)
{
vtkm::cont::ArrayHandle<T> originalArray =
vtkm::cont::make_ArrayHandle(inputData, vtkm::CopyFlag::On);
vtkm::cont::ArrayHandleCast<vtkm::Float64, vtkm::cont::ArrayHandle<T>> castArray(
originalArray);
////
//// END-EXAMPLE ArrayHandleCast
////
CheckArray<T>(castArray);
CheckArray<T>(
////
//// BEGIN-EXAMPLE MakeArrayHandleCast
////
vtkm::cont::make_ArrayHandleCast<vtkm::Float64>(originalArray)
////
//// END-EXAMPLE MakeArrayHandleCast
////
);
}
void Test()
{
const std::size_t ARRAY_SIZE = 50;
std::vector<vtkm::Int32> inputData(ARRAY_SIZE);
for (std::size_t index = 0; index < ARRAY_SIZE; index++)
{
inputData[index] = TestValue(vtkm::Id(index), vtkm::Int32());
}
Foo(inputData);
}
} // anonymous namespace
int GuideExampleArrayHandleCast(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,106 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray(ArrayHandleType array)
{
vtkm::cont::printSummary_ArrayHandle(array, std::cout);
std::cout << std::endl;
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
// [(0,3,2,0), (1,1,7,0), (2,4,1,0), (3,1,8,0), (4,5,2,0)].
VTKM_TEST_ASSERT(test_equal(portal.Get(0), vtkm::make_Vec(0, 3, 2, 0)),
"Bad value in array.");
VTKM_TEST_ASSERT(test_equal(portal.Get(1), vtkm::make_Vec(1, 1, 7, 0)),
"Bad value in array.");
VTKM_TEST_ASSERT(test_equal(portal.Get(2), vtkm::make_Vec(2, 4, 1, 0)),
"Bad value in array.");
VTKM_TEST_ASSERT(test_equal(portal.Get(3), vtkm::make_Vec(3, 1, 8, 0)),
"Bad value in array.");
}
void ArrayHandleCompositeVectorBasic()
{
////
//// BEGIN-EXAMPLE ArrayHandleCompositeVectorBasic
////
// Create an array with [0, 1, 2, 3, 4]
using ArrayType1 = vtkm::cont::ArrayHandleIndex;
ArrayType1 array1(5);
// Create an array with [3, 1, 4, 1, 5]
using ArrayType2 = vtkm::cont::ArrayHandle<vtkm::Id>;
ArrayType2 array2;
array2.Allocate(5);
ArrayType2::WritePortalType arrayPortal2 = array2.WritePortal();
arrayPortal2.Set(0, 3);
arrayPortal2.Set(1, 1);
arrayPortal2.Set(2, 4);
arrayPortal2.Set(3, 1);
arrayPortal2.Set(4, 5);
// Create an array with [2, 7, 1, 8, 2]
using ArrayType3 = vtkm::cont::ArrayHandle<vtkm::Id>;
ArrayType3 array3;
array3.Allocate(5);
ArrayType2::WritePortalType arrayPortal3 = array3.WritePortal();
arrayPortal3.Set(0, 2);
arrayPortal3.Set(1, 7);
arrayPortal3.Set(2, 1);
arrayPortal3.Set(3, 8);
arrayPortal3.Set(4, 2);
// Create an array with [0, 0, 0, 0]
using ArrayType4 = vtkm::cont::ArrayHandleConstant<vtkm::Id>;
ArrayType4 array4(0, 5);
// Use ArrayhandleCompositeVector to create the array
// [(0,3,2,0), (1,1,7,0), (2,4,1,0), (3,1,8,0), (4,5,2,0)].
using CompositeArrayType = vtkm::cont::
ArrayHandleCompositeVector<ArrayType1, ArrayType2, ArrayType3, ArrayType4>;
CompositeArrayType compositeArray(array1, array2, array3, array4);
////
//// END-EXAMPLE ArrayHandleCompositeVectorBasic
////
CheckArray(compositeArray);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleCompositeVector
////
vtkm::cont::make_ArrayHandleCompositeVector(array1, array2, array3, array4)
////
//// END-EXAMPLE MakeArrayHandleCompositeVector
////
);
}
void Test()
{
ArrayHandleCompositeVectorBasic();
}
} // anonymous namespace
int GuideExampleArrayHandleCompositeVector(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,70 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleConstant.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray(const ArrayHandleType array,
vtkm::Id expectedLength,
typename ArrayHandleType::ValueType expectedValue)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == expectedLength, "Array has wrong size.");
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == expectedLength,
"Portal has wrong size.");
for (vtkm::Id index = 0; index < expectedLength; index++)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(index), expectedValue),
"Array has wrong value.");
}
}
void Test()
{
////
//// BEGIN-EXAMPLE ArrayHandleConstant
////
// Create an array of 50 entries, all containing the number 3. This could be
// used, for example, to represent the sizes of all the polygons in a set
// where we know all the polygons are triangles.
vtkm::cont::ArrayHandleConstant<vtkm::Id> constantArray(3, 50);
////
//// END-EXAMPLE ArrayHandleConstant
////
CheckArray(constantArray, 50, 3);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleConstant
////
// Create an array of 50 entries, all containing the number 3.
vtkm::cont::make_ArrayHandleConstant(3, 50)
////
//// END-EXAMPLE MakeArrayHandleConstant
////
,
50,
3);
}
} // anonymous namespace
int GuideExampleArrayHandleConstant(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,137 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleCartesianProduct.h>
#include <vtkm/cont/ArrayHandleUniformPointCoordinates.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void UniformPointCoordinates()
{
std::cout << "Trying uniform point coordinates." << std::endl;
////
//// BEGIN-EXAMPLE ArrayHandleUniformPointCoordinates
////
// Create a set of point coordinates for a uniform grid in the space between
// -5 and 5 in the x direction and -3 and 3 in the y and z directions. The
// uniform sampling is spaced in 0.08 unit increments in the x direction (for
// 126 samples), 0.08 unit increments in the y direction (for 76 samples) and
// 0.24 unit increments in the z direction (for 26 samples). That makes
// 248,976 values in the array total.
vtkm::cont::ArrayHandleUniformPointCoordinates uniformCoordinates(
vtkm::Id3(126, 76, 26),
vtkm::Vec3f{ -5.0f, -3.0f, -3.0f },
vtkm::Vec3f{ 0.08f, 0.08f, 0.24f });
////
//// END-EXAMPLE ArrayHandleUniformPointCoordinates
////
VTKM_TEST_ASSERT(uniformCoordinates.GetNumberOfValues() == 248976,
"Wrong number of values in uniform coordinates.");
VTKM_TEST_ASSERT(
test_equal(uniformCoordinates.ReadPortal().Get(0), vtkm::Vec3f{ -5.0, -3.0, -3.0 }),
"Bad first point coordinate.");
VTKM_TEST_ASSERT(test_equal(uniformCoordinates.ReadPortal().Get(248975),
vtkm::Vec3f{ 5.0, 3.0, 3.0 }),
"Bad last point coordinate.");
}
template<typename ArrayHandleType>
void CheckRectilinearPointCoordinates(ArrayHandleType rectilinearCoordinates)
{
VTKM_TEST_ASSERT(rectilinearCoordinates.GetNumberOfValues() == 12,
"Wrong number of values.");
VTKM_TEST_ASSERT(test_equal(rectilinearCoordinates.ReadPortal().Get(0),
vtkm::Vec3f{ 0.0f, 0.0f, 0.0f }),
"Bad value at 0.");
VTKM_TEST_ASSERT(test_equal(rectilinearCoordinates.ReadPortal().Get(4),
vtkm::Vec3f{ 1.1f, 2.0f, 0.0f }),
"Bad value at 4.");
VTKM_TEST_ASSERT(test_equal(rectilinearCoordinates.ReadPortal().Get(11),
vtkm::Vec3f{ 5.0f, 2.0f, 0.5f }),
"Bad value at 11.");
}
void RectilinearPointCoordinates()
{
std::cout << "Trying rectilinear point coordinates." << std::endl;
////
//// BEGIN-EXAMPLE ArrayHandleCartesianProduct
////
using AxisArrayType = vtkm::cont::ArrayHandle<vtkm::Float32>;
using AxisPortalType = AxisArrayType::WritePortalType;
// Create array for x axis coordinates with values [0.0, 1.1, 5.0]
AxisArrayType xAxisArray;
xAxisArray.Allocate(3);
AxisPortalType xAxisPortal = xAxisArray.WritePortal();
xAxisPortal.Set(0, 0.0f);
xAxisPortal.Set(1, 1.1f);
xAxisPortal.Set(2, 5.0f);
// Create array for y axis coordinates with values [0.0, 2.0]
AxisArrayType yAxisArray;
yAxisArray.Allocate(2);
AxisPortalType yAxisPortal = yAxisArray.WritePortal();
yAxisPortal.Set(0, 0.0f);
yAxisPortal.Set(1, 2.0f);
// Create array for z axis coordinates with values [0.0, 0.5]
AxisArrayType zAxisArray;
zAxisArray.Allocate(2);
AxisPortalType zAxisPortal = zAxisArray.WritePortal();
zAxisPortal.Set(0, 0.0f);
zAxisPortal.Set(1, 0.5f);
// Create point coordinates for a "rectilinear grid" with axis-aligned points
// with variable spacing by taking the Cartesian product of the three
// previously defined arrays. This generates the following 3x2x2 = 12 values:
//
// [0.0, 0.0, 0.0], [1.1, 0.0, 0.0], [5.0, 0.0, 0.0],
// [0.0, 2.0, 0.0], [1.1, 2.0, 0.0], [5.0, 2.0, 0.0],
// [0.0, 0.0, 0.5], [1.1, 0.0, 0.5], [5.0, 0.0, 0.5],
// [0.0, 2.0, 0.5], [1.1, 2.0, 0.5], [5.0, 2.0, 0.5]
vtkm::cont::ArrayHandleCartesianProduct<AxisArrayType, AxisArrayType, AxisArrayType>
rectilinearCoordinates(xAxisArray, yAxisArray, zAxisArray);
////
//// END-EXAMPLE ArrayHandleCartesianProduct
////
CheckRectilinearPointCoordinates(rectilinearCoordinates);
CheckRectilinearPointCoordinates(
////
//// BEGIN-EXAMPLE MakeArrayHandleCartesianProduct
////
vtkm::cont::make_ArrayHandleCartesianProduct(xAxisArray, yAxisArray, zAxisArray)
////
//// END-EXAMPLE MakeArrayHandleCartesianProduct
////
);
}
void Test()
{
UniformPointCoordinates();
RectilinearPointCoordinates();
}
} // anonymous namespace
int GuideExampleArrayHandleCoordinateSystems(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,106 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray(const ArrayHandleType array,
typename ArrayHandleType::ValueType startValue,
typename ArrayHandleType::ValueType stepValue,
vtkm::Id expectedLength)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == expectedLength, "Array has wrong size.");
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == expectedLength,
"Portal has wrong size.");
typename ArrayHandleType::ValueType expectedValue = startValue;
for (vtkm::Id index = 0; index < expectedLength; index++)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(index), expectedValue),
"Array has wrong value.");
expectedValue = expectedValue + stepValue;
}
}
void Test()
{
////
//// BEGIN-EXAMPLE ArrayHandleIndex
////
// Create an array containing [0, 1, 2, 3, ..., 49].
vtkm::cont::ArrayHandleIndex indexArray(50);
////
//// END-EXAMPLE ArrayHandleIndex
////
CheckArray(indexArray, 0, 1, 50);
////
//// BEGIN-EXAMPLE ArrayHandleCountingBasic
////
// Create an array containing [-1.0, -0.9, -0.8, ..., 0.9, 1.0]
vtkm::cont::ArrayHandleCounting<vtkm::Float32> sampleArray(-1.0f, 0.1f, 21);
////
//// END-EXAMPLE ArrayHandleCountingBasic
////
CheckArray(sampleArray, -1.0f, 0.1f, 21);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleCountingBasic
////
// Create an array containing [-1.0, -0.9, -0.8, ..., 0.9, 1.0]
vtkm::cont::make_ArrayHandleCounting(-1.0f, 0.1f, 21)
////
//// END-EXAMPLE MakeArrayHandleCountingBasic
////
,
-1.0f,
0.1f,
21);
////
//// BEGIN-EXAMPLE ArrayHandleCountingBackward
////
// Create an array containing [49, 48, 47, 46, ..., 0].
vtkm::cont::ArrayHandleCounting<vtkm::Id> backwardIndexArray(49, -1, 50);
////
//// END-EXAMPLE ArrayHandleCountingBackward
////
CheckArray(backwardIndexArray, 49, -1, 50);
CheckArray(
////
//// BEGIN-EXAMPLE ArrayHandleCountingVec
////
// Create an array containg [(0,-3,75), (1,2,25), (3,7,-25)]
vtkm::cont::make_ArrayHandleCounting(
vtkm::make_Vec(0, -3, 75), vtkm::make_Vec(1, 5, -50), 3)
////
//// END-EXAMPLE ArrayHandleCountingVec
////
,
vtkm::make_Vec(0, -3, 75),
vtkm::make_Vec(1, 5, -50),
3);
}
} // anonymous namespace
int GuideExampleArrayHandleCounting(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,67 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleDiscard.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
////
//// BEGIN-EXAMPLE ArrayHandleDiscard
////
template<typename InputArrayType, typename OutputArrayType1, typename OutputArrayType2>
VTKM_CONT void DoFoo(InputArrayType input,
OutputArrayType1 output1,
OutputArrayType2 output2);
template<typename InputArrayType>
VTKM_CONT inline vtkm::cont::ArrayHandle<vtkm::FloatDefault> DoBar(InputArrayType input)
{
VTKM_IS_ARRAY_HANDLE(InputArrayType);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> keepOutput;
vtkm::cont::ArrayHandleDiscard<vtkm::FloatDefault> discardOutput;
DoFoo(input, keepOutput, discardOutput);
return keepOutput;
}
////
//// END-EXAMPLE ArrayHandleDiscard
////
template<typename InputArrayType, typename OutputArrayType1, typename OutputArrayType2>
VTKM_CONT inline void DoFoo(InputArrayType input,
OutputArrayType1 output1,
OutputArrayType2 output2)
{
vtkm::cont::Algorithm::Copy(input, output1);
vtkm::cont::Algorithm::Copy(input, output2);
}
void Test()
{
vtkm::cont::ArrayHandleCounting<vtkm::FloatDefault> inputArray(0, 10, 10);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outputArray = DoBar(inputArray);
VTKM_TEST_ASSERT(outputArray.GetNumberOfValues() == 10, "Wrong size.");
}
} // anonymous namespace
int GuideExampleArrayHandleDiscard(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,70 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleExtractComponent.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray(const ArrayHandleType array)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == 3, "Permuted array has wrong size.");
auto portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == 3, "Permuted portal has wrong size.");
VTKM_TEST_ASSERT(test_equal(portal.Get(0), 0.2), "Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(1), 1.2), "Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(2), 2.2), "Permuted array has wrong value.");
}
void Test()
{
////
//// BEGIN-EXAMPLE ArrayHandleExtractComponent
////
using ValueArrayType = vtkm::cont::ArrayHandle<vtkm::Vec3f_64>;
// Create array with values [ (0.0, 0.1, 0.2), (1.0, 1.1, 1.2), (2.0, 2.1, 2.2) ]
ValueArrayType valueArray;
valueArray.Allocate(3);
auto valuePortal = valueArray.WritePortal();
valuePortal.Set(0, vtkm::make_Vec(0.0, 0.1, 0.2));
valuePortal.Set(1, vtkm::make_Vec(1.0, 1.1, 1.2));
valuePortal.Set(2, vtkm::make_Vec(2.0, 2.1, 2.2));
// Use ArrayHandleExtractComponent to make an array = [1.3, 2.3, 3.3].
vtkm::cont::ArrayHandleExtractComponent<ValueArrayType> extractedComponentArray(
valueArray, 2);
////
//// END-EXAMPLE ArrayHandleExtractComponent
////
CheckArray(extractedComponentArray);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleExtractComponent
////
vtkm::cont::make_ArrayHandleExtractComponent(valueArray, 2)
////
//// END-EXAMPLE MakeArrayHandleExtractComponent
////
);
}
} // anonymous namespace
int GuideExampleArrayHandleExtractComponent(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,143 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandleGroupVec.h>
#include <vtkm/cont/ArrayHandleGroupVecVariable.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ConvertNumComponentsToOffsets.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray(ArrayHandleType array)
{
vtkm::cont::printSummary_ArrayHandle(array, std::cout);
std::cout << std::endl;
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
vtkm::Id expectedValue = 0;
for (vtkm::Id vecIndex = 0; vecIndex < portal.GetNumberOfValues(); ++vecIndex)
{
for (vtkm::IdComponent componentIndex = 0;
componentIndex < portal.Get(vecIndex).GetNumberOfComponents();
componentIndex++)
{
VTKM_TEST_ASSERT(portal.Get(vecIndex)[componentIndex] == expectedValue,
"Got bad value.");
++expectedValue;
}
}
}
void ArrayHandleGroupVecBasic()
{
std::cout << "ArrayHandleGroupVec" << std::endl;
////
//// BEGIN-EXAMPLE ArrayHandleGroupVecBasic
////
// Create an array containing [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
using ArrayType = vtkm::cont::ArrayHandleIndex;
ArrayType sourceArray(12);
// Create an array containing [(0,1), (2,3), (4,5), (6,7), (8,9), (10,11)]
vtkm::cont::ArrayHandleGroupVec<ArrayType, 2> vec2Array(sourceArray);
// Create an array containing [(0,1,2), (3,4,5), (6,7,8), (9,10,11)]
vtkm::cont::ArrayHandleGroupVec<ArrayType, 3> vec3Array(sourceArray);
////
//// END-EXAMPLE ArrayHandleGroupVecBasic
////
CheckArray(vec2Array);
vtkm::cont::printSummary_ArrayHandle(vec3Array, std::cout);
std::cout << std::endl;
CheckArray(vec3Array);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleGroupVec
////
// Create an array containing [(0,1,2,3), (4,5,6,7), (8,9,10,11)]
vtkm::cont::make_ArrayHandleGroupVec<4>(sourceArray)
////
//// END-EXAMPLE MakeArrayHandleGroupVec
////
);
}
void ArrayHandleGroupVecVariable()
{
std::cout << "ArrayHandleGroupVecVariable" << std::endl;
////
//// BEGIN-EXAMPLE ArrayHandleGroupVecVariable
////
// Create an array of counts containing [4, 2, 3, 3]
vtkm::cont::ArrayHandle<vtkm::IdComponent> countArray =
vtkm::cont::make_ArrayHandle<vtkm::IdComponent>({ 4, 2, 3, 3 });
// Convert the count array to an offset array [0, 4, 6, 9, 12]
// Returns the number of total components: 12
vtkm::Id sourceArraySize;
using OffsetArrayType = vtkm::cont::ArrayHandle<vtkm::Id>;
OffsetArrayType offsetArray =
vtkm::cont::ConvertNumComponentsToOffsets(countArray, sourceArraySize);
//// PAUSE-EXAMPLE
vtkm::cont::printSummary_ArrayHandle(offsetArray, std::cout);
std::cout << std::endl;
VTKM_TEST_ASSERT(sourceArraySize == 12, "Bad source array size");
VTKM_TEST_ASSERT(offsetArray.GetNumberOfValues() == 5);
VTKM_TEST_ASSERT(offsetArray.ReadPortal().Get(0) == 0, "Unexpected offset value");
VTKM_TEST_ASSERT(offsetArray.ReadPortal().Get(1) == 4, "Unexpected offset value");
VTKM_TEST_ASSERT(offsetArray.ReadPortal().Get(2) == 6, "Unexpected offset value");
VTKM_TEST_ASSERT(offsetArray.ReadPortal().Get(3) == 9, "Unexpected offset value");
VTKM_TEST_ASSERT(offsetArray.ReadPortal().Get(4) == 12, "Unexpected offset value");
//// RESUME-EXAMPLE
// Create an array containing [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
using SourceArrayType = vtkm::cont::ArrayHandleIndex;
SourceArrayType sourceArray(sourceArraySize);
// Create an array containing [(0,1,2,3), (4,5), (6,7,8), (9,10,11)]
vtkm::cont::ArrayHandleGroupVecVariable<SourceArrayType, OffsetArrayType>
vecVariableArray(sourceArray, offsetArray);
////
//// END-EXAMPLE ArrayHandleGroupVecVariable
////
CheckArray(vecVariableArray);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleGroupVecVariable
////
// Create an array containing [(0,1,2,3), (4,5), (6,7,8), (9,10,11)]
vtkm::cont::make_ArrayHandleGroupVecVariable(sourceArray, offsetArray)
////
//// END-EXAMPLE MakeArrayHandleGroupVecVariable
////
);
}
void Test()
{
ArrayHandleGroupVecBasic();
ArrayHandleGroupVecVariable();
}
} // anonymous namespace
int GuideExampleArrayHandleGroupVec(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,114 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray1(const ArrayHandleType array)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == 3, "Permuted array has wrong size.");
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == 3, "Permuted portal has wrong size.");
VTKM_TEST_ASSERT(test_equal(portal.Get(0), 0.3), "Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(1), 0.0), "Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(2), 0.1), "Permuted array has wrong value.");
}
template<typename ArrayHandleType>
void CheckArray2(const ArrayHandleType array)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == 5, "Permuted array has wrong size.");
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == 5, "Permuted portal has wrong size.");
VTKM_TEST_ASSERT(test_equal(portal.Get(0), 0.1), "Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(1), 0.2), "Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(2), 0.2), "Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(3), 0.3), "Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(4), 0.0), "Permuted array has wrong value.");
}
void Test()
{
////
//// BEGIN-EXAMPLE ArrayHandlePermutation
////
using IdArrayType = vtkm::cont::ArrayHandle<vtkm::Id>;
using IdPortalType = IdArrayType::WritePortalType;
using ValueArrayType = vtkm::cont::ArrayHandle<vtkm::Float64>;
using ValuePortalType = ValueArrayType::WritePortalType;
// Create array with values [0.0, 0.1, 0.2, 0.3]
ValueArrayType valueArray;
valueArray.Allocate(4);
ValuePortalType valuePortal = valueArray.WritePortal();
valuePortal.Set(0, 0.0);
valuePortal.Set(1, 0.1);
valuePortal.Set(2, 0.2);
valuePortal.Set(3, 0.3);
// Use ArrayHandlePermutation to make an array = [0.3, 0.0, 0.1].
IdArrayType idArray1;
idArray1.Allocate(3);
IdPortalType idPortal1 = idArray1.WritePortal();
idPortal1.Set(0, 3);
idPortal1.Set(1, 0);
idPortal1.Set(2, 1);
vtkm::cont::ArrayHandlePermutation<IdArrayType, ValueArrayType> permutedArray1(
idArray1, valueArray);
//// PAUSE-EXAMPLE
CheckArray1(permutedArray1);
//// RESUME-EXAMPLE
// Use ArrayHandlePermutation to make an array = [0.1, 0.2, 0.2, 0.3, 0.0]
IdArrayType idArray2;
idArray2.Allocate(5);
IdPortalType idPortal2 = idArray2.WritePortal();
idPortal2.Set(0, 1);
idPortal2.Set(1, 2);
idPortal2.Set(2, 2);
idPortal2.Set(3, 3);
idPortal2.Set(4, 0);
vtkm::cont::ArrayHandlePermutation<IdArrayType, ValueArrayType> permutedArray2(
idArray2, valueArray);
//// PAUSE-EXAMPLE
CheckArray2(permutedArray2);
//// RESUME-EXAMPLE
////
//// END-EXAMPLE ArrayHandlePermutation
////
IdArrayType idArray = idArray2;
CheckArray2(
////
//// BEGIN-EXAMPLE MakeArrayHandlePermutation
////
vtkm::cont::make_ArrayHandlePermutation(idArray, valueArray)
////
//// END-EXAMPLE MakeArrayHandlePermutation
////
);
}
} // anonymous namespace
int GuideExampleArrayHandlePermutation(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,110 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleCompositeVector.h>
#include <vtkm/cont/ArrayHandleRandomStandardNormal.h>
#include <vtkm/cont/ArrayHandleRandomUniformBits.h>
#include <vtkm/cont/ArrayHandleRandomUniformReal.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
void Test()
{
////
//// BEGIN-EXAMPLE ArrayHandleRandomUniformBits
////
// Create an array containing a sequence of random bits seeded
// by std::random_device.
vtkm::cont::ArrayHandleRandomUniformBits randomArray(50);
// Create an array containing a sequence of random bits with
// a user supplied seed.
vtkm::cont::ArrayHandleRandomUniformBits randomArraySeeded(50, { 123 });
////
//// END-EXAMPLE ArrayHandleRandomUniformBits
////
////
//// BEGIN-EXAMPLE ArrayHandleRandomUniformBitsFunctional
////
// ArrayHandleRandomUniformBits is functional, it returns
// the same value for the same entry is accessed.
auto r0 = randomArray.ReadPortal().Get(5);
auto r1 = randomArray.ReadPortal().Get(5);
assert(r0 == r1);
////
//// END-EXAMPLE ArrayHandleRandomUniformBitsFunctional
////
// In case assert is an empty expression.
VTKM_TEST_ASSERT(r0 == r1);
////
//// BEGIN-EXAMPLE ArrayHandleRandomUniformBitsIteration
////
// Create a new insance of ArrayHandleRandomUniformBits
// for each set of random bits.
vtkm::cont::ArrayHandleRandomUniformBits randomArray0(50, { 0 });
vtkm::cont::ArrayHandleRandomUniformBits randomArray1(50, { 1 });
assert(randomArray0.ReadPortal().Get(5) != randomArray1.ReadPortal().Get(5));
////
//// END-EXAMPLE ArrayHandleRandomUniformBitsIteration
////
// In case assert is an empty expression.
VTKM_TEST_ASSERT(randomArray0.ReadPortal().Get(5) != randomArray1.ReadPortal().Get(5));
{
////
//// BEGIN-EXAMPLE ArrayHandleRandomUniformReal
////
constexpr vtkm::Id NumPoints = 50;
auto randomPointsInBox = vtkm::cont::make_ArrayHandleCompositeVector(
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::FloatDefault>(NumPoints),
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::FloatDefault>(NumPoints),
vtkm::cont::ArrayHandleRandomUniformReal<vtkm::FloatDefault>(NumPoints));
////
//// END-EXAMPLE ArrayHandleRandomUniformReal
////
VTKM_TEST_ASSERT(randomPointsInBox.GetNumberOfValues() == NumPoints);
auto portal = randomPointsInBox.ReadPortal();
for (vtkm::Id idx = 0; idx < NumPoints; ++idx)
{
vtkm::Vec3f value = portal.Get(idx);
VTKM_TEST_ASSERT((value[0] >= 0) && (value[0] <= 1));
VTKM_TEST_ASSERT((value[1] >= 0) && (value[1] <= 1));
VTKM_TEST_ASSERT((value[2] >= 0) && (value[2] <= 1));
}
}
{
////
//// BEGIN-EXAMPLE ArrayHandleRandomStandardNormal
////
constexpr vtkm::Id NumPoints = 50;
auto randomPointsInGaussian = vtkm::cont::make_ArrayHandleCompositeVector(
vtkm::cont::ArrayHandleRandomStandardNormal<vtkm::FloatDefault>(NumPoints),
vtkm::cont::ArrayHandleRandomStandardNormal<vtkm::FloatDefault>(NumPoints),
vtkm::cont::ArrayHandleRandomStandardNormal<vtkm::FloatDefault>(NumPoints));
////
//// END-EXAMPLE ArrayHandleRandomStandardNormal
////
VTKM_TEST_ASSERT(randomPointsInGaussian.GetNumberOfValues() == NumPoints);
}
}
} // anonymous namespace
int GuideExampleArrayHandleRandom(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,75 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleSwizzle.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray(const ArrayHandleType array)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == 3, "Permuted array has wrong size.");
auto portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == 3, "Permuted portal has wrong size.");
VTKM_TEST_ASSERT(test_equal(portal.Get(0), vtkm::Vec3f_64(0.2, 0.0, 0.3)),
"Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(1), vtkm::Vec3f_64(1.2, 1.0, 1.3)),
"Permuted array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(2), vtkm::Vec3f_64(2.2, 2.0, 2.3)),
"Permuted array has wrong value.");
}
void Test()
{
////
//// BEGIN-EXAMPLE ArrayHandleSwizzle
////
using ValueArrayType = vtkm::cont::ArrayHandle<vtkm::Vec4f_64>;
// Create array with values
// [ (0.0, 0.1, 0.2, 0.3), (1.0, 1.1, 1.2, 1.3), (2.0, 2.1, 2.2, 2.3) ]
ValueArrayType valueArray;
valueArray.Allocate(3);
auto valuePortal = valueArray.WritePortal();
valuePortal.Set(0, vtkm::make_Vec(0.0, 0.1, 0.2, 0.3));
valuePortal.Set(1, vtkm::make_Vec(1.0, 1.1, 1.2, 1.3));
valuePortal.Set(2, vtkm::make_Vec(2.0, 2.1, 2.2, 2.3));
// Use ArrayHandleSwizzle to make an array of Vec-3 with x,y,z,w swizzled to z,x,w
// [ (0.2, 0.0, 0.3), (1.2, 1.0, 1.3), (2.2, 2.0, 2.3) ]
vtkm::cont::ArrayHandleSwizzle<ValueArrayType, 3> swizzledArray(
valueArray, vtkm::IdComponent3(2, 0, 3));
////
//// END-EXAMPLE ArrayHandleSwizzle
////
CheckArray(swizzledArray);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleSwizzle
////
vtkm::cont::make_ArrayHandleSwizzle(valueArray, 2, 0, 3)
////
//// END-EXAMPLE MakeArrayHandleSwizzle
////
);
}
} // anonymous namespace
int GuideExampleArrayHandleSwizzle(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,76 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandleIndex.h>
#include <vtkm/cont/ArrayHandleView.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray(const ArrayHandleType array,
typename ArrayHandleType::ValueType firstValue,
vtkm::Id expectedLength)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == expectedLength, "Array has wrong size.");
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == expectedLength,
"Portal has wrong size.");
typename ArrayHandleType::ValueType expectedValue = firstValue;
for (vtkm::Id index = 0; index < expectedLength; index++)
{
VTKM_TEST_ASSERT(test_equal(portal.Get(index), expectedValue),
"Array has wrong value.");
expectedValue++;
}
}
void Test()
{
////
//// BEGIN-EXAMPLE ArrayHandleView
////
vtkm::cont::ArrayHandle<vtkm::Id> sourceArray;
vtkm::cont::ArrayCopy(vtkm::cont::ArrayHandleIndex(10), sourceArray);
// sourceArray has [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
vtkm::cont::ArrayHandleView<vtkm::cont::ArrayHandle<vtkm::Id>> viewArray(
sourceArray, 3, 5);
// viewArray has [3, 4, 5, 6, 7]
////
//// END-EXAMPLE ArrayHandleView
////
CheckArray(viewArray, 3, 5);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleView
////
vtkm::cont::make_ArrayHandleView(sourceArray, 3, 5)
////
//// END-EXAMPLE MakeArrayHandleView
////
,
3,
5);
}
} // anonymous namespace
int GuideExampleArrayHandleView(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,88 @@
//============================================================================
// 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.
//============================================================================
#include <vtkm/cont/ArrayHandleZip.h>
#include <vtkm/cont/testing/Testing.h>
namespace
{
template<typename ArrayHandleType>
void CheckArray(const ArrayHandleType array)
{
VTKM_TEST_ASSERT(array.GetNumberOfValues() == 3, "Permuted array has wrong size.");
typename ArrayHandleType::ReadPortalType portal = array.ReadPortal();
VTKM_TEST_ASSERT(portal.GetNumberOfValues() == 3, "Permuted portal has wrong size.");
using PairType = vtkm::Pair<vtkm::Id, vtkm::Float64>;
VTKM_TEST_ASSERT(test_equal(portal.Get(0), PairType(3, 0.0)),
"Zipped array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(1), PairType(0, 0.1)),
"Zipped array has wrong value.");
VTKM_TEST_ASSERT(test_equal(portal.Get(2), PairType(1, 0.2)),
"Zipped array has wrong value.");
}
void Test()
{
////
//// BEGIN-EXAMPLE ArrayHandleZip
////
using ArrayType1 = vtkm::cont::ArrayHandle<vtkm::Id>;
using PortalType1 = ArrayType1::WritePortalType;
using ArrayType2 = vtkm::cont::ArrayHandle<vtkm::Float64>;
using PortalType2 = ArrayType2::WritePortalType;
// Create an array of vtkm::Id with values [3, 0, 1]
ArrayType1 array1;
array1.Allocate(3);
PortalType1 portal1 = array1.WritePortal();
portal1.Set(0, 3);
portal1.Set(1, 0);
portal1.Set(2, 1);
// Create a second array of vtkm::Float32 with values [0.0, 0.1, 0.2]
ArrayType2 array2;
array2.Allocate(3);
PortalType2 portal2 = array2.WritePortal();
portal2.Set(0, 0.0);
portal2.Set(1, 0.1);
portal2.Set(2, 0.2);
// Zip the two arrays together to create an array of
// vtkm::Pair<vtkm::Id, vtkm::Float64> with values [(3,0.0), (0,0.1), (1,0.2)]
vtkm::cont::ArrayHandleZip<ArrayType1, ArrayType2> zipArray(array1, array2);
////
//// END-EXAMPLE ArrayHandleZip
////
CheckArray(zipArray);
CheckArray(
////
//// BEGIN-EXAMPLE MakeArrayHandleZip
////
vtkm::cont::make_ArrayHandleZip(array1, array2)
////
//// END-EXAMPLE MakeArrayHandleZip
////
);
}
} // anonymous namespace
int GuideExampleArrayHandleZip(int argc, char* argv[])
{
return vtkm::cont::testing::Testing::Run(Test, argc, argv);
}

@ -0,0 +1,632 @@
==============================
Fancy Array Handles
==============================
.. index::
double: array handle; fancy
One of the features of using :class:`vtkm::cont::ArrayHandle` is that it hides the implementation and layout of the array behind a generic interface.
This gives us the opportunity to replace a simple C array with some custom definition of the data and the code using the :class:`vtkm::cont::ArrayHandle` is none the wiser.
This gives us the opportunity to implement *fancy* arrays that do more than simply look up a value in an array.
For example, arrays can be augmented on the fly by mutating their indices or values.
Or values could be computed directly from the index so that no storage is required for the array at all.
|VTKm| provides many of the fancy arrays, which we explore in this section.
.. didyouknow::
One of the advantages of |VTKm|'s implementation of fancy arrays is that they can define whole arrays without actually storing and values.
For example, :class:`vtkm::cont::ArrayHandleConstant`, :class:`vtkm::cont::ArrayHandleIndex`, and :class:`vtkm::cont::ArrayHandleCounting` do not store data in any array in memory.
Rather, they construct the value for an index at runtime.
Likewise, arrays like :class:`vtkm::cont::ArrayHandlePermutation` construct new arrays from the values of other arrays without having to create a copy of the data.
.. didyouknow::
This chapter documents several array handle types that modify other array handles.
:chapref:`memory-layout:Memory Layout of Array Handles` has several similar examples of modifying basic arrays to represent data in different layouts.
The difference is that the fancy array handles in this chapter decorate other array handles of any type whereas those in :numref:`Chapter {number} <memory-layout:Memory Layout of Array Handles>` only decorate basic array handles.
If you do not find the fancy array handle you are looking for here, you might try that chapter.
------------------------------
Constant Arrays
------------------------------
.. index::
single: array handle; constant
single: constant array handle
A constant array is a fancy array handle that has the same value in all of its entries.
The constant array provides this array without actually using any memory.
Specifying a constant array in |VTKm| is straightforward.
|VTKm| has a class named :class:`vtkm::cont::ArrayHandleConstant`.
:class:`vtkm::cont::ArrayHandleConstant` is a templated class with a single template argument that is the type of value for each element in the array.
The constructor for :class:`vtkm::cont::ArrayHandleConstant` takes the value to provide by the array and the number of values the array should present.
The following example is a simple demonstration of the constant array handle.
.. doxygenclass:: vtkm::cont::ArrayHandleConstant
:members:
.. load-example:: ArrayHandleConstant
:file: GuideExampleArrayHandleConstant.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleConstant`.
The :file:`vtkm/cont/ArrayHandleConstant.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleConstant` that takes a value and a size for the array.
This function can sometimes be used to avoid having to declare the full array type.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleConstant
.. load-example:: MakeArrayHandleConstant
:file: GuideExampleArrayHandleConstant.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleConstant`.
------------------------------
Viewing a Subset of an Array
------------------------------
.. index::
single: array handle; view
single: view array handle
An array handle view is a fancy array handle that returns a subset of an already existing array handle.
The array handle view uses the same memory as the existing array handle the view was created from.
This means that changes to the data in the array handle view will also change the data in the original array handle.
.. doxygenclass:: vtkm::cont::ArrayHandleView
:members:
To use the :class:`vtkm::cont::ArrayHandleView` you must supply an :class:`vtkm::cont::ArrayHandle` to the :class:`vtkm::cont::ArrayHandleView` class constructor.
:class:`vtkm::cont::ArrayHandleView` is a templated class with a single template argument that is the :class:`vtkm::cont::ArrayHandle` type of the array that the view is being created from.
The constructor for :class:`vtkm::cont::ArrayHandleView` takes a target array, starting index, and length.
The following example shows a simple usage of the array handle view.
.. load-example:: ArrayHandleView
:file: GuideExampleArrayHandleView.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleView`.
The :file:`vtkm/cont/ArrayHandleView.h` header contains a templated convenience function :func:`vtkm::cont::make_ArrayHandleView` that takes a target array, index, and length.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleView
.. load-example:: MakeArrayHandleView
:file: GuideExampleArrayHandleView.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleView`.
------------------------------
Counting Arrays
------------------------------
.. index::
single: array handle; counting
single: counting array handle
single: array handle; index
single: index array handle
A counting array is a fancy array handle that provides a sequence of numbers.
These fancy arrays can represent the data without actually using any memory.
|VTKm| provides two versions of a counting array.
The first version is an index array that provides a specialized but common form of a counting array called an index array.
An index array has values of type :type:`vtkm::Id` that start at 0 and count up by 1 (i.e., :math:`0, 1, 2, 3,\ldots`).
The index array mirrors the array's index.
.. doxygenclass:: vtkm::cont::ArrayHandleIndex
:members:
Specifying an index array in |VTKm| is done with a class named :class:`vtkm::cont::ArrayHandleIndex`.
The constructor for :class:`vtkm::cont::ArrayHandleIndex` takes the size of the array to create.
The following example is a simple demonstration of the index array handle.
.. load-example:: ArrayHandleIndex
:file: GuideExampleArrayHandleCounting.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleIndex`.
A :func:`vtkm::cont::make_ArrayHandleIndex` convenience function is also available.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleIndex
The :class:`vtkm::cont::ArrayHandleCounting` class provides a more general form of counting.
:class:`vtkm::cont::ArrayHandleCounting` is a templated class with a single template argument that is the type of value for each element in the array.
The constructor for :class:`vtkm::cont::ArrayHandleCounting` takes three arguments: the start value (used at index 0), the step from one value to the next, and the length of the array.
The following example is a simple demonstration of the counting array handle.
.. doxygenclass:: vtkm::cont::ArrayHandleCounting
:members:
.. load-example:: ArrayHandleCountingBasic
:file: GuideExampleArrayHandleCounting.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleCounting`.
.. didyouknow::
In addition to being simpler to declare, :class:`vtkm::cont::ArrayHandleIndex` is slightly faster than :class:`vtkm::cont::ArrayHandleCounting`.
Thus, when applicable, you should prefer using :class:`vtkm::cont::ArrayHandleIndex`.
The :file:`vtkm/cont/ArrayHandleCounting.h` header also contains the templated convenience function :file:`vtkm::cont::make_ArrayHandleCounting` that also takes the start value, step, and length as arguments.
This function can sometimes be used to avoid having to declare the full array type.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleCounting
.. load-example:: MakeArrayHandleCountingBasic
:file: GuideExampleArrayHandleCounting.cxx
:caption: Using :file:`vtkm::cont::make_ArrayHandleCounting`.
There are no fundamental limits on how :class:`vtkm::cont::ArrayHandleCounting` counts.
For example, it is possible to count backwards.
.. load-example:: ArrayHandleCountingBackward
:file: GuideExampleArrayHandleCounting.cxx
:caption: Counting backwards with :class:`vtkm::cont::ArrayHandleCounting`.
It is also possible to use :class:`vtkm::cont::ArrayHandleCounting` to make sequences of :class:`vtkm::Vec` values with piece-wise counting in each of the components.
.. load-example:: ArrayHandleCountingVec
:file: GuideExampleArrayHandleCounting.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleCounting` with :class:`vtkm::Vec` objects.
------------------------------
Cast Arrays
------------------------------
.. index::
single: array handle; cast
single: cast array handle
A cast array is a fancy array that changes the type of the elements in an array.
The cast array provides this re-typed array without actually copying or generating any data.
Instead, casts are performed as the array is accessed.
|VTKm| has a class named :class:`vtkm::cont::ArrayHandleCast` to perform this implicit casting.
:class:`vtkm::cont::ArrayHandleCast` is a templated class with two template arguments.
The first argument is the type to cast values to.
The second argument is the type of the original :class:`vtkm::cont::ArrayHandle`.
The constructor to :class:`vtkm::cont::ArrayHandleCast` takes the :class:`vtkm::cont::ArrayHandle` to modify by casting.
.. doxygenclass:: vtkm::cont::ArrayHandleCast
:members:
.. load-example:: ArrayHandleCast
:file: GuideExampleArrayHandleCast.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleCast`.
The :file:`vtkm/cont/ArrayHandleCast.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleCast` that constructs the cast array.
The first argument is the original :class:`vtkm::cont::ArrayHandle` original array to cast.
The optional second argument is of the type to cast to (or you can optionally specify the cast-to type as a template argument.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleCast
.. load-example:: MakeArrayHandleCast
:file: GuideExampleArrayHandleCast.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleCast`.
------------------------------
Discard Arrays
------------------------------
.. index::
single: array handle; discard
single discard array handle
It is sometimes the case where you will want to run an operation in |VTKm| that fills values in two (or more) arrays, but you only want the values that are stored in one of the arrays.
It is possible to allocate space for both arrays and then throw away the values that you do not want, but that is a waste of memory.
It is also possible to rewrite the functionality to output only what you want, but that is a poor use of developer time.
To solve this problem easily, |VTKm| provides :class:`vtkm::cont::ArrayHandleDiscard`.
This array behaves similar to a regular :class:`vtkm::cont::ArrayHandle` in that it can be "allocated" and has size, but any values that are written to it are immediately discarded.
:class:`vtkm::cont::ArrayHandleDiscard` takes up no memory.
.. doxygenclass:: vtkm::cont::ArrayHandleDiscard
:members:
.. load-example:: ArrayHandleDiscard
:file: GuideExampleArrayHandleDiscard.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleDiscard`.}
------------------------------
Permuted Arrays
------------------------------
.. index::
single: array handle; permutation
single: permutation array handle
A permutation array is a fancy array handle that reorders the elements in an array.
Elements in the array can be skipped over or replicated.
The permutation array provides this reordered array without actually coping any data.
Instead, indices are adjusted as the array is accessed.
Specifying a permutation array in |VTKm| is straightforward.
|VTKm| has a class named :class:`vtkm::cont::ArrayHandlePermutation` that takes two arrays: an array of values and an array of indices that maps an index in the permutation to an index of the original values.
The index array is specified first.
The following example is a simple demonstration of the permutation array handle.
.. doxygenclass:: vtkm::cont::ArrayHandlePermutation
:members:
.. load-example:: ArrayHandlePermutation
:file: GuideExampleArrayHandlePermutation.cxx
:caption: Using :class:`vtkm::cont::ArrayHandlePermutation`.
The :file:`vtkm/cont/ArrayHandlePermutation.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandlePermutation` that takes instances of the index and value array handles and returns a permutation array.
This function can sometimes be used to avoid having to declare the full array type.
.. doxygenfunction:: vtkm::cont::make_ArrayHandlePermutation
.. load-example:: MakeArrayHandlePermutation
:file: GuideExampleArrayHandlePermutation.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandlePermutation`.
.. commonerrors::
When using an :class:`vtkm::cont::ArrayHandlePermutation`, take care that all the provided indices in the index array point to valid locations in the values array.
Bad indices can cause reading from or writing to invalid memory locations, which can be difficult to debug.
Also, be wary about having duplicate indices, which means that multiple array entries point to the same memory location.
This will work fine when using the array as input, but will cause a dangerous race condition if used as an output.
.. didyouknow::
You can write to a :class:`vtkm::cont::ArrayHandlePermutation` by, for example, using it as an output array.
Writes to the :class:`vtkm::cont::ArrayHandlePermutation` will go to the respective location in the source array.
However, :class:`vtkm::cont::ArrayHandlePermutation` cannot be resized.
------------------------------
Zipped Arrays
------------------------------
.. index::
single: array handle; zipped
single: zipped array handle
A zip array is a fancy array handle that combines two arrays of the same size to pair up the corresponding values.
Each element in the zipped array is a :class:`vtkm::Pair` containing the values of the two respective arrays.
These pairs are not stored in their own memory space.
Rather, the pairs are generated as the array is used.
Writing a pair to the zipped array writes the values in the two source arrays.
Specifying a zipped array in |VTKm| is straightforward.
|VTKm| has a class named :class:`vtkm::cont::ArrayHandleZip` that takes the two arrays providing values for the first and second entries in the pairs.
The following example is a simple demonstration of creating a zip array handle.
.. doxygenclass:: vtkm::cont::ArrayHandleZip
:members:
.. load-example:: ArrayHandleZip
:file: GuideExampleArrayHandleZip.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleZip`.
The :file:`vtkm/cont/ArrayHandleZip.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleZip` that takes instances of the two array handles and returns a zip array.
This function can sometimes be used to avoid having to declare the full array type.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleZip
.. load-example:: MakeArrayHandleZip
:file: GuideExampleArrayHandleZip.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleZip`.
------------------------------
Coordinate System Arrays
------------------------------
Many of the data structures we use in |VTKm| are described in a 3D coordinate system.
Although, as we will see in :chapref:`dataset:Data Sets`, we can use any :class:`vtkm::cont::ArrayHandle` to store point coordinates, including a raw array of 3D vectors, there are some common patterns for point coordinates that we can use specialized arrays to better represent the data.
.. index::
double: array handle; uniform point coordinates
There are two fancy array handles that each handle a special form of coordinate system.
The first such array handle is :class:`vtkm::cont::ArrayHandleUniformPointCoordinates`, which represents a uniform sampling of space.
The constructor for :class:`vtkm::cont::ArrayHandleUniformPointCoordinates` takes three arguments.
The first argument is a :type:`vtkm::Id3` that specifies the number of samples in the :math:`x`, :math:`y`, and :math:`z` directions.
The second argument, which is optional, specifies the origin (the location of the first point at the lower left corner).
If not specified, the origin is set to :math:`[0,0,0]`.
The third argument, which is also optional, specifies the distance between samples in the :math:`x`, :math:`y`, and :math:`z` directions.
If not specified, the spacing is set to 1 in each direction.
.. doxygenclass:: vtkm::cont::ArrayHandleUniformPointCoordinates
:members:
.. load-example:: ArrayHandleUniformPointCoordinates
:file: GuideExampleArrayHandleCoordinateSystems.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleUniformPointCoordinates`.
.. index::
double: array handle; Cartesian product
double: array handle; rectilinear point coordinates
The second fancy array handle for special coordinate systems is :class:`vtkm::cont::ArrayHandleCartesianProduct`, which represents a rectilinear sampling of space where the samples are axis aligned but have variable spacing.
Sets of coordinates of this type are most efficiently represented by having a separate array for each component of the axis, and then for each :math:`[i,j,k]` index of the array take the value for each component from each array using the respective index.
This is equivalent to performing a Cartesian product on the arrays.
.. doxygenclass:: vtkm::cont::ArrayHandleCartesianProduct
:members:
:class:`vtkm::cont::ArrayHandleCartesianProduct` is a templated class.
It has three template parameters, which are the types of the arrays used for the :math:`x`, :math:`y`, and :math:`z` axes.
The constructor for :class:`vtkm::cont::ArrayHandleCartesianProduct` takes the three arrays.
.. load-example:: ArrayHandleCartesianProduct
:file: GuideExampleArrayHandleCoordinateSystems.cxx
:caption: Using a :class:`vtkm::cont::ArrayHandleCartesianProduct`.
The :file:`vtkm/cont/ArrayHandleCartesianProduct.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleCartesianProduct` that takes the three axis arrays and returns an array of the Cartesian product.
This function can sometimes be used to avoid having to declare the full array type.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleCartesianProduct
.. load-example:: MakeArrayHandleCartesianProduct
:file: GuideExampleArrayHandleCoordinateSystems.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleCartesianProduct`.
.. didyouknow::
These specialized arrays for coordinate systems greatly reduce the code duplication in |VTKm|.
Most scientific visualization systems need separate implementations of algorithms for uniform, rectilinear, and unstructured grids.
But in |VTKm| an algorithm can be written once and then applied to all these different grid structures by using these specialized array handles and letting the compiler's templates optimize the code.
.. didyouknow::
The special array handles in this section are designed to represent point coordinates in particular, common configurations.
However, the array for a :class:`vtkm::cont::CoordinateSystem` does not have to be one of these arrays.
For example, it is common to use a :class:`vtkm::cont::ArrayHandleBasic` to represent points in general position.
------------------------------
Composite Vector Arrays
------------------------------
.. index::
double: array handle; composite vector
A composite vector array is a fancy array handle that combines two to four arrays of the same size and value type and combines their corresponding values to form a :class:`vtkm::Vec`.
A composite vector array is similar in nature to a zipped array (described in :secref:`fancy-array-handles:Zipped Arrays`) except that values are combined into :class:`vtkm::Vec`'s instead of :class:`vtkm::Pair`'s.
The composite vector array is also similar to a structure of arrays (described in :secref:`memory-layout:Structure of Arrays`) except that any type of array handles can be used for the components rather than a basic array handle.
The created :class:`vtkm::Vec`'s are not stored in their own memory space.
Rather, the :class:`vtkm::Vec`'s are generated as the array is used.
Writing :class:`vtkm::Vec`'s to the composite vector array writes values into the components of the source arrays.
A composite vector array can be created using the :class:`vtkm::cont::ArrayHandleCompositeVector` class.
This class has a variadic template argument that is a "signature" for the arrays to be combined.
The constructor for :class:`vtkm::cont::ArrayHandleCompositeVector` takes instances of the array handles to combine.
.. doxygenclass:: vtkm::cont::ArrayHandleCompositeVector
:members:
.. load-example:: ArrayHandleCompositeVectorBasic
:file: GuideExampleArrayHandleCompositeVector.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleCompositeVector`.
The :file:`vtkm/cont/ArrayHandleCompositeVector.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleCompositeVector` which takes a variable number of array handles and returns an :class:`vtkm::cont::ArrayHandleCompositeVector`.
This function can sometimes be used to avoid having to declare the full array type.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleCompositeVector
.. load-example:: MakeArrayHandleCompositeVector
:file: GuideExampleArrayHandleCompositeVector.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleCompositeVector`.
------------------------------
Extract Component Arrays
------------------------------
.. index::
double: array handle; extract component
Component extraction allows access to a single component of an :class:`vtkm::cont::ArrayHandle` with a :class:`vtkm::Vec` as the :member:`vtkm::cont::ArrayHandle::ValueType`.
:class:`vtkm::cont::ArrayHandleExtractComponent` allows one component of a vector array to be extracted without creating a copy of the data.
:class:`vtkm::cont::ArrayHandleExtractComponent` can also be combined with :class:`vtkm::cont::ArrayHandleCompositeVector` (described in :secref:`fancy-array-handles:Composite Vector Arrays`) to arbitrarily stitch several components from multiple arrays together.
.. doxygenclass:: vtkm::cont::ArrayHandleExtractComponent
:members:
As a simple example, consider an :class:`vtkm::cont::ArrayHandle` containing 3D coordinates for a collection of points and a filter that only operates on the points' elevations (Z, in this example).
We can easily create the elevation array on-the-fly without allocating a new array as in the following example.
.. load-example:: ArrayHandleExtractComponent
:file: GuideExampleArrayHandleExtractComponent.cxx
:caption: Extracting components of :class:`vtkm::Vec`'s in an array with :class:`vtkm::cont::ArrayHandleExtractComponent`.
The :file:`vtkm/cont/ArrayHandleExtractComponent.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleExtractComponent` that takes an :class:`vtkm::cont::ArrayHandle` of :class:`vtkm::Vec`'s and :type:`vtkm::IdComponent` which returns an appropriately typed :class:`vtkm::cont::ArrayHandleExtractComponent` containing the values for a specified component.
The index of the component to extract is provided as an argument to :func:`vtkm::cont::make_ArrayHandleExtractComponent`, which is required.
The use of :func:`vtkm::cont::make_ArrayHandleExtractComponent` can be used to avoid having to declare the full array type.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleExtractComponent
.. load-example:: MakeArrayHandleExtractComponent
:file: GuideExampleArrayHandleExtractComponent.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleExtractComponent`.
.. didyouknow::
An alternate way to extract a component from a :class:`vtkm::cont::ArrayHandle` is to use the :func:`vtkm::cont::ArrayExtractComponent` function.
Rather than wrap a :class:`vtkm::cont::ArrayHandleExtractComponent` around the target array, it converts the array into a :class:`vtkm::cont::ArrayHandleStride`, as described in :secref:`memory-layout:Strided Arrays`.
This can be advantageous when trying to unify the storage type of different array types, but can work poorly for some array types.
------------------------------
Swizzle Arrays
------------------------------
.. index::
double: array handle; swizzle
It is often useful to reorder or remove specific components from an :class:`vtkm::cont::ArrayHandle` with a :class:`vtkm::Vec` :member:`vtkm::cont::ArrayHandle::ValueType`.
:class:`vtkm::cont::ArrayHandleSwizzle` provides an easy way to accomplish this.
The constructor of :class:`vtkm::cont::ArrayHandleSwizzle` specifies a "component map," which defines the swizzle operation.
This map consists of the components from the input :class:`vtkm::cont::ArrayHandle`, which will be exposed in the :class:`vtkm::cont::ArrayHandleSwizzle`.
For instance, constructing ``vtkm::cont::ArrayHandleSwizzle<Some3DArrayType, 3>`` with ``vtkm::IdComponent3(0, 2, 1)`` as the second constructor argument will allow access to a 3D array, but with the Y and Z components exchanged.
This rearrangement does not create a copy, and occurs on-the-fly as data are accessed through the :class:`vtkm::cont::ArrayHandleSwizzle`'s portal.
This fancy array handle can also be used to eliminate unnecessary components from an :class:`vtkm::cont::ArrayHandle`'s data, as shown below.
.. doxygenclass:: vtkm::cont::ArrayHandleSwizzle
:members:
.. load-example:: ArrayHandleSwizzle
:file: GuideExampleArrayHandleSwizzle.cxx
:caption: Swizzling components of :class:`vtkm::Vec`'s in an array with :class:`vtkm::cont::ArrayHandleSwizzle`.
The :file:`vtkm/cont/ArrayHandleSwizzle.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleSwizzle` that takes an :class:`vtkm::cont::ArrayHandle` of :class:`vtkm::Vec`'s and returns an appropriately typed :class:`vtkm::cont::ArrayHandleSwizzle` containing swizzled vectors.
The use of :func:`vtkm::cont::make_ArrayHandleSwizzle` can be used to avoid having to declare the full array type.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleSwizzle(const ArrayHandleType&, const vtkm::Vec<vtkm::IdComponent, OutSize>&)
.. doxygenfunction:: vtkm::cont::make_ArrayHandleSwizzle(const ArrayHandleType&, vtkm::IdComponent, SwizzleIndexTypes...)
.. load-example:: MakeArrayHandleSwizzle
:file: GuideExampleArrayHandleSwizzle.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleSwizzle`.
------------------------------
Grouped Vector Arrays
------------------------------
.. index::
double: array handle; group vector
A grouped vector array is a fancy array handle that groups consecutive values of an array together to form a :class:`vtkm::Vec`.
The source array must be of a length that is divisible by the requested :class:`vtkm::Vec` size.
The created :class:`vtkm::Vec`'s are not stored in their own memory space.
Rather, the :class:`vtkm::Vec`'s are generated as the array is used.
Writing :class:`vtkm::Vec`'s to the grouped vector array writes values into the the source array.
A grouped vector array is created using the :class:`vtkm::cont::ArrayHandleGroupVec` class.
This templated class has two template arguments.
The first argument is the type of array being grouped and the second argument is an integer specifying the size of the :class:`vtkm::Vec`'s to create (the number of values to group together).
.. doxygenclass:: vtkm::cont::ArrayHandleGroupVec
:members:
.. load-example:: ArrayHandleGroupVecBasic
:file: GuideExampleArrayHandleGroupVec.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleGroupVec`.
The :file:`vtkm/cont/ArrayHandleGroupVec.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleGroupVec` that takes an instance of the array to group into :class:`vtkm::Vec`'s.
You must specify the size of the :class:`vtkm::Vec`'s as a template parameter when using :func:`vtkm::cont::make_ArrayHandleGroupVec`.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleGroupVec
.. load-example:: MakeArrayHandleGroupVec
:file: GuideExampleArrayHandleGroupVec.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleGroupVec`.
.. didyouknow::
:class:`vtkm::cont::ArrayHandleGroupVec` requires you to specify the number of components at compile time.
For a similar functionality, consider using :class:`vtkm::cont::ArrayHandleRuntimeVec`, described in :secref:`memory-layout:Runtime Vec Arrays`.
This allows the runtime selection of :class:`vtkm::Vec` sizes and can be applied to existing basic arrays, but is limited in other ways.
:class:`vtkm::cont::ArrayHandleGroupVec` is handy when you need to build an array of vectors that are all of the same length, but what about when you need an array of vectors of different lengths?
One common use case for this is if you are defining a collection of polygons of different sizes (triangles, quadrilaterals, pentagons, and so on).
We would like to define an array such that the data for each polygon were stored in its own :class:`vtkm::Vec` (or, rather, |Veclike|) object.
:class:`vtkm::cont::ArrayHandleGroupVecVariable` does just that.
:class:`vtkm::cont::ArrayHandleGroupVecVariable` takes two arrays. The first array, identified as the "source" array, is a flat representation of the values (much like the array used with :class:`vtkm::cont::ArrayHandleGroupVec`).
The second array, identified as the "offsets" array, provides for each vector the index into the source array where the start of the vector is.
The offsets array must be monotonically increasing.
The size of the offsets array is one greater than the number of vectors in the resulting array.
The first offset is always 0 and the last offset is always the size of the input source array.
The first and second template parameters to :class:`vtkm::cont::ArrayHandleGroupVecVariable` are the types for the source and offset arrays, respectively.
.. doxygenclass:: vtkm::cont::ArrayHandleGroupVecVariable
:members:
It is often the case that you will start with a group of vector lengths rather than offsets into the source array.
If this is the case, then the :func:`vtkm::cont::ConvertNumComponentsToOffsets` helper function can convert an array of vector lengths to an array of offsets.
The first argument to this function is always the array of vector lengths.
The second argument, which is optional, is a reference to a :class:`vtkm::cont::ArrayHandle` into which the offsets should be stored.
If this offset array is not specified, an :class:`vtkm::cont::ArrayHandle` will be returned from the function instead.
The third argument, which is also optional, is a reference to a :type:`vtkm::Id` into which the expected size of the source array is put.
Having the size of the source array is often helpful, as it can be used to allocate data for the source array or check the source array's size.
It is also OK to give the expected size reference but not the offset array reference.
.. doxygenfunction:: vtkm::cont::ConvertNumComponentsToOffsets(const vtkm::cont::UnknownArrayHandle&, vtkm::cont::ArrayHandle<vtkm::Id>&, vtkm::Id&, vtkm::cont::DeviceAdapterId)
.. load-example:: ArrayHandleGroupVecVariable
:file: GuideExampleArrayHandleGroupVec.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleGroupVecVariable`.
The :file:`vtkm/cont/ArrayHandleGroupVecVariable.h` header also contains the templated convenience function :func:`vtkm::cont::make_ArrayHandleGroupVecVariable` that takes an instance of the source array to group into |Veclike| objects and the offset array.
.. doxygenfunction:: vtkm::cont::make_ArrayHandleGroupVecVariable
.. load-example:: MakeArrayHandleGroupVecVariable
:file: GuideExampleArrayHandleGroupVec.cxx
:caption: Using :func:`vtkm::cont::make_ArrayHandleGroupVecVariable`.
.. didyouknow::
You can write to :class:`vtkm::cont::ArrayHandleGroupVec` and :class:`vtkm::cont::ArrayHandleGroupVecVariable` by, for example, using it as an output array.
Writes to these arrays will go to the respective location in the source array.
:class:`vtkm::cont::ArrayHandleGroupVec` can also be allocated and resized (which in turn causes the source array to be allocated).
However, :class:`vtkm::cont::ArrayHandleGroupVecVariable` cannot be resized and the source array must be pre-allocated.
You can use the source array size value returned from :func:`vtkm::cont::ConvertNumComponentsToOffsets` to allocate source arrays.
.. commonerrors::
Keep in mind that the values stored in a :class:`vtkm::cont::ArrayHandleGroupVecVariable` are not actually :class:`vtkm::Vec` objects.
Rather, they are "|Veclike|" objects, which has some subtle but important ramifications.
First, the type will not match the :class:`vtkm::Vec` template, and there is no automatic conversion to :class:`vtkm::Vec` objects.
Thus, many functions that accept :class:`vtkm::Vec` objects as parameters will not accept the |Veclike| object.
Second, the size of |Veclike| objects are not known until runtime.
See :secref:`base-types:Vector Types` and :secref:`advanced-types:Vector Traits` for more information on the difference between :class:`vtkm::Vec` and |Veclike| objects.
------------------------------
Random Arrays
------------------------------
.. index::
double: array handle; random
The basis of generating random numbers in |VTKm| is built on the :class:`vtkm::cont::ArrayHandleRandomUniformBits`.
An uniform random bits array is a fancy array handle that generates pseudo random bits as :type:`vtkm::Unit64` in its entries.
The uniform random bits array provides this array without actually using any memory.
.. doxygenclass:: vtkm::cont::ArrayHandleRandomUniformBits
:members:
The constructor for :class:`vtkm::cont::ArrayHandleRandomUniformBits` takes two arguments: the first argument is the length of the array handle, the second is a seed of type ``vtkm::Vec<Uint32, 1>``.
If the seed is not specified, the C++11 ``std::random_device`` is used as default.
.. load-example:: ArrayHandleRandomUniformBits
:file: GuideExampleArrayHandleRandom.cxx
:caption: Using :class:`vtkm::cont::ArrayHandleRandomUniformBits`.
:class:`vtkm::cont::ArrayHandleRandomUniformBits` is functional, in the sense that once an instance of :class:`vtkm::cont::ArrayHandleRandomUniformBits` is created, its content does not change and always returns the same :type:`vtkm::UInt64` value given the same index.
.. load-example:: ArrayHandleRandomUniformBitsFunctional
:file: GuideExampleArrayHandleRandom.cxx
:caption: :class:`vtkm::cont::ArrayHandleRandomUniformBits` is functional.
To generate a new set of random bits, we need to create another instance of :class:`vtkm::cont::ArrayHandleRandomUniformBits` with a different seed, we can either let ``std::random_device`` provide a unique seed or use some unique identifier such as iteration number as the seed.
.. load-example:: ArrayHandleRandomUniformBitsIteration
:file: GuideExampleArrayHandleRandom.cxx
:caption: Independent :class:`vtkm::cont::ArrayHandleRandomUniformBits`.
The random bits provided by :class:`vtkm::cont::ArrayHandleRandomUniformBits` can be manipulated to provide random numbers with specific distributions.
|VTKm| provides some specialized classes that implement common distributions.
The :class:`vtkm::cont::ArrayHandleRandomUniformReal` class generates an array of numbers sampled from a real uniform distribution in the range :math:`[0, 1)`.
.. doxygenclass:: vtkm::cont::ArrayHandleRandomUniformReal
:members:
.. load-example:: ArrayHandleRandomUniformReal
:file: GuideExampleArrayHandleRandom.cxx
:caption: Generating a random cloud of point coordinates in the box bounded by [0, 1].
The :class:`vtkm::cont::ArrayHandleRandomStandardNormal` class generates an array of numbers sampled from a standard normal distribution.
This provides a set of points centered at 0 and with probability exponentially diminishing away from 0 in both the positive and negative directions.
.. doxygenclass:: vtkm::cont::ArrayHandleRandomStandardNormal
:members:
.. load-example:: ArrayHandleRandomStandardNormal
:file: GuideExampleArrayHandleRandom.cxx
:caption: Generating a random cloud of point coordinates in a Gaussian distribution centered at the origin.
.. didyouknow::
The distributions of the provided random array handles can manipulated by shifting and scaling the values they provide.
This will keep the general distribution shape but change the range.
This manipulation can happen in a worklet from the values returned from the arrays or they can be generated automatically by wrapping the random arrays in a :class:`vtkm::cont::ArrayHandleTransform`.
.. todo:: Add a reference to the section describing :class:`vtkm::cont::ArrayHandleTransform`.

@ -13,3 +13,4 @@ Advanced Development
math.rst
working-with-cells.rst
memory-layout.rst
fancy-array-handles.rst

@ -350,6 +350,8 @@ public:
SecondHandleType,
ThirdHandleType>::Superclass));
/// Construct an `ArrayHandleCartesianProduct` given arrays for the coordinates in
/// the x, y, and z diretions.
VTKM_CONT
ArrayHandleCartesianProduct(const FirstHandleType& firstArray,
const SecondHandleType& secondArray,
@ -365,14 +367,17 @@ public:
///
~ArrayHandleCartesianProduct() {}
/// Get the array for the coordinates in the x direction.
VTKM_CONT FirstHandleType GetFirstArray() const
{
return StorageType::GetArrayHandle1(this->GetBuffers());
}
/// Get the array for the coordinates in the y direction.
VTKM_CONT SecondHandleType GetSecondArray() const
{
return StorageType::GetArrayHandle2(this->GetBuffers());
}
/// Get the array for the coordinates in the z direction.
VTKM_CONT ThirdHandleType GetThirdArray() const
{
return StorageType::GetArrayHandle3(this->GetBuffers());

@ -151,6 +151,7 @@ public:
T,
StorageTagCast<typename ArrayHandleType::ValueType, typename ArrayHandleType::StorageTag>>));
/// Construct an `ArrayHandleCast` from a source array handle.
ArrayHandleCast(const vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
typename ArrayHandleType::StorageTag>& handle)
: Superclass(Superclass::StorageType::CreateBuffers(handle))
@ -158,11 +159,10 @@ public:
this->ValidateTypeCast<typename ArrayHandleType::ValueType>();
}
/// Implemented so that it is defined exclusively in the control environment.
/// If there is a separate device for the execution environment (for example,
/// with CUDA), then the automatically generated destructor could be
/// created for all devices, and it would not be valid for all devices.
///
// Implemented so that it is defined exclusively in the control environment.
// If there is a separate device for the execution environment (for example,
// with CUDA), then the automatically generated destructor could be
// created for all devices, and it would not be valid for all devices.
~ArrayHandleCast() {}
/// \brief Returns the `ArrayHandle` that is being transformed.
@ -246,7 +246,7 @@ struct MakeArrayHandleCastImpl<T, T, ArrayType>
} // namespace detail
/// make_ArrayHandleCast is convenience function to generate an
/// `make_ArrayHandleCast` is convenience function to generate an
/// ArrayHandleCast.
///
template <typename T, typename ArrayType>

@ -390,18 +390,21 @@ struct Storage<T, vtkm::cont::StorageTagCompositeVec<StorageTag>> : Storage<T, S
} // namespace internal
/// \brief An \c ArrayHandle that combines components from other arrays.
/// @brief An `ArrayHandle` that combines components from other arrays.
///
/// \c ArrayHandleCompositeVector is a specialization of \c ArrayHandle that
/// `ArrayHandleCompositeVector` is a specialization of `ArrayHandle` that
/// derives its content from other arrays. It takes any number of
/// single-component \c ArrayHandle objects and mimics an array that contains
/// vectors with components that come from these delegate arrays.
///
/// The easiest way to create and type an \c ArrayHandleCompositeVector is
/// The easiest way to create and type an `ArrayHandleCompositeVector` is
/// to use the \c make_ArrayHandleCompositeVector functions.
///
/// The \c ArrayHandleExtractComponent class may be helpful when a desired
/// component is part of an \c ArrayHandle with a \c vtkm::Vec \c ValueType.
/// The `ArrayHandleExtractComponent` class may be helpful when a desired
/// component is part of an `ArrayHandle` with a `vtkm::Vec` `ValueType`.
///
/// If you are attempted to combine components that you know are stored in
/// basic `ArrayHandle`s, consider using `ArrayHandleSOA` instead.
///
template <typename... ArrayTs>
class ArrayHandleCompositeVector
@ -413,12 +416,14 @@ public:
(ArrayHandleCompositeVector<ArrayTs...>),
(typename internal::CompositeVectorTraits<ArrayTs...>::Superclass));
/// Construct an `ArrayHandleCompositeVector` from a set of component vectors.
VTKM_CONT
ArrayHandleCompositeVector(const ArrayTs&... arrays)
: Superclass(StorageType::CreateBuffers(arrays...))
{
}
/// Return the arrays of all of the components in a `vtkm::Tuple` object.
VTKM_CONT vtkm::Tuple<ArrayTs...> GetArrayTuple() const
{
return StorageType::GetArrayTuple(this->GetBuffers());

@ -58,9 +58,9 @@ struct Storage<T, vtkm::cont::StorageTagConstant> : Storage<T, StorageTagConstan
} // namespace internal
/// \brief An array handle with a constant value.
/// @brief An array handle with a constant value.
///
/// ArrayHandleConstant is an implicit array handle with a constant value. A
/// `ArrayHandleConstant` is an implicit array handle with a constant value. A
/// constant array handle is constructed by giving a value and an array length.
/// The resulting array is of the given size with each entry the same value
/// given in the constructor. The array is defined implicitly, so there it
@ -74,6 +74,7 @@ public:
(ArrayHandleConstant<T>),
(vtkm::cont::ArrayHandle<T, vtkm::cont::StorageTagConstant>));
/// Construct a constant array containing the given value.
VTKM_CONT
ArrayHandleConstant(T value, vtkm::Id numberOfValues = 0)
: Superclass(internal::FunctorToArrayHandleImplicitBuffers(internal::ConstantFunctor<T>(value),
@ -81,17 +82,15 @@ public:
{
}
/// \brief Returns the constant value stored in this array.
/// @brief Returns the constant value stored in this array.
///
/// The value set in the constructor of this array is returned even if the number of values is 0.
///
VTKM_CONT T GetValue() const { return this->ReadPortal().GetFunctor()(0); }
};
/// make_ArrayHandleConstant is convenience function to generate an
/// ArrayHandleImplicit. It takes a functor and the virtual length of the
/// array.
///
/// `make_ArrayHandleConstant` is convenience function to generate an
/// ArrayHandleImplicit.
template <typename T>
vtkm::cont::ArrayHandleConstant<T> make_ArrayHandleConstant(T value, vtkm::Id numberOfValues)
{

@ -31,7 +31,7 @@ struct VTKM_ALWAYS_EXPORT StorageTagCounting
namespace internal
{
/// \brief An implicit array portal that returns an counting value.
/// \brief An implicit array portal that returns a counting value.
template <class CountingValueType>
class VTKM_ALWAYS_EXPORT ArrayPortalCounting
{
@ -48,6 +48,11 @@ public:
{
}
/// @brief Create an implicit counting array.
///
/// @param start The starting value in the first value of the array.
/// @param step The increment between sequential values in the array.
/// @param numValues The size of the array.
VTKM_EXEC_CONT
ArrayPortalCounting(ValueType start, ValueType step, vtkm::Id numValues)
: Start(start)
@ -56,15 +61,19 @@ public:
{
}
/// Returns the starting value.
VTKM_EXEC_CONT
ValueType GetStart() const { return this->Start; }
/// Returns the step value.
VTKM_EXEC_CONT
ValueType GetStep() const { return this->Step; }
/// Returns the number of values in the array.
VTKM_EXEC_CONT
vtkm::Id GetNumberOfValues() const { return this->NumberOfValues; }
/// Returns the value for the given index.
VTKM_EXEC_CONT
ValueType Get(vtkm::Id index) const
{

@ -178,14 +178,14 @@ namespace vtkm
namespace cont
{
/// \brief A fancy ArrayHandle that turns a vector array into a scalar array by
/// @brief A fancy `ArrayHandle` that turns a vector array into a scalar array by
/// slicing out a single component of each vector.
///
/// ArrayHandleExtractComponent is a specialization of ArrayHandle. It takes an
/// input ArrayHandle with a vtkm::Vec ValueType and a component index
/// `ArrayHandleExtractComponent` is a specialization of `ArrayHandle`. It takes an
/// input `ArrayHandle` with a `vtkm::Vec` `ValueType` and a component index
/// and uses this information to expose a scalar array consisting of the
/// specified component across all vectors in the input ArrayHandle. So for a
/// given index i, ArrayHandleExtractComponent looks up the i-th vtkm::Vec in
/// specified component across all vectors in the input `ArrayHandle`. So for a
/// given index i, `ArrayHandleExtractComponent` looks up the i-th `vtkm::Vec` in
/// the index array and reads or writes to the specified component, leave all
/// other components unmodified. This is done on the fly rather than creating a
/// copy of the array.
@ -203,17 +203,20 @@ public:
typename vtkm::VecTraits<typename ArrayHandleType::ValueType>::ComponentType,
StorageTagExtractComponent<ArrayHandleType>>));
/// Construct an `ArrayHandleExtractComponent` with a given array and component.
VTKM_CONT
ArrayHandleExtractComponent(const ArrayHandleType& array, vtkm::IdComponent component)
: Superclass(StorageType::CreateBuffers(component, array))
{
}
/// Get the component index being extracted from the source array.
VTKM_CONT vtkm::IdComponent GetComponent() const
{
return StorageType::ComponentIndex(this->GetBuffers());
}
/// Get the source array of `Vec`s to get a component out of.
VTKM_CONT ArrayHandleType GetArray() const
{
using BaseArray = vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
@ -222,8 +225,8 @@ public:
}
};
/// make_ArrayHandleExtractComponent is convenience function to generate an
/// ArrayHandleExtractComponent.
/// `make_ArrayHandleExtractComponent` is convenience function to generate an
/// `ArrayHandleExtractComponent`.
template <typename ArrayHandleType>
VTKM_CONT ArrayHandleExtractComponent<ArrayHandleType> make_ArrayHandleExtractComponent(
const ArrayHandleType& array,

@ -192,21 +192,21 @@ public:
} // namespace internal
/// \brief Fancy array handle that groups values into vectors.
/// @brief Fancy array handle that groups values into vectors.
///
/// It is sometimes the case that an array is stored such that consecutive
/// entries are meant to form a group. This fancy array handle takes an array
/// of values and a size of groups and then groups the consecutive values
/// stored in a \c Vec.
/// stored in a `vtkm::Vec`.
///
/// For example, if you have an array handle with the six values 0,1,2,3,4,5
/// and give it to a \c ArrayHandleGroupVec with the number of components set
/// to 3, you get an array that looks like it contains two values of \c Vec
/// values of size 3 with the data [0,1,2], [3,4,5].
/// and give it to a `ArrayHandleGroupVec` with the number of components set
/// to 3, you get an array that looks like it contains two values of `vtkm::Vec`
/// of size 3 with the data [0,1,2], [3,4,5].
///
/// The array of components should have a number of values that divides evenly
/// with the size of the Vec. If the components array does not divide evenly
/// into `Vec`s, then a warning will be logged and the extra component values
/// with the size of the `vtkm::Vec`. If the components array does not divide evenly
/// into `vtkm::Vec`s, then a warning will be logged and the extra component values
/// will be ignored.
///
template <typename ComponentsArrayHandleType, vtkm::IdComponent NUM_COMPONENTS>
@ -229,19 +229,21 @@ public:
using ComponentType = typename ComponentsArrayHandleType::ValueType;
/// Construct an `ArrayHandleGroupVec` with a provided components array.
VTKM_CONT
ArrayHandleGroupVec(const ComponentsArrayHandleType& componentsArray)
: Superclass(componentsArray.GetBuffers())
{
}
/// Retrieve the components array being grouped.
VTKM_CONT ComponentsArrayHandleType GetComponentsArray() const
{
return ComponentsArrayHandleType(this->GetBuffers());
}
};
/// \c make_ArrayHandleGroupVec is convenience function to generate an
/// `make_ArrayHandleGroupVec` is convenience function to generate an
/// ArrayHandleGroupVec. It takes in an ArrayHandle and the number of components
/// (as a specified template parameter), and returns an array handle with
/// consecutive entries grouped in a Vec.

@ -233,13 +233,13 @@ public:
} // namespace internal
/// \brief Fancy array handle that groups values into vectors of different sizes.
/// @brief Fancy array handle that groups values into vectors of different sizes.
///
/// It is sometimes the case that you need to run a worklet with an input or
/// output that has a different number of values per instance. For example, the
/// cells of a CellCetExplicit can have different numbers of points in each
/// cells of a `vtkm::cont::CellCetExplicit` can have different numbers of points in each
/// cell. If inputting or outputting cells of this type, each instance of the
/// worklet might need a \c Vec of a different length. This fance array handle
/// worklet might need a `vtkm::Vec` of a different length. This fancy array handle
/// takes an array of values and an array of offsets and groups the consecutive
/// values in Vec-like objects. The values are treated as tightly packed, so
/// that each Vec contains the values from one offset to the next. The last
@ -247,25 +247,25 @@ public:
///
/// For example, if you have an array handle with the 9 values
/// 0,1,2,3,4,5,6,7,8 an offsets array handle with the 4 values 0,4,6,9 and give
/// them to an \c ArrayHandleGroupVecVariable, you get an array that looks like
/// them to an `ArrayHandleGroupVecVariable`, you get an array that looks like
/// it contains three values of Vec-like objects with the data [0,1,2,3],
/// [4,5], and [6,7,8].
///
/// Note that caution should be used with `ArrayHandleRuntimeVec` because the
/// size of the `Vec` values is not known at compile time. Thus, the value
/// type of this array is forced to a special `VecFromPortal` class that can cause
/// surprises if treated as a `Vec`. In particular, the static `NUM_COMPONENTS`
/// expression does not exist. Furthermore, new variables of type `VecFromPortal`
/// size of the `vtkm::Vec` values is not known at compile time. Thus, the value
/// type of this array is forced to a special `vtkm::VecFromPortal` class that can cause
/// surprises if treated as a `vtkm::Vec`. In particular, the static `NUM_COMPONENTS`
/// expression does not exist. Furthermore, new variables of type `vtkm::VecFromPortal`
/// cannot be created. This means that simple operators like `+` will not work
/// because they require an intermediate object to be created. (Equal operators
/// like `+=` do work because they are given an existing variable to place the
/// output.)
///
/// The offsets array is often derived from a list of sizes for each of the
/// entries. You can use the convenience function \c
/// ConvertNumComponentsToOffsets to take an array of sizes (i.e. the number of
/// components for each entry) and get an array of offsets needed for \c
/// ArrayHandleGroupVecVariable.
/// entries. You can use the convenience function
/// `vtkm::cont::ConvertNumComponentsToOffsets` to take an array of sizes
/// (i.e. the number of components for each entry) and get an array of offsets
/// needed for `ArrayHandleGroupVecVariable`.
///
template <typename ComponentsArrayHandleType, typename OffsetsArrayHandleType>
class ArrayHandleGroupVecVariable
@ -292,6 +292,7 @@ public:
using ComponentType = typename ComponentsArrayHandleType::ValueType;
/// Construct an `ArrayHandleGroupVecVariable`
VTKM_CONT
ArrayHandleGroupVecVariable(const ComponentsArrayHandleType& componentsArray,
const OffsetsArrayHandleType& offsetsArray)
@ -299,18 +300,20 @@ public:
{
}
/// Return the components array providing the data for the grouped vec array.
VTKM_CONT ComponentsArrayHandleType GetComponentsArray() const
{
return StorageType::GetComponentsArray(this->GetBuffers());
}
/// Return the offsets array defining the locations and sizes of each value.
VTKM_CONT OffsetsArrayHandleType GetOffsetsArray() const
{
return StorageType::GetOffsetsArray(this->GetBuffers());
}
};
/// \c make_ArrayHandleGroupVecVariable is convenience function to generate an
/// `make_ArrayHandleGroupVecVariable` is convenience function to generate an
/// ArrayHandleGroupVecVariable. It takes in an ArrayHandle of values and an
/// array handle of offsets and returns an array handle with consecutive
/// entries grouped in a Vec.

@ -58,6 +58,7 @@ public:
VTKM_ARRAY_HANDLE_SUBCLASS_NT(ArrayHandleIndex,
(vtkm::cont::ArrayHandle<vtkm::Id, StorageTagIndex>));
/// Construct an index array containing values from 0 to `length` - 1.
VTKM_CONT
ArrayHandleIndex(vtkm::Id length)
: Superclass(

@ -254,6 +254,7 @@ public:
vtkm::cont::StorageTagPermutation<typename IndexArrayHandleType::StorageTag,
typename ValueArrayHandleType::StorageTag>>));
/// Construct a permuation array with index and value arrays.
VTKM_CONT
ArrayHandlePermutation(const IndexArrayHandleType& indexArray,
const ValueArrayHandleType& valueArray)
@ -261,11 +262,21 @@ public:
{
}
/// @brief Return the array used for indices.
///
/// The index array provides how indices get permuted. When a value is retrieved from an
/// `ArrayHandlePermutation`, an index is retrived from this index array, and this new
/// index is used to retrieve a value from the value array.
VTKM_CONT IndexArrayHandleType GetIndexArray() const
{
return StorageType::GetIndexArray(this->GetBuffers());
}
/// @brief Return the array used for values.
///
/// The index array provides how indices get permuted. When a value is retrieved from an
/// `ArrayHandlePermutation`, an index is retrived from this index array, and this new
/// index is used to retrieve a value from the value array.
VTKM_CONT ValueArrayHandleType GetValueArray() const
{
return StorageType::GetValueArray(this->GetBuffers());
@ -275,13 +286,13 @@ public:
/// make_ArrayHandleTransform is convenience function to generate an
/// ArrayHandleTransform. It takes in an ArrayHandle and a functor
/// to apply to each element of the Handle.
template <typename IndexArrayHandleType, typename ValueArrayHandleType>
VTKM_CONT vtkm::cont::ArrayHandlePermutation<IndexArrayHandleType, ValueArrayHandleType>
make_ArrayHandlePermutation(IndexArrayHandleType indexArray, ValueArrayHandleType valueArray)
{
return ArrayHandlePermutation<IndexArrayHandleType, ValueArrayHandleType>(indexArray, valueArray);
}
}
} // namespace vtkm::cont

@ -37,6 +37,22 @@ struct BoxMuller
};
} //detail
/// @brief An `ArrayHandle` that provides a source of random numbers with a standard normal distribution.
///
/// `ArrayHandleRandomStandardNormal` takes a user supplied seed and hashes it to provide
/// a sequence of numbers drawn from a random standard normal distribution. The probability
/// density function of the numbers is @f$\frac{e^{-x^2/2}}{\sqrt{2\pi}}@f$. The range of possible
/// values is technically infinite, but the probability of large positive or negative numbers
/// becomes vanishingly small.
///
/// This array uses the Box-Muller transform to pick random numbers in the stanard normal
/// distribution.
///
/// Note: In contrast to traditional random number generator,
/// `ArrayHandleRandomStandardNormal` does not have "state", i.e. multiple calls
/// the Get() method with the same index will always return the same hash value.
/// To get a new set of random bits, create a new `ArrayHandleRandomUniformBits`
/// with a different seed.
template <typename Real = vtkm::Float64>
class VTKM_ALWAYS_EXPORT ArrayHandleRandomStandardNormal
: public vtkm::cont::ArrayHandleTransform<
@ -56,6 +72,13 @@ public:
vtkm::cont::ArrayHandleRandomUniformReal<Real>>,
detail::BoxMuller>));
/// Construct an `ArrayHandleRandomStandardNormal`.
///
/// @param length Specifies the length of the generated array.
/// @param seed Provides a seed to use for the pseudorandom numbers. To prevent confusion
/// between the seed and the length, the type of the seed is a `vtkm::Vec` of size 1. To
/// specify the seed, declare it in braces. For example, to construct a random array of
/// size 50 with seed 123, use `ArrayHandleRandomStandardNormal(50, { 123 })`.
explicit ArrayHandleRandomStandardNormal(vtkm::Id length,
SeedType seed = { std::random_device{}() })
: Superclass(vtkm::cont::make_ArrayHandleZip(UniformReal{ length, seed },

@ -51,9 +51,9 @@ private:
}; // class PhiloxFunctor
} // namespace detail
/// \brief An \c ArrayHandle that provides a source of random bits
/// @brief An `ArrayHandle` that provides a source of random bits
///
/// \c ArrayHandleRandomUniformBits is a specialization of ArrayHandleImplicit.
/// `ArrayHandleRandomUniformBits` is a specialization of `ArrayHandleImplicit`.
/// It takes a user supplied seed and hash it with the a given index value. The
/// hashed value is the value of the array at that position.
///
@ -64,9 +64,9 @@ private:
/// is used as the hash function.
///
/// Note: In contrast to traditional random number generator,
/// ArrayHandleRandomUniformBits does not have "state", i.e. multiple calls
/// `ArrayHandleRandomUniformBits` does not have "state", i.e. multiple calls
/// the Get() method with the same index will always return the same hash value.
/// To ge a new set of random bits, create a new ArrayHandleRandomUniformBits
/// To get a new set of random bits, create a new `ArrayHandleRandomUniformBits`
/// with a different seed.
class VTKM_ALWAYS_EXPORT ArrayHandleRandomUniformBits
: public vtkm::cont::ArrayHandleImplicit<detail::PhiloxFunctor>
@ -77,8 +77,13 @@ public:
VTKM_ARRAY_HANDLE_SUBCLASS_NT(ArrayHandleRandomUniformBits,
(vtkm::cont::ArrayHandleImplicit<detail::PhiloxFunctor>));
/// The type of seed is specifically designed to be an vtkm::Vec<> to provide
/// type safety for the parameters so user will not transpose two integer parameters.
/// Construct an `ArrayHandleRandomUniformBits`.
///
/// @param length Specifies the length of the generated array.
/// @param seed Provides a seed to use for the pseudorandom numbers. To prevent confusion
/// between the seed and the length, the type of the seed is a `vtkm::Vec` of size 1. To
/// specify the seed, declare it in braces. For example, to construct a random array of
/// size 50 with seed 123, use `ArrayHandleRandomUniformBits(50, { 123 })`.
explicit ArrayHandleRandomUniformBits(vtkm::Id length, SeedType seed = { std::random_device{}() })
: Superclass(detail::PhiloxFunctor(seed), length)
{

@ -50,6 +50,18 @@ struct CanonicalFunctor<vtkm::Float32>
};
} // detail
/// @brief An `ArrayHandle` that provides a source of random numbers with uniform distribution.
///
/// `ArrayHandleRandomUniformReal` takes a user supplied seed and hashes it to provide
/// a sequence of numbers drawn from a random uniform distribution in the range [0, 1).
/// `ArrayHandleRandomUniformReal` is built on top of `ArrayHandleRandomUniformBits` so
/// shares its behavior with that array.
///
/// Note: In contrast to traditional random number generator,
/// `ArrayHandleRandomUniformReal` does not have "state", i.e. multiple calls
/// the Get() method with the same index will always return the same hash value.
/// To get a new set of random bits, create a new `ArrayHandleRandomUniformBits`
/// with a different seed.
template <typename Real = vtkm::Float64>
class VTKM_ALWAYS_EXPORT ArrayHandleRandomUniformReal
: public vtkm::cont::ArrayHandleTransform<vtkm::cont::ArrayHandleRandomUniformBits,
@ -64,6 +76,13 @@ public:
(vtkm::cont::ArrayHandleTransform<vtkm::cont::ArrayHandleRandomUniformBits,
detail::CanonicalFunctor<Real>>));
/// Construct an `ArrayHandleRandomUniformReal`.
///
/// @param length Specifies the length of the generated array.
/// @param seed Provides a seed to use for the pseudorandom numbers. To prevent confusion
/// between the seed and the length, the type of the seed is a `vtkm::Vec` of size 1. To
/// specify the seed, declare it in braces. For example, to construct a random array of
/// size 50 with seed 123, use `ArrayHandleRandomUniformReal(50, { 123 })`.
explicit ArrayHandleRandomUniformReal(vtkm::Id length, SeedType seed = { std::random_device{}() })
: Superclass(vtkm::cont::ArrayHandleRandomUniformBits{ length, seed },
detail::CanonicalFunctor<Real>{})

@ -204,12 +204,22 @@ public:
using MapType = typename Traits::MapType;
/// Construct an `ArrayHandleSwizzle` with a source array and a swizzle map.
/// The swizzle map is a `vtkm::Vec` containing `vtkm::IdComponent` components
/// and sized to the number of components in the array. Each value in the map
/// specifies from which component of the input the corresponding component of
/// the output should come from.
VTKM_CONT ArrayHandleSwizzle(const ArrayHandleType& array, const MapType& map)
: Superclass(array, Traits::GetFunctor(map), Traits::GetInverseFunctor(map))
{
}
};
/// Construct an `ArrayHandleSwizzle` from a provided array and swizzle map.
/// The swizzle map is a `vtkm::Vec` containing `vtkm::IdComponent` components
/// and sized to the number of components in the array. Each value in the map
/// specifies from which component of the input the corresponding component of
/// the output should come from.
template <typename ArrayHandleType, vtkm::IdComponent OutSize>
VTKM_CONT ArrayHandleSwizzle<ArrayHandleType, OutSize> make_ArrayHandleSwizzle(
const ArrayHandleType& array,
@ -218,11 +228,14 @@ VTKM_CONT ArrayHandleSwizzle<ArrayHandleType, OutSize> make_ArrayHandleSwizzle(
return ArrayHandleSwizzle<ArrayHandleType, OutSize>(array, map);
}
/// Construct an `ArrayHandleSwizzle` from a provided array and swizzle map.
/// The swizzle map is specified as independent function parameters after the array.
/// Each value in the map specifies from which component of the input the corresponding
/// component of the output should come from.
template <typename ArrayHandleType, typename... SwizzleIndexTypes>
VTKM_CONT ArrayHandleSwizzle<ArrayHandleType, vtkm::IdComponent(sizeof...(SwizzleIndexTypes) + 1)>
make_ArrayHandleSwizzle(const ArrayHandleType& array,
vtkm::IdComponent swizzleIndex0,
SwizzleIndexTypes... swizzleIndices)
VTKM_CONT auto make_ArrayHandleSwizzle(const ArrayHandleType& array,
vtkm::IdComponent swizzleIndex0,
SwizzleIndexTypes... swizzleIndices)
{
return make_ArrayHandleSwizzle(array, vtkm::make_Vec(swizzleIndex0, swizzleIndices...));
}

@ -50,20 +50,23 @@ public:
ArrayHandleUniformPointCoordinates,
(vtkm::cont::ArrayHandle<vtkm::Vec3f, vtkm::cont::StorageTagUniformPoints>));
/// Create an `ArrayHandleUniformPointCoordinates` with the given specifications.
VTKM_CONT
ArrayHandleUniformPointCoordinates(vtkm::Id3 dimensions,
ValueType origin = ValueType(0.0f, 0.0f, 0.0f),
ValueType spacing = ValueType(1.0f, 1.0f, 1.0f));
/// Implemented so that it is defined exclusively in the control environment.
/// If there is a separate device for the execution environment (for example,
/// with CUDA), then the automatically generated destructor could be
/// created for all devices, and it would not be valid for all devices.
///
// Implemented so that it is defined exclusively in the control environment.
// If there is a separate device for the execution environment (for example,
// with CUDA), then the automatically generated destructor could be
// created for all devices, and it would not be valid for all devices.
~ArrayHandleUniformPointCoordinates();
/// Get the number of points of the uniform grid in the x, y, and z directions.
VTKM_CONT vtkm::Id3 GetDimensions() const;
/// Get the coordinates of the "lower-left" cornder of the mesh.
VTKM_CONT vtkm::Vec3f GetOrigin() const;
/// Get the spacing between points of the grid in the x, y, and z directions.
VTKM_CONT vtkm::Vec3f GetSpacing() const;
};

@ -189,6 +189,12 @@ public:
} // namespace internal
/// @brief Provided a windowed view into a `vtkm::cont::ArrayHandle`.
///
/// `ArrayHandleView` is a fancy array that wraps around another `ArrayHandle`
/// and reindexes it to provide access to a specified region of values in the
/// array. This view is specified using the offset to the first index and the
/// length of the entries to view.
template <typename ArrayHandleType>
class ArrayHandleView
: public vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
@ -203,23 +209,33 @@ public:
(vtkm::cont::ArrayHandle<typename ArrayHandleType::ValueType,
StorageTagView<typename ArrayHandleType::StorageTag>>));
/// Create an `ArrayHandleView` over a provided source array.
///
/// @param array The source array to create a view from.
/// @param startIndex The offset in `array` to start the view.
/// @param numValues The number of values in the view.
VTKM_CONT
ArrayHandleView(const ArrayHandleType& array, vtkm::Id startIndex, vtkm::Id numValues)
: Superclass(StorageType::CreateBuffers(startIndex, numValues, array))
{
}
/// Retrieve the full array being viewed.
VTKM_CONT ArrayHandleType GetSourceArray() const
{
return this->GetStorage().GetSourceArray(this->GetBuffers());
}
/// Retrieve the start index from the array being viewed.
/// (Note, to get the number of values, simply call the `GetNumberOfValues`
/// method from the superclass.)
VTKM_CONT vtkm::Id GetStartIndex() const
{
return this->GetStorage().GetStartIndex(this->GetBuffers());
}
};
/// @brief Construct a `vtkm::cont::ArrayHandleView` from a source array.
template <typename ArrayHandleType>
ArrayHandleView<ArrayHandleType> make_ArrayHandleView(const ArrayHandleType& array,
vtkm::Id startIndex,

@ -267,13 +267,16 @@ public:
(ArrayHandleZip<FirstHandleType, SecondHandleType>),
(typename internal::ArrayHandleZipTraits<FirstHandleType, SecondHandleType>::Superclass));
/// Create `ArrayHandleZip` with two arrays.
VTKM_CONT
ArrayHandleZip(const FirstHandleType& firstArray, const SecondHandleType& secondArray)
: Superclass(StorageType::CreateBuffers(firstArray, secondArray))
{
}
/// Returns the the array for the first part of the zip pair.
FirstHandleType GetFirstArray() const { return StorageType::GetFirstArray(this->GetBuffers()); }
/// Returns the the array for the second part of the zip pair.
SecondHandleType GetSecondArray() const
{
return StorageType::GetSecondArray(this->GetBuffers());

@ -35,7 +35,7 @@ namespace cont
/// @param[in] componentsArraySize (optional) a reference to a \c vtkm::Id and is filled with the
/// expected size of the component values array.
///
/// \param[in] device (optional) specifies the device on which to run the conversion.
/// @param[in] device (optional) specifies the device on which to run the conversion.
///
/// Note that this function is pre-compiled for some set of `ArrayHandle` types. If you get a
/// warning about an inefficient conversion (or the operation fails outright), you might need to