Merge branch 'master' into tangle_source

This commit is contained in:
Li-Ta Lo 2019-09-11 12:06:58 -06:00
commit 05b6792500
357 changed files with 5060 additions and 4301 deletions

4
.gitattributes vendored

@ -6,8 +6,8 @@
*.hxx our-c-style
*.cu our-c-style
data/* filter=lfs diff=lfs merge=lfs -text
/**/data/* filter=lfs diff=lfs merge=lfs -text
data/** filter=lfs diff=lfs merge=lfs -text
/**/data/** filter=lfs diff=lfs merge=lfs -text
*.cmake whitespace=tab-in-indent
*.md whitespace=tab-in-indent conflict-marker-size=79 -whitespace

@ -87,10 +87,20 @@ endif()
# Load the library exports, but only if not compiling VTK-m itself
set_and_check(VTKm_CONFIG_DIR "@PACKAGE_VTKm_INSTALL_CONFIG_DIR@")
set(VTKM_FROM_INSTALL_DIR FALSE)
if(NOT "${CMAKE_BINARY_DIR}" STREQUAL "@VTKm_BINARY_DIR@")
set(VTKM_FROM_INSTALL_DIR TRUE)
include(${VTKm_CONFIG_DIR}/VTKmTargets.cmake)
endif()
# Once we can require CMake 3.15 for all cuda builds we can
# replace this with setting `cuda_architecture_flags` as part of the
# EXPORT_PROPERTIES of the vtkm_cuda target
if(VTKm_ENABLE_CUDA AND VTKM_FROM_INSTALL_DIR)
set_target_properties(vtkm::cuda PROPERTIES cuda_architecture_flags "@VTKm_CUDA_Architecture_Flags@")
set_target_properties(vtkm::cuda PROPERTIES requires_static_builds TRUE)
endif()
# VTKm requires some CMake Find modules not included with CMake, so
# include the CMake modules distributed with VTKm.
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${VTKm_CMAKE_MODULE_PATH})

@ -121,14 +121,18 @@ if(VTKm_ENABLE_CUDA)
set_target_properties(vtkm_cuda PROPERTIES EXPORT_NAME vtkm::cuda)
install(TARGETS vtkm_cuda EXPORT ${VTKm_EXPORT_NAME})
# Reserve `INTERFACE_REQUIRES_STATIC_BUILDS` to potential work around issues
# Reserve `requires_static_builds` to potential work around issues
# where VTK-m doesn't work when building shared as virtual functions fail
# inside device code. We don't want to force BUILD_SHARED_LIBS to a specific
# value as that could impact other projects that embed VTK-m. Instead what
# we do is make sure that libraries built by vtkm_library() are static
# if they use CUDA
#
# This needs to be lower-case for the property to be properly exported
# CMake 3.15 we can add `requires_static_builds` to the EXPORT_PROPERTIES
# target property to have this automatically exported for us
set_target_properties(vtkm_cuda PROPERTIES
INTERFACE_REQUIRES_STATIC_BUILDS TRUE
requires_static_builds TRUE
)
@ -247,7 +251,11 @@ if(VTKm_ENABLE_CUDA)
string(REPLACE ";" " " arch_flags "${arch_flags}")
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${arch_flags}")
set_target_properties(vtkm_cuda PROPERTIES INTERFACE_CUDA_Architecture_Flags "${arch_flags}")
# This needs to be lower-case for the property to be properly exported
# CMake 3.15 we can add `cuda_architecture_flags` to the EXPORT_PROPERTIES
# target property to have this automatically exported for us
set_target_properties(vtkm_cuda PROPERTIES cuda_architecture_flags "${arch_flags}")
set(VTKm_CUDA_Architecture_Flags "${arch_flags}")
endif()
endif()

@ -130,7 +130,7 @@ function(vtkm_get_cuda_flags settings_var)
if(TARGET vtkm::cuda)
get_property(arch_flags
TARGET vtkm::cuda
PROPERTY INTERFACE_CUDA_Architecture_Flags)
PROPERTY cuda_architecture_flags)
set(${settings_var} "${${settings_var}} ${arch_flags}" PARENT_SCOPE)
endif()
endfunction()
@ -166,7 +166,8 @@ endfunction()
# need to be marked as going to a special compiler for certain device adapters
# such as CUDA.
#
# EXTENDS_VTKM: Some programming models have restrictions on how types can be extended.
# EXTENDS_VTKM: Some programming models have restrictions on how types can be used,
# passed across library boundaries, and derived from.
# For example CUDA doesn't allow device side calls across dynamic library boundaries,
# and requires all polymorphic classes to be reachable at dynamic library/executable
# link time.
@ -177,10 +178,13 @@ endfunction()
# Executable: do nothing, zero restrictions
# Static library: do nothing, zero restrictions
# Dynamic library:
# -> Wanting to extend VTK-m and provide these types to consumers. This
# is supported when CUDA isn't enabled. Otherwise we need to ERROR!
# -> Wanting to use VTK-m as implementation detail, doesn't expose VTK-m
# types to consumers. This is supported no matter if CUDA is enabled.
# -> Wanting to extend VTK-m and provide these types to consumers.
# This is only supported when CUDA isn't enabled. Otherwise we need to ERROR!
# -> Wanting to pass known VTK-m types across library boundaries for others
# to use in filters/worklets.
# This is only supported when CUDA isn't enabled. Otherwise we need to ERROR!
#
# For most consumers they can ignore the `EXTENDS_VTKM` property as the default
# will be correct.
@ -203,9 +207,9 @@ function(vtkm_add_target_information uses_vtkm_target)
# dynamic library boundaries.
if(TARGET vtkm::cuda)
get_target_property(lib_type ${uses_vtkm_target} TYPE)
get_target_property(requires_static vtkm::cuda INTERFACE_REQUIRES_STATIC_BUILDS)
get_target_property(requires_static vtkm::cuda requires_static_builds)
if(requires_static AND ${lib_type} STREQUAL "SHARED_LIBRARY")
if(requires_static AND ${lib_type} STREQUAL "SHARED_LIBRARY" AND VTKm_TI_EXTENDS_VTKM)
#We provide different error messages based on if we are building VTK-m
#or being called by a consumer of VTK-m. We use PROJECT_NAME so that we
#produce the correct error message when VTK-m is a subdirectory include
@ -277,6 +281,7 @@ function(vtkm_library)
${VTKm_LIB_DEVICE_SOURCES}
)
vtkm_add_target_information(${lib_name}
EXTENDS_VTKM
DEVICE_SOURCES ${VTKm_LIB_DEVICE_SOURCES}
)
if(NOT VTKm_USE_DEFAULT_SYMBOL_VISIBILITY)

@ -56,7 +56,7 @@ function(vtkm_unit_tests)
set(test_prog)
set(per_device_command_line_arguments "")
set(per_device_command_line_arguments "NONE")
set(per_device_suffix "")
set(per_device_timeout 180)
set(per_device_serial FALSE)
@ -65,7 +65,6 @@ function(vtkm_unit_tests)
if(enable_all_backends)
set(per_device_command_line_arguments --device=serial)
set(per_device_suffix "SERIAL")
if (VTKm_ENABLE_CUDA)
list(APPEND per_device_command_line_arguments --device=cuda)
list(APPEND per_device_suffix "CUDA")
@ -131,8 +130,14 @@ function(vtkm_unit_tests)
target_link_libraries(${test_prog} PRIVATE vtkm_cont ${VTKm_UT_LIBRARIES})
foreach(index RANGE per_device_command_line_arguments)
if(per_device_command_line_arguments STREQUAL "")
list(LENGTH per_device_command_line_arguments number_of_devices)
foreach(index RANGE ${number_of_devices})
if(index EQUAL number_of_devices)
#RANGE is inclusive on both sides, and we want it to be
#exclusive on the end ( e.g. for(i=0; i < n; ++i))
break()
endif()
if(per_device_command_line_arguments STREQUAL "NONE")
set(device_command_line_argument ${per_device_command_line_arguments})
set(upper_backend ${per_device_suffix})
set(timeout ${per_device_timeout})

@ -317,7 +317,7 @@ public:
vtkm::Id idx = i % this->ArraySize;
ValueType val = static_cast<ValueType>(i);
// Get the old val with a no-op
ValueType oldVal = this->Portal.Add(idx, static_cast<ValueType>(0));
ValueType oldVal = this->Portal.Get(idx);
ValueType assumed = static_cast<ValueType>(0);
do
{
@ -445,7 +445,7 @@ public:
vtkm::Id idx = (i / this->Stride + this->Stride * (i % this->Stride)) % this->ArraySize;
ValueType val = static_cast<ValueType>(i);
// Get the old val with a no-op
ValueType oldVal = this->Portal.Add(idx, static_cast<ValueType>(0));
ValueType oldVal = this->Portal.Get(idx);
ValueType assumed = static_cast<ValueType>(0);
do
{

3
data/magField.vtk Normal file

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b947d66dbae99a1ebb392b200a9ea0d380cfccb7fcb3a3739615d0dde558d2f1
size 238166

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6969444d4082055c2334a834f025cf8490bd6d43bb2965b3e0859740e0b73767
size 7670

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b7a6f69e78910d828523fa3c05b787f1d6d89ec6049d2279758b3b032177fda5
size 7703

@ -0,0 +1,47 @@
# Add ability to get an array from a Field for a particular type
Previously, whenever you got an array from a `Field` object from a call to
an `ApplyPolicy`, you would get back a `VariantArrayHandle` that allows you
to cast to multiple types. To use that, you then have to cast it to
multiple different types and multiple different storage.
Often, this is what you want. If you are operating on a field, then you
want to cast to the native type. But there are also cases where you know a
specific type you want. For example, if you are operating on two fields, it
makes sense to find the exact type for the first field and then cast the
second field to that type if necessary rather than pointlessly unroll
templates for the cross of every possible combination. Also, we are not
unrolling for different storage types or attempting to create a virtual
array. Instead, we are using an `ArrayHandleMultiplexer` so that you only
have to compile for this array once.
This is done through a new version of `ApplyPolicy`. This version takes a
type of the array as its first template argument, which must be specified.
This requires having a list of potential storage to try. It will use that
to construct an `ArrayHandleMultiplexer` containing all potential types.
This list of storages comes from the policy. A `StorageList` item was added
to the policy. It is also sometimes necessary for a filter to provide its
own special storage types. Thus, an `AdditionalFieldStorage` type was added
to `Filter` which is set to a `ListTag` of storage types that should be
added to those specified by the policy.
Types are automatically converted. So if you ask for a `vtkm::Float64` and
field contains a `vtkm::Float32`, it will the array wrapped in an
`ArrayHandleCast` to give the expected type.
Here is an example where you are doing an operation on a field and
coordinate system. The superclass finds the correct type of the field. Your
result is just going to follow the type of the field.
``` cpp
template <typename T, typename StorageType, typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::DataSet MyFilter::DoExecute(
const vtkm::cont::DataSet& inDataSet,
const vtkm::cont::ArrayHandle<T, StorageType>& field,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<DerivedPolicy> policy)
{
vtkm::cont::CoordinateSystem coords = inDataSet.GetCoordianteSystem();
auto coordsArray = vtkm::filter::ApplyPolicy<T>(coords, policy, *this);
```

@ -0,0 +1,8 @@
# CellSets now don't have a name
The requirement that `vtkm::cont::CellSets` have a name was so
cell based `vtkm::cont::Field`'s could be associated with the
correct CellSet in a `vtkm::cont::DataSet`.
Now that `DataSet`'s don't support multiple CellSets, we can remove
the `CellSet` name member variable.

@ -1,6 +1,6 @@
# DataSet queries for CellSet and Coordinate System Indices don't throw
# DataSet queries for CoordinateSystem Indices don't throw
Asking for the index of a `vtkm::cont::CellSet` or `vtkm::cont::CoordinateSystem` by
Asking for the index of a `vtkm::cont::CoordinateSystem` by
name now returns a `-1` when no matching item has been found instead of throwing
an exception.

@ -0,0 +1,29 @@
# DataSet only has a single vtkm::cont::CellSet
Multiple `vtkm::cont::CellSets` on a datasets increased the
complexity of using VTK-m correctly without any significant
benefits.
It had the effect that `vtkm::cont::Fields` that representing
cell fields needed to be associated with a given cellset. This
has to be a loose coupling to allow for filters to generate
new output cellsets. At the same time it introduced errors when
that output had a different name.
It raised questions about how should filters propagate cell fields.
Should a filter drop all cell fields not associated with the active
CellSet, or is that too aggressive given the fact that maybe the
algorithm just mistakenly named the field, or the IO routine added
a field with the wrong cellset name.
It increased the complexity of filters, as the developer needed to
determine if the algorithm should support execution on a single `CellSet` or
execution over all `CellSets`.
Given these issues it was deemed that removing multiple `CellSets` was
the correct way forward. People using multiple `CellSets` will need to
move over to `vtkm::cont::MultiBlock` which supports shared points and
fields between multiple blocks.

@ -0,0 +1,5 @@
# Fields now don't require the associated CellSet name
Now that `vtkm::cont::DataSet` can only have a single `vtkm::cont::CellSet`
the requirement that cell based `vtkm::cont::Field`s need a CellSet name
has been lifted.

@ -1,6 +0,0 @@
# FilterField now tries to be smart when selecting active cellset
Now when a calls a `vtkm::filter::FilterField` algorithm without an explicit
active CellSet, if the field is cell based we set the active `vtkm::cont::CellSet`
to be the one associated with that field. If that `vtkm::cont::CellSet` doesn't
exist we default back to using the first CellSet in the input `vtkm::cont::DataSet`.

@ -0,0 +1,4 @@
# vtkm::cont::Filter now don't have an active cell set
`vtkm::filter::FilterField` has removed the concept of `ActiveCellSetIndex`. This
has been done as `vtkm::cont::DataSet` now only contains a single `vtkm::cont::CellSet`.

@ -0,0 +1,19 @@
# Fix cell derivatives for polygon cell shape
For polygon cell shapes (that are not triangles or quadrilaterals),
interpolations are done by finding the center point and creating a triangle
fan around that point. Previously, the gradient was computed in the same
way as interpolation: identifying the correct triangle and computing the
gradient for that triangle.
The problem with that approach is that makes the gradient discontinuous at
the boundaries of this implicit triangle fan. To make things worse, this
discontinuity happens right at each vertex where gradient calculations
happen frequently. This means that when you ask for the gradient at the
vertex, you might get wildly different answers based on floating point
imprecision.
Get around this problem by creating a small triangle around the point in
question, interpolating values to that triangle, and use that for the
gradient. This makes for a smoother gradient transition around these
internal boundaries.

@ -0,0 +1,16 @@
# `MultiBlock` renamed to `PartitionedDataSet`
The `MultiBlock` class has been renamed to `PartitionedDataSet`, and its API
has been refactored to refer to "partitions", rather than "blocks".
Additionally, the `AddBlocks` method has been changed to `AppendPartitions` to
more accurately reflect the operation performed. The associated
`AssignerMultiBlock` class has also been renamed to
`AssignerPartitionedDataSet`.
This change is motivated towards unifying VTK-m's data model with VTK. VTK has
started to move away from `vtkMultiBlockDataSet`, which is a hierarchical tree
of nested datasets, to `vtkPartitionedDataSet`, which is always a flat vector
of datasets used to assist geometry distribution in multi-process environments.
This simplifies traversal during processing and clarifies the intent of the
container: The component datasets are partitions for distribution, not
organizational groupings (e.g. materials).

@ -0,0 +1,10 @@
# Remove ArrayPortalShrink, behavior subsumed by ArrayHandleView
ArrayPortalShrink originaly allowed a user to pass in a delegate array portal
and then shrink the reported array size without actually modifying the
underlying allocation. An iterator was also provided that would
correctly iterate over the shrunken size of the stored array.
Instead of directly shrinking the original array, it is prefered
to create an ArrayHandleView from an ArrayHandle and then specify the
number of values to use in the ArrayHandleView constructor.

@ -0,0 +1,29 @@
# A `ScanExtended` device algorithm has been added.
This new scan algorithm produces an array that contains both an inclusive scan
and an exclusive scan in the same array:
```
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayGetValue.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/ArrayHandleView.h>
vtkm::cont::ArrayHandle<T> inputData = ...;
const vtkm::Id size = inputData.GetNumberOfValues();
vtkm::cont::ArrayHandle<T> extendedScan;
vtkm::cont::Algorithm::ScanExtended(inputData, extendedScan);
// The exclusive scan is the first `inputSize` values starting at index 0:
auto exclusiveScan = vtkm::cont::make_ArrayHandleView(extendedScan, 0, size);
// The inclusive scan is the first `inputSize` values starting at index 1:
auto inclusiveScan = vtkm::cont::make_ArrayHandleView(extendedScan, 1, size);
// The total sum of the input data is the last value in the extended scan.
const T totalSum = vtkm::cont::ArrayGetValue(size, extendedScan);
```
This can also be thought of as an exclusive scan that appends the total sum,
rather than returning it.

@ -0,0 +1,39 @@
# Recursive base component queries to VecTraits
This change adds a recursive `BaseComponentType` to `VecTraits` that
recursively finds the base (non-`Vec`) type of a `Vec`. This is useful when
dealing with potentially nested `Vec`s (e.g. `Vec<Vec<T, M>, N>`) and you
want to know the precision of the math being defined.
``` cpp
using NestedVec = vtkm::Vec<vtkm::Vec<vtkm::Float32, 3>, 8>;
// ComponentType becomes vtkm::Vec<vtkm::Float32, 3>
using ComponentType = typename vtkm::VecTraits<NestedVec>::ComponentType;
// BaseComponentType becomes vtkm::Float32
using BaseComponentType = typename vtkm::VecTraits<NestedVec>::BaseComponentType;
```
Also added the ability to `VecTraits` to change the component type of a
vector. The template `RepalceComponentType` resolves to a `Vec` of the same
type with the component replaced with a new type. The template
`ReplaceBaseComponentType` traverses down a nested type and replaces the
base type.
``` cpp
using NestedVec = vtkm::Vec<vtkm::Vec<vtkm::Float32, 3>, 8>;
// NewVec1 becomes vtkm::Vec<vtkm::Float64, 8>
using NewVec1 =
typename vtkm::VecTraits<NestedVec>::template ReplaceComponentType<vtkm::Float64>;
// NewVec2 becomes vtkm::Vec<vtkm::Vec<vtkm::Float64, 3>, 8>
using NewVec1 =
typename vtkm::VecTraits<NestedVec>::template ReplaceBaseComponentType<vtkm::Float64>;
```
This functionality replaces the functionality in `vtkm::BaseComponent`. Unfortunately,
`vtkm::BaseComponent` did not have the ability to replace the base component and
there was no straightforward way to implement that outside of `VecTraits`.

@ -40,10 +40,11 @@ void TestCosmoHaloFinder(const char* fileName)
// Read in number of particles and locations
int nParticles;
inFile >> nParticles;
std::size_t size = static_cast<std::size_t>(nParticles);
float* xLocation = new float[nParticles];
float* yLocation = new float[nParticles];
float* zLocation = new float[nParticles];
float* xLocation = new float[size];
float* yLocation = new float[size];
float* zLocation = new float[size];
std::cout << "Running Halo Finder on " << nParticles << std::endl;
for (vtkm::Id p = 0; p < nParticles; p++)

@ -115,26 +115,21 @@ public:
vtkm::cont::ArrayHandle<vtkm::Vec4ui_8> colors;
//get the coordinate system we are using for the 2D area
const vtkm::cont::DynamicCellSet& cells = input.GetCellSet(this->GetActiveCellSetIndex());
const vtkm::cont::DynamicCellSet& cells = input.GetCellSet();
//get the previous state of the game
input.GetField("state", vtkm::cont::Field::Association::POINTS).GetData().CopyTo(prevstate);
//Update the game state
this->Invoke(
UpdateLifeState{}, vtkm::filter::ApplyPolicy(cells, policy), prevstate, state, colors);
UpdateLifeState{}, vtkm::filter::ApplyPolicyCellSet(cells, policy), prevstate, state, colors);
//save the results
vtkm::cont::DataSet output;
output.AddCellSet(input.GetCellSet(this->GetActiveCellSetIndex()));
output.AddCoordinateSystem(input.GetCoordinateSystem(this->GetActiveCoordinateSystemIndex()));
vtkm::cont::Field colorField("colors", vtkm::cont::Field::Association::POINTS, colors);
output.AddField(colorField);
vtkm::cont::Field stateField("state", vtkm::cont::Field::Association::POINTS, state);
output.AddField(stateField);
output.CopyStructure(input);
output.AddField(vtkm::cont::make_FieldPoint("colors", colors));
output.AddField(vtkm::cont::make_FieldPoint("state", state));
return output;
}
@ -206,7 +201,7 @@ struct RenderGameOfLife
void render(vtkm::cont::DataSet& data)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
vtkm::Int32 arraySize = (vtkm::Int32)data.GetCoordinateSystem().GetNumberOfPoints();
vtkm::Int32 arraySize = (vtkm::Int32)data.GetNumberOfPoints();
UploadData task(&this->ColorState,
data.GetField("colors", vtkm::cont::Field::Association::POINTS));

@ -80,18 +80,18 @@ int main(int argc, char* argv[])
const vtkm::Id num_bins = static_cast<vtkm::Id>(std::atoi(argv[1]));
const vtkm::Id numVals = 1024;
vtkm::cont::MultiBlock mb;
vtkm::cont::PartitionedDataSet pds;
vtkm::cont::DataSet ds;
vtkm::cont::DataSetFieldAdd::AddPointField(ds, "pointvar", CreateArray(-1024, 1024, numVals));
mb.AddBlock(ds);
pds.AppendPartition(ds);
example::HistogramMPI histogram;
histogram.SetActiveField("pointvar");
histogram.SetNumberOfBins(std::max<vtkm::Id>(1, num_bins));
vtkm::cont::MultiBlock result = histogram.Execute(mb);
vtkm::cont::PartitionedDataSet result = histogram.Execute(pds);
vtkm::cont::ArrayHandle<vtkm::Id> bins;
result.GetBlock(0).GetField("histogram").GetData().CopyTo(bins);
result.GetPartition(0).GetField("histogram").GetData().CopyTo(bins);
auto binPortal = bins.GetPortalConstControl();
if (rank == 0)
{

@ -65,16 +65,16 @@ public:
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
//@{
/// when operating on vtkm::cont::MultiBlock, we
/// when operating on vtkm::cont::PartitionedDataSet, we
/// want to do processing across ranks as well. Just adding pre/post handles
/// for the same does the trick.
template <typename DerivedPolicy>
VTKM_CONT void PreExecute(const vtkm::cont::MultiBlock& input,
VTKM_CONT void PreExecute(const vtkm::cont::PartitionedDataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
template <typename DerivedPolicy>
VTKM_CONT void PostExecute(const vtkm::cont::MultiBlock& input,
vtkm::cont::MultiBlock& output,
VTKM_CONT void PostExecute(const vtkm::cont::PartitionedDataSet& input,
vtkm::cont::PartitionedDataSet& output,
const vtkm::filter::PolicyBase<DerivedPolicy>&);
//@}

@ -12,7 +12,7 @@
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/ArrayPortalToIterators.h>
#include <vtkm/cont/AssignerMultiBlock.h>
#include <vtkm/cont/AssignerPartitionedDataSet.h>
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/ErrorFilterExecution.h>
#include <vtkm/cont/FieldRangeGlobalCompute.h>
@ -143,7 +143,7 @@ inline VTKM_CONT vtkm::cont::DataSet HistogramMPI::DoExecute(
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT void HistogramMPI::PreExecute(const vtkm::cont::MultiBlock& input,
inline VTKM_CONT void HistogramMPI::PreExecute(const vtkm::cont::PartitionedDataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
if (this->Range.IsNonEmpty())
@ -164,15 +164,15 @@ inline VTKM_CONT void HistogramMPI::PreExecute(const vtkm::cont::MultiBlock& inp
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT void HistogramMPI::PostExecute(const vtkm::cont::MultiBlock&,
vtkm::cont::MultiBlock& result,
inline VTKM_CONT void HistogramMPI::PostExecute(const vtkm::cont::PartitionedDataSet&,
vtkm::cont::PartitionedDataSet& result,
const vtkm::filter::PolicyBase<DerivedPolicy>&)
{
// iterate and compute HistogramMPI for each local block.
detail::DistributedHistogram helper(result.GetNumberOfBlocks());
for (vtkm::Id cc = 0; cc < result.GetNumberOfBlocks(); ++cc)
detail::DistributedHistogram helper(result.GetNumberOfPartitions());
for (vtkm::Id cc = 0; cc < result.GetNumberOfPartitions(); ++cc)
{
auto& ablock = result.GetBlock(cc);
auto& ablock = result.GetPartition(cc);
helper.SetLocalHistogram(cc, ablock.GetField(this->GetOutputFieldName()));
}
@ -182,6 +182,6 @@ inline VTKM_CONT void HistogramMPI::PostExecute(const vtkm::cont::MultiBlock&,
helper.ReduceAll(this->NumberOfBins));
output.AddField(rfield);
result = vtkm::cont::MultiBlock(output);
result = vtkm::cont::PartitionedDataSet(output);
}
} // namespace example

@ -16,4 +16,4 @@ add_executable(Lagrangian lagrangian.cxx ABCfield.h)
target_link_libraries(Lagrangian PRIVATE vtkm_filter)
vtkm_add_target_information(Lagrangian
MODIFY_CUDA_FLAGS
DEVICE_SOURCES Lagrangian.cxx)
DEVICE_SOURCES lagrangian.cxx)

@ -32,6 +32,6 @@ if(TARGET vtkm::tbb)
target_compile_definitions(MeshQuality PRIVATE BUILDING_TBB_VERSION)
endif()
if(TARGET vtkm::cuda)
set_source_files_properties(MeshQuality.cxx PROPERTIES LANGUAGE "CUDA")
endif()
vtkm_add_target_information(MeshQuality
MODIFY_CUDA_FLAGS
DEVICE_SOURCES MeshQuality.cxx)

@ -194,7 +194,7 @@ inline vtkm::cont::DataSet Make3DExplicitDataSet()
conn.push_back(7);
conn.push_back(2);
dataSet = dsb.Create(coords, shapes, numindices, conn, "coordinates", "cells");
dataSet = dsb.Create(coords, shapes, numindices, conn, "coordinates");
return dataSet;
}

@ -20,17 +20,14 @@ set(headers
TaskQueue.h
)
set(device_srcs
MultiDeviceGradient.cxx
)
set(srcs
IOGenerator.cxx
MultiBackend.cxx
MultiDeviceGradient.cxx
IOGenerator.cxx
)
add_executable(MultiBackend ${device_srcs} ${srcs} ${headers})
add_executable(MultiBackend ${srcs} ${headers})
target_link_libraries(MultiBackend PRIVATE vtkm_filter Threads::Threads)
vtkm_add_target_information(MultiBackend
MODIFY_CUDA_FLAGS
DEVICE_SOURCES ${device_srcs})
DEVICE_SOURCES ${srcs})

@ -51,46 +51,47 @@ vtkm::cont::DataSet make_test3DImageData(vtkm::Id3 dims)
}
//=================================================================
void io_generator(TaskQueue<vtkm::cont::MultiBlock>& queue, std::size_t numberOfTasks)
void io_generator(TaskQueue<vtkm::cont::PartitionedDataSet>& queue, std::size_t numberOfTasks)
{
//Step 1. We want to build an initial set of blocks
//Step 1. We want to build an initial set of partitions
//that vary in size. This way we can generate uneven
//work to show off the vtk-m filter work distribution
vtkm::Id3 small(128, 128, 128);
vtkm::Id3 medium(256, 256, 128);
vtkm::Id3 large(512, 256, 128);
std::vector<vtkm::Id3> block_sizes;
block_sizes.push_back(small);
block_sizes.push_back(medium);
block_sizes.push_back(large);
std::vector<vtkm::Id3> partition_sizes;
partition_sizes.push_back(small);
partition_sizes.push_back(medium);
partition_sizes.push_back(large);
std::mt19937 rng;
//uniform_int_distribution is a closed interval [] so both the min and max
//can be chosen values
std::uniform_int_distribution<vtkm::Id> blockNumGen(6, 32);
std::uniform_int_distribution<std::size_t> blockPicker(0, block_sizes.size() - 1);
std::uniform_int_distribution<vtkm::Id> partitionNumGen(6, 32);
std::uniform_int_distribution<std::size_t> partitionPicker(0, partition_sizes.size() - 1);
for (std::size_t i = 0; i < numberOfTasks; ++i)
{
//Step 2. Construct a random number of blocks
const vtkm::Id numberOfBlocks = blockNumGen(rng);
//Step 2. Construct a random number of partitions
const vtkm::Id numberOfPartitions = partitionNumGen(rng);
//Step 3. Randomly pick the blocks in the dataset
vtkm::cont::MultiBlock mb(numberOfBlocks);
for (vtkm::Id b = 0; b < numberOfBlocks; ++b)
//Step 3. Randomly pick the partitions in the dataset
vtkm::cont::PartitionedDataSet pds(numberOfPartitions);
for (vtkm::Id p = 0; p < numberOfPartitions; ++p)
{
const auto& dims = block_sizes[blockPicker(rng)];
auto block = make_test3DImageData(dims);
mb.AddBlock(block);
const auto& dims = partition_sizes[partitionPicker(rng)];
auto partition = make_test3DImageData(dims);
pds.AppendPartition(partition);
}
std::cout << "adding multi-block with " << mb.GetNumberOfBlocks() << " blocks" << std::endl;
std::cout << "adding partitioned dataset with " << pds.GetNumberOfPartitions() << " partitions"
<< std::endl;
//Step 4. Add the multi-block to the queue. We explicitly
//Step 4. Add the partitioned dataset to the queue. We explicitly
//use std::move to signal that this thread can't use the
//mb object after this call
queue.push(std::move(mb));
//pds object after this call
queue.push(std::move(pds));
//Step 5. Go to sleep for a period of time to replicate
//data stream in

@ -12,9 +12,9 @@
#include "TaskQueue.h"
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/PartitionedDataSet.h>
vtkm::cont::DataSet make_test3DImageData(int xdim, int ydim, int zdim);
void io_generator(TaskQueue<vtkm::cont::MultiBlock>& queue, std::size_t numberOfTasks);
void io_generator(TaskQueue<vtkm::cont::PartitionedDataSet>& queue, std::size_t numberOfTasks);
#endif

@ -12,7 +12,7 @@
#include <thread>
#include <vtkm/cont/Initialize.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include "IOGenerator.h"
#include "MultiDeviceGradient.h"
@ -22,9 +22,9 @@
//
//At a high level we have 2 primary threads, an IO thread and a Worker thread
//The IO thread will generate all data using the vtk-m serial device, and
//will post this data to a worker queue as a vtk-m multiblock.
//The Worker thread will pull down these vtk-m multiblock data and run a
//vtk-m filter on the multiblock.
//will post this data to a worker queue as a vtk-m partitioned dataset.
//The Worker thread will pull down these vtk-m data and run a
//vtk-m filter on the partitions.
//The vtk-m filter it runs will itself have a worker pool which it will
//distribute work too. The number of workers is based on what device adapters
//are enabled but uses the following logic:
@ -38,7 +38,7 @@
//and single GPU we should expect that we will have 2 primary 'main loop'
//threads, and 5 threads for heavy 'task' work.
void multiblock_processing(TaskQueue<vtkm::cont::MultiBlock>& queue);
void partition_processing(TaskQueue<vtkm::cont::PartitionedDataSet>& queue);
int main(int argc, char** argv)
{
auto opts =
@ -48,9 +48,9 @@ int main(int argc, char** argv)
//Step 1. Construct the two primary 'main loops'. The threads
//share a queue object so we need to explicitly pass it
//by reference (the std::ref call)
TaskQueue<vtkm::cont::MultiBlock> queue;
TaskQueue<vtkm::cont::PartitionedDataSet> queue;
std::thread io(io_generator, std::ref(queue), 6);
std::thread worker(multiblock_processing, std::ref(queue));
std::thread worker(partition_processing, std::ref(queue));
//Step N. Wait for the work to finish
io.join();
@ -59,7 +59,7 @@ int main(int argc, char** argv)
}
//=================================================================
void multiblock_processing(TaskQueue<vtkm::cont::MultiBlock>& queue)
void partition_processing(TaskQueue<vtkm::cont::PartitionedDataSet>& queue)
{
//Step 1. Construct the gradient filter outside the work loop
//so that we can reuse the thread pool it constructs
@ -67,42 +67,37 @@ void multiblock_processing(TaskQueue<vtkm::cont::MultiBlock>& queue)
gradient.SetComputePointGradient(true);
while (queue.hasTasks())
{
//Step 2. grab the next multi-block skipping any that are empty
//Step 2. grab the next partition skipping any that are empty
//as empty ones can be returned when the queue is about
//to say it has no work
vtkm::cont::MultiBlock mb = queue.pop();
if (mb.GetNumberOfBlocks() == 0)
vtkm::cont::PartitionedDataSet pds = queue.pop();
if (pds.GetNumberOfPartitions() == 0)
{
continue;
}
//Step 3. Get the first field name from the multi-block
std::string fieldName = mb.GetBlock(0).GetField(0).GetName();
//Step 3. Get the first field name from the partition
std::string fieldName = pds.GetPartition(0).GetField(0).GetName();
//Step 4. Run a multi device gradient
gradient.SetActiveField(fieldName);
vtkm::cont::MultiBlock result = gradient.Execute(mb);
std::cout << "finished processing a multi-block" << std::endl;
vtkm::cont::PartitionedDataSet result = gradient.Execute(pds);
std::cout << "finished processing a partitioned dataset" << std::endl;
//Step 5. Verify each block has a "Gradients" field
for (auto&& block : result)
//Step 5. Verify each partition has a "Gradients" field
for (auto&& partition : result)
{
// std::cout << std::endl << std::endl << std::endl;
// std::cout << "block: " << std::endl;
// block.PrintSummary(std::cout);
try
{
const auto& field = block.GetField("Gradients", vtkm::cont::Field::Association::POINTS);
(void)field;
}
catch (const vtkm::cont::ErrorBadValue& error)
// std::cout << "partition: " << std::endl;
// partition.PrintSummary(std::cout);
if (!partition.HasField("Gradients", vtkm::cont::Field::Association::POINTS))
{
std::cerr << "Gradient filter failed!" << std::endl;
std::cerr << error.GetMessage() << std::endl;
std::cerr << "Missing Gradient field on output partition." << std::endl;
break;
}
}
}
std::cout << "multiblock_processing finished" << std::endl;
std::cout << "partition_processing finished" << std::endl;
}

@ -13,6 +13,6 @@
#include "MultiDeviceGradient.h"
#include "MultiDeviceGradient.hxx"
template vtkm::cont::MultiBlock MultiDeviceGradient::PrepareForExecution<
vtkm::filter::PolicyDefault>(const vtkm::cont::MultiBlock&,
template vtkm::cont::PartitionedDataSet MultiDeviceGradient::PrepareForExecution<
vtkm::filter::PolicyDefault>(const vtkm::cont::PartitionedDataSet&,
const vtkm::filter::PolicyBase<vtkm::filter::PolicyDefault>&);

@ -18,7 +18,7 @@
using RuntimeTaskQueue = TaskQueue<std::function<void()>>;
/// \brief Construct a MultiDeviceGradient for a given multiblock dataset
/// \brief Construct a MultiDeviceGradient for a given partitioned dataset
///
/// The Policy used with MultiDeviceGradient must include the TBB and CUDA
/// backends.
@ -45,8 +45,8 @@ public:
/// Will submit each block to a work queue that the threads will
/// pull work from
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::MultiBlock PrepareForExecution(
const vtkm::cont::MultiBlock&,
VTKM_CONT vtkm::cont::PartitionedDataSet PrepareForExecution(
const vtkm::cont::PartitionedDataSet&,
const vtkm::filter::PolicyBase<DerivedPolicy>&);
private:
@ -56,8 +56,8 @@ private:
};
#ifndef vtk_m_examples_multibackend_MultiDeviceGradient_cxx
extern template vtkm::cont::MultiBlock MultiDeviceGradient::PrepareForExecution<
vtkm::filter::PolicyDefault>(const vtkm::cont::MultiBlock&,
extern template vtkm::cont::PartitionedDataSet MultiDeviceGradient::PrepareForExecution<
vtkm::filter::PolicyDefault>(const vtkm::cont::PartitionedDataSet&,
const vtkm::filter::PolicyBase<vtkm::filter::PolicyDefault>&);
#endif

@ -32,7 +32,7 @@ int determine_cuda_gpu_count()
return count;
}
void process_block_tbb(RuntimeTaskQueue& queue)
void process_partition_tbb(RuntimeTaskQueue& queue)
{
//Step 1. Set the device adapter to this thread to TBB.
//This makes sure that any vtkm::filters used by our
@ -56,11 +56,11 @@ void process_block_tbb(RuntimeTaskQueue& queue)
//Step 4. Notify the queue that we finished processing this task
queue.completedTask();
std::cout << "finished a block on tbb (" << std::this_thread::get_id() << ")" << std::endl;
std::cout << "finished a partition on tbb (" << std::this_thread::get_id() << ")" << std::endl;
}
}
void process_block_openMP(RuntimeTaskQueue& queue)
void process_partition_openMP(RuntimeTaskQueue& queue)
{
//Step 1. Set the device adapter to this thread to TBB.
//This makes sure that any vtkm::filters used by our
@ -84,11 +84,11 @@ void process_block_openMP(RuntimeTaskQueue& queue)
//Step 4. Notify the queue that we finished processing this task
queue.completedTask();
std::cout << "finished a block on tbb (" << std::this_thread::get_id() << ")" << std::endl;
std::cout << "finished a partition on tbb (" << std::this_thread::get_id() << ")" << std::endl;
}
}
void process_block_cuda(RuntimeTaskQueue& queue, int gpuId)
void process_partition_cuda(RuntimeTaskQueue& queue, int gpuId)
{
//Step 1. Set the device adapter to this thread to cuda.
//This makes sure that any vtkm::filters used by our
@ -113,7 +113,7 @@ void process_block_cuda(RuntimeTaskQueue& queue, int gpuId)
//Step 4. Notify the queue that we finished processing this task
queue.completedTask();
std::cout << "finished a block on cuda (" << std::this_thread::get_id() << ")" << std::endl;
std::cout << "finished a partition on cuda (" << std::this_thread::get_id() << ")" << std::endl;
}
}
@ -149,10 +149,10 @@ VTKM_CONT MultiDeviceGradient::MultiDeviceGradient()
//The number of workers per GPU is purely arbitrary currently,
//but in general we want multiple of them so we can overlap compute
//and transfer
this->Workers.emplace_back(std::bind(process_block_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_block_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_block_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_block_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_partition_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_partition_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_partition_cuda, std::ref(this->Queue), i));
this->Workers.emplace_back(std::bind(process_partition_cuda, std::ref(this->Queue), i));
}
}
//Step 3. Launch a worker that will use openMP (if enabled).
@ -161,7 +161,7 @@ VTKM_CONT MultiDeviceGradient::MultiDeviceGradient()
else if (runOnOpenMP)
{
std::cout << "adding a openMP worker" << std::endl;
this->Workers.emplace_back(std::bind(process_block_openMP, std::ref(this->Queue)));
this->Workers.emplace_back(std::bind(process_partition_openMP, std::ref(this->Queue)));
}
//Step 4. Launch a worker that will use tbb (if enabled).
//The threads share a queue object so we need to explicitly pass it
@ -169,7 +169,7 @@ VTKM_CONT MultiDeviceGradient::MultiDeviceGradient()
else if (runOnTbb)
{
std::cout << "adding a tbb worker" << std::endl;
this->Workers.emplace_back(std::bind(process_block_tbb, std::ref(this->Queue)));
this->Workers.emplace_back(std::bind(process_partition_tbb, std::ref(this->Queue)));
}
}
@ -187,49 +187,50 @@ VTKM_CONT MultiDeviceGradient::~MultiDeviceGradient()
//-----------------------------------------------------------------------------
template <typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::MultiBlock MultiDeviceGradient::PrepareForExecution(
const vtkm::cont::MultiBlock& mb,
inline VTKM_CONT vtkm::cont::PartitionedDataSet MultiDeviceGradient::PrepareForExecution(
const vtkm::cont::PartitionedDataSet& pds,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy)
{
//Step 1. Say that we have no more to submit for this multi block
//Step 1. Say that we have no more to submit for this PartitionedDataSet
//This is needed to happen for each execute as we want to support
//the same filter being used for multiple inputs
this->Queue.reset();
//Step 2. Construct the multi-block we are going to fill. The size signature
//to MultiBlock just reserves size
vtkm::cont::MultiBlock output;
output.AddBlocks(std::vector<vtkm::cont::DataSet>(static_cast<size_t>(mb.GetNumberOfBlocks())));
vtkm::cont::MultiBlock* outPtr = &output;
//Step 2. Construct the PartitionedDataSet we are going to fill. The size
//signature to PartitionedDataSet just reserves size
vtkm::cont::PartitionedDataSet output;
output.AppendPartitions(
std::vector<vtkm::cont::DataSet>(static_cast<size_t>(pds.GetNumberOfPartitions())));
vtkm::cont::PartitionedDataSet* outPtr = &output;
//Step 3. Construct the filter we want to run on each block
//Step 3. Construct the filter we want to run on each partition
vtkm::filter::Gradient gradient;
gradient.SetComputePointGradient(this->GetComputePointGradient());
gradient.SetActiveField(this->GetActiveFieldName());
//Step 3b. Post 1 block up as work and block intil it is
//Step 3b. Post 1 partition up as work and block until it is
//complete. This is needed as currently constructing the virtual
//Point Coordinates is not thread safe.
auto block = mb.cbegin();
auto partition = pds.cbegin();
{
vtkm::cont::DataSet input = *block;
vtkm::cont::DataSet input = *partition;
this->Queue.push( //build a lambda that is the work to do
[=]() {
vtkm::filter::Gradient perThreadGrad = gradient;
vtkm::cont::DataSet result = perThreadGrad.Execute(input, policy);
outPtr->ReplaceBlock(0, result);
outPtr->ReplacePartition(0, result);
});
this->Queue.waitForAllTasksToComplete();
block++;
partition++;
}
vtkm::Id index = 1;
for (; block != mb.cend(); ++block)
for (; partition != pds.cend(); ++partition)
{
vtkm::cont::DataSet input = *block;
//Step 4. For each input block construct a lambda
vtkm::cont::DataSet input = *partition;
//Step 4. For each input partition construct a lambda
//and add it to the queue for workers to take. This
//will allows us to have multiple works execute in a non
//blocking manner
@ -238,7 +239,7 @@ inline VTKM_CONT vtkm::cont::MultiBlock MultiDeviceGradient::PrepareForExecution
vtkm::filter::Gradient perThreadGrad = gradient;
vtkm::cont::DataSet result = perThreadGrad.Execute(input, policy);
outPtr->ReplaceBlock(index, result);
outPtr->ReplacePartition(index, result);
});
index++;
}

@ -10,7 +10,7 @@
#ifndef vtk_m_examples_multibackend_TaskQueue_h
#define vtk_m_examples_multibackend_TaskQueue_h
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <condition_variable>
#include <mutex>

@ -9,297 +9,76 @@
//============================================================================
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/filter/Streamline.h>
#include <vtkm/io/reader/VTKDataSetReader.h>
#include <vtkm/io/writer/VTKDataSetWriter.h>
#include <vtkm/worklet/ParticleAdvection.h>
#include <vtkm/worklet/particleadvection/GridEvaluators.h>
#include <vtkm/worklet/particleadvection/Integrators.h>
#include <vtkm/worklet/particleadvection/ParticleAdvectionWorklets.h>
#include <vtkm/worklet/particleadvection/Particles.h>
#include <vtkm/io/reader/BOVDataSetReader.h>
#include <chrono>
#include <vector>
#ifdef BUILDING_TBB_VERSION
#include <tbb/task_scheduler_init.h>
#endif
const vtkm::Id SPARSE = 0;
const vtkm::Id DENSE = 1;
const vtkm::Id MEDIUM = 2;
template <typename T>
static vtkm::Range subRange(vtkm::Range& range, T a, T b)
{
vtkm::Float32 arg1, arg2, len;
arg1 = static_cast<vtkm::Float32>(a);
arg2 = static_cast<vtkm::Float32>(b);
len = static_cast<vtkm::Float32>(range.Length());
return vtkm::Range(range.Min + arg1 * len, range.Min + arg2 * len);
}
template <typename T>
void ignore(T&&)
{
}
void RunTest(const std::string& fname,
vtkm::Id numSeeds,
vtkm::Id numSteps,
vtkm::Float32 stepSize,
vtkm::Id numThreads,
vtkm::Id advectType,
vtkm::Id seeding)
{
using FieldType = vtkm::Float32;
using FieldHandle = vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>>;
vtkm::io::reader::BOVDataSetReader rdr(fname);
vtkm::cont::DataSet ds = rdr.ReadDataSet();
using RGEvalType = vtkm::worklet::particleadvection::GridEvaluator<FieldHandle>;
using RK4RGType = vtkm::worklet::particleadvection::RK4Integrator<RGEvalType>;
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> fieldArray;
ds.GetField(0).GetData().CopyTo(fieldArray);
RGEvalType eval(ds.GetCoordinateSystem(), ds.GetCellSet(0), fieldArray);
RK4RGType rk4(eval, stepSize);
std::vector<vtkm::Vec<FieldType, 3>> seeds;
srand(314);
vtkm::Bounds bounds = ds.GetCoordinateSystem().GetBounds();
if (seeding == SPARSE)
bounds = ds.GetCoordinateSystem().GetBounds();
else if (seeding == DENSE)
{
if (fname.find("astro") != std::string::npos)
{
bounds.X = subRange(bounds.X, .1, .15);
bounds.Y = subRange(bounds.Y, .1, .15);
bounds.Z = subRange(bounds.Z, .1, .15);
}
else if (fname.find("fusion") != std::string::npos)
{
bounds.X = subRange(bounds.X, .8, .85);
bounds.Y = subRange(bounds.Y, .55, .60);
bounds.Z = subRange(bounds.Z, .55, .60);
}
else if (fname.find("fishtank") != std::string::npos)
{
bounds.X = subRange(bounds.X, .1, .15);
bounds.Y = subRange(bounds.Y, .1, .15);
bounds.Z = subRange(bounds.Z, .55, .60);
}
}
else if (seeding == MEDIUM)
{
if (fname.find("astro") != std::string::npos)
{
bounds.X = subRange(bounds.X, .4, .6);
bounds.Y = subRange(bounds.Y, .4, .6);
bounds.Z = subRange(bounds.Z, .4, .6);
}
else if (fname.find("fusion") != std::string::npos)
{
bounds.X = subRange(bounds.X, .01, .99);
bounds.Y = subRange(bounds.Y, .01, .99);
bounds.Z = subRange(bounds.Z, .45, .55);
}
else if (fname.find("fishtank") != std::string::npos)
{
bounds.X = subRange(bounds.X, .4, .6);
bounds.Y = subRange(bounds.Y, .4, .6);
bounds.Z = subRange(bounds.Z, .4, .6);
}
}
for (int i = 0; i < numSeeds; i++)
{
vtkm::Vec<FieldType, 3> p;
vtkm::Float32 rx = (vtkm::Float32)rand() / (vtkm::Float32)RAND_MAX;
vtkm::Float32 ry = (vtkm::Float32)rand() / (vtkm::Float32)RAND_MAX;
vtkm::Float32 rz = (vtkm::Float32)rand() / (vtkm::Float32)RAND_MAX;
p[0] = static_cast<FieldType>(bounds.X.Min + rx * bounds.X.Length());
p[1] = static_cast<FieldType>(bounds.Y.Min + ry * bounds.Y.Length());
p[2] = static_cast<FieldType>(bounds.Z.Min + rz * bounds.Z.Length());
seeds.push_back(p);
}
#ifdef BUILDING_TBB_VERSION
int nT = tbb::task_scheduler_init::default_num_threads();
if (numThreads != -1)
nT = (int)numThreads;
//make sure the task_scheduler_init object is in scope when running sth w/ TBB
tbb::task_scheduler_init init(nT);
#else
ignore(numThreads);
#endif
//time only the actual run
auto t0 = std::chrono::high_resolution_clock::now();
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> seedArray;
seedArray = vtkm::cont::make_ArrayHandle(seeds);
if (advectType == 0)
{
vtkm::worklet::ParticleAdvection particleAdvection;
particleAdvection.Run(rk4, seedArray, numSteps);
}
else
{
vtkm::worklet::Streamline streamline;
streamline.Run(rk4, seedArray, numSteps);
}
auto t1 = std::chrono::high_resolution_clock::now() - t0;
auto runtime = std::chrono::duration_cast<std::chrono::milliseconds>(t1).count();
std::cerr << "Runtime = " << runtime << " ms " << std::endl;
}
bool ParseArgs(int argc,
char** argv,
const vtkm::cont::InitializeResult& config,
vtkm::Id& numSeeds,
vtkm::Id& numSteps,
vtkm::Float32& stepSize,
vtkm::Id& advectType,
vtkm::Id& stepsPerRound,
vtkm::Id& particlesPerRound,
vtkm::Id& numThreads,
std::string& dataFile,
std::string& pgmType,
bool& dumpOutput,
vtkm::Id& seeding)
{
numSeeds = 100;
numSteps = 100;
stepSize = 0.1f;
advectType = 0;
stepsPerRound = -1;
particlesPerRound = -1;
numThreads = -1;
dataFile = "";
pgmType = config.Device.GetName();
dumpOutput = false;
seeding = SPARSE;
if (argc < 2)
{
std::cerr << "Usage " << argv[0] << std::endl;
std::cerr << " -seeds #seeds" << std::endl;
std::cerr << " -steps maxSteps" << std::endl;
std::cerr << " -h stepSize" << std::endl;
std::cerr << " -particle : particle push" << std::endl;
std::cerr << " -streamline steps_per_round (-1 = 0 rounds): particle history" << std::endl;
std::cerr << " -t #numThreads" << std::endl;
std::cerr << " -file dataFile" << std::endl;
std::cerr << " -dump : dump output points" << std::endl << std::endl;
std::cerr << "General VTK-m Options" << std::endl;
std::cerr << config.Usage << std::endl;
return false;
}
for (int i = 1; i < argc; i++)
{
std::string arg = argv[i];
if (arg == "-seeds")
numSeeds = static_cast<vtkm::Id>(atoi(argv[++i]));
else if (arg == "-steps")
numSteps = static_cast<vtkm::Id>(atoi(argv[++i]));
else if (arg == "-h")
stepSize = static_cast<vtkm::Float32>(atof(argv[++i]));
else if (arg == "-particle")
advectType = 0;
else if (arg == "-streamline")
{
advectType = 1;
}
else if (arg == "-streamlineS")
{
advectType = 1;
stepsPerRound = static_cast<vtkm::Id>(atoi(argv[++i]));
}
else if (arg == "-streamlineP")
{
advectType = 1;
particlesPerRound = static_cast<vtkm::Id>(atoi(argv[++i]));
}
else if (arg == "-streamlineSP")
{
advectType = 1;
stepsPerRound = static_cast<vtkm::Id>(atoi(argv[++i]));
particlesPerRound = static_cast<vtkm::Id>(atoi(argv[++i]));
}
else if (arg == "-file")
dataFile = argv[++i];
else if (arg == "-t")
numThreads = static_cast<vtkm::Id>(atoi(argv[++i]));
else if (arg == "-dump")
dumpOutput = true;
else if (arg == "-sparse")
seeding = SPARSE;
else if (arg == "-dense")
seeding = DENSE;
else if (arg == "-medium")
seeding = MEDIUM;
else
std::cerr << "Unexpected argument: " << arg << std::endl;
}
if (dataFile.size() == 0)
{
std::cerr << "Error: no data file specified" << std::endl;
return false;
}
//Congratulations user, we have a valid run:
std::cerr << pgmType << ": " << numSeeds << " " << numSteps << " " << stepSize << " ";
if (advectType == 0)
std::cerr << "PP ";
else
std::cerr << "SL ";
std::cerr << numThreads << " ";
std::cerr << dataFile << std::endl;
return true;
}
// Example computing streamlines.
// An example vector field is available in the vtk-m data directory: magField.vtk
// Example usage:
// this will advect 200 particles 50 steps using a step size of 0.01
//
// Particle_Advection <path-to-data-dir>/magField.vtk vec 200 50 0.01 output.vtk
//
int main(int argc, char** argv)
{
// Process vtk-m general args
auto opts = vtkm::cont::InitializeOptions::DefaultAnyDevice;
auto config = vtkm::cont::Initialize(argc, argv, opts);
vtkm::Id numSeeds = 100, numSteps = 100, advectType = 0, numThreads = -1, stepsPerRound = -1,
particlesPerRound = -1;
vtkm::Float32 stepSize = 0.1f;
std::string dataFile, pgmType;
vtkm::Id seeding = SPARSE;
bool dumpOutput = false;
if (!ParseArgs(argc,
argv,
config,
numSeeds,
numSteps,
stepSize,
advectType,
stepsPerRound,
particlesPerRound,
numThreads,
dataFile,
pgmType,
dumpOutput,
seeding))
if (argc != 7)
{
std::cerr << "Usage: " << argv[0] << " dataFile varName numSeeds numSteps stepSize outputFile"
<< std::endl;
return -1;
}
RunTest(dataFile, numSeeds, numSteps, stepSize, numThreads, advectType, seeding);
std::string dataFile = argv[1];
std::string varName = argv[2];
vtkm::Id numSeeds = std::stoi(argv[3]);
vtkm::Id numSteps = std::stoi(argv[4]);
vtkm::FloatDefault stepSize = std::stof(argv[5]);
std::string outputFile = argv[6];
vtkm::cont::DataSet ds;
if (dataFile.find(".vtk") != std::string::npos)
{
vtkm::io::reader::VTKDataSetReader rdr(dataFile);
ds = rdr.ReadDataSet();
}
else
{
std::cerr << "Unsupported data file: " << dataFile << std::endl;
return -1;
}
//create seeds randomly placed withing the bounding box of the data.
vtkm::Bounds bounds = ds.GetCoordinateSystem().GetBounds();
std::vector<vtkm::Vec3f> seeds;
for (int i = 0; i < numSeeds; i++)
{
vtkm::Vec3f p;
vtkm::FloatDefault rx = (vtkm::FloatDefault)rand() / (vtkm::FloatDefault)RAND_MAX;
vtkm::FloatDefault ry = (vtkm::FloatDefault)rand() / (vtkm::FloatDefault)RAND_MAX;
vtkm::FloatDefault rz = (vtkm::FloatDefault)rand() / (vtkm::FloatDefault)RAND_MAX;
p[0] = static_cast<vtkm::FloatDefault>(bounds.X.Min + rx * bounds.X.Length());
p[1] = static_cast<vtkm::FloatDefault>(bounds.Y.Min + ry * bounds.Y.Length());
p[2] = static_cast<vtkm::FloatDefault>(bounds.Z.Min + rz * bounds.Z.Length());
seeds.push_back(p);
}
vtkm::cont::ArrayHandle<vtkm::Vec3f> seedArray = vtkm::cont::make_ArrayHandle(seeds);
//compute streamlines
vtkm::filter::Streamline streamline;
streamline.SetStepSize(stepSize);
streamline.SetNumberOfSteps(numSteps);
streamline.SetSeeds(seedArray);
streamline.SetActiveField(varName);
auto output = streamline.Execute(ds);
vtkm::io::writer::VTKDataSetWriter wrt(outputFile);
wrt.WriteDataSet(output);
return 0;
}

@ -67,11 +67,11 @@ void TubeThatSpiral(vtkm::FloatDefault radius, vtkm::Id numLineSegments, vtkm::I
// This generates a new pointset, and new cell set.
vtkm::cont::ArrayHandle<vtkm::Vec3f> tubePoints;
vtkm::cont::CellSetSingleType<> tubeCells;
tubeWorklet.Run(ds.GetCoordinateSystem(0), ds.GetCellSet(0), tubePoints, tubeCells);
tubeWorklet.Run(ds.GetCoordinateSystem(), ds.GetCellSet(), tubePoints, tubeCells);
vtkm::cont::DataSet tubeDataset;
tubeDataset.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coords", tubePoints));
tubeDataset.AddCellSet(tubeCells);
tubeDataset.SetCellSet(tubeCells);
vtkm::Bounds coordsBounds = tubeDataset.GetCoordinateSystem().GetBounds();

@ -10,7 +10,7 @@
#include <vtkm/ImplicitFunction.h>
#include <vtkm/cont/Algorithm.h>
#include <vtkm/cont/AssignerMultiBlock.h>
#include <vtkm/cont/AssignerPartitionedDataSet.h>
#include <vtkm/cont/BoundsGlobalCompute.h>
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/Serialization.h>
@ -204,14 +204,14 @@ public:
~RedistributePoints() {}
template <typename DerivedPolicy>
VTKM_CONT vtkm::cont::MultiBlock PrepareForExecution(
const vtkm::cont::MultiBlock& input,
VTKM_CONT vtkm::cont::PartitionedDataSet PrepareForExecution(
const vtkm::cont::PartitionedDataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
};
template <typename DerivedPolicy>
inline VTKM_CONT vtkm::cont::MultiBlock RedistributePoints::PrepareForExecution(
const vtkm::cont::MultiBlock& input,
inline VTKM_CONT vtkm::cont::PartitionedDataSet RedistributePoints::PrepareForExecution(
const vtkm::cont::PartitionedDataSet& input,
const vtkm::filter::PolicyBase<DerivedPolicy>& policy)
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
@ -219,7 +219,7 @@ inline VTKM_CONT vtkm::cont::MultiBlock RedistributePoints::PrepareForExecution(
// let's first get the global bounds of the domain
vtkm::Bounds gbounds = vtkm::cont::BoundsGlobalCompute(input);
vtkm::cont::AssignerMultiBlock assigner(input.GetNumberOfBlocks());
vtkm::cont::AssignerPartitionedDataSet assigner(input.GetNumberOfPartitions());
vtkmdiy::RegularDecomposer<vtkmdiy::ContinuousBounds> decomposer(
/*dim*/ 3, internal::convert(gbounds), assigner.nblocks());
@ -230,19 +230,19 @@ inline VTKM_CONT vtkm::cont::MultiBlock RedistributePoints::PrepareForExecution(
[](void* ptr) { delete static_cast<vtkm::cont::DataSet*>(ptr); });
decomposer.decompose(comm.rank(), assigner, master);
assert(static_cast<vtkm::Id>(master.size()) == input.GetNumberOfBlocks());
assert(static_cast<vtkm::Id>(master.size()) == input.GetNumberOfPartitions());
// let's populate local blocks
master.foreach ([&input](vtkm::cont::DataSet* ds, const vtkmdiy::Master::ProxyWithLink& proxy) {
auto lid = proxy.master()->lid(proxy.gid());
*ds = input.GetBlock(lid);
*ds = input.GetPartition(lid);
});
internal::Redistributor<DerivedPolicy> redistributor(decomposer, policy);
vtkmdiy::all_to_all(master, assigner, redistributor, /*k=*/2);
vtkm::cont::MultiBlock result;
vtkm::cont::PartitionedDataSet result;
master.foreach ([&result](vtkm::cont::DataSet* ds, const vtkmdiy::Master::ProxyWithLink&) {
result.AddBlock(*ds);
result.AppendPartition(*ds);
});
return result;

@ -8,127 +8,95 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/worklet/ParticleAdvection.h>
#include <vtkm/worklet/particleadvection/Integrators.h>
#include <vtkm/worklet/particleadvection/ParticleAdvectionWorklets.h>
#include <vtkm/worklet/particleadvection/TemporalGridEvaluators.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/io/reader/BOVDataSetReader.h>
#include <vtkm/io/writer/VTKDataSetWriter.h>
#include <cstdlib>
#include <string>
#include <vector>
// The way to verify if the code produces correct streamlines
// is to do a visual test by using VisIt/ParaView to visualize
// the file written by this method.
int renderAndWriteDataSet(const vtkm::cont::DataSet& dataset)
{
std::cout << "Trying to render the dataset" << std::endl;
vtkm::io::writer::VTKDataSetWriter writer("pathlines.vtk");
writer.WriteDataSet(dataset);
return 0;
}
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Initialize.h>
#include <vtkm/cont/Timer.h>
#include <vtkm/filter/Pathline.h>
void RunTest(vtkm::Id numSteps, vtkm::Float32 stepSize, vtkm::Id advectType)
{
using FieldType = vtkm::Float32;
using FieldHandle = vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>>;
// These lines read two datasets, which are BOVs.
// Currently VTKm does not support providing time series datasets
// In the hackiest way possible this pathlines example run using
// two time slices. The way to provide more datasets will be explored
// as VTKm evolves.
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> fieldArray1;
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> fieldArray2;
vtkm::io::reader::BOVDataSetReader reader1("slice1.bov");
vtkm::cont::DataSet ds1 = reader1.ReadDataSet();
ds1.GetField(0).GetData().CopyTo(fieldArray1);
vtkm::io::reader::BOVDataSetReader reader2("slice2.bov");
vtkm::cont::DataSet ds2 = reader2.ReadDataSet();
ds2.GetField(0).GetData().CopyTo(fieldArray2);
// The only change in this example and the vanilla particle advection example is
// this example makes use of the TemporalGridEvaluator.
using GridEvaluator = vtkm::worklet::particleadvection::TemporalGridEvaluator<FieldHandle>;
using Integrator = vtkm::worklet::particleadvection::EulerIntegrator<GridEvaluator>;
GridEvaluator eval(ds1.GetCoordinateSystem(),
ds1.GetCellSet(0),
fieldArray1,
0,
ds2.GetCoordinateSystem(),
ds2.GetCellSet(0),
fieldArray2,
10.0);
Integrator integrator(eval, stepSize);
// This example does not work on scale, works on basic 11 particles
// so the results are more tractible
std::vector<vtkm::Vec<FieldType, 3>> seeds;
FieldType x = 0, y = 5, z = 0;
for (int i = 0; i <= 11; i++)
{
vtkm::Vec<FieldType, 3> point;
point[0] = x;
point[1] = y;
point[2] = z++;
seeds.push_back(point);
}
vtkm::cont::ArrayHandle<vtkm::Vec<FieldType, 3>> seedArray;
seedArray = vtkm::cont::make_ArrayHandle(seeds);
if (advectType == 0)
{
vtkm::worklet::ParticleAdvection particleAdvection;
particleAdvection.Run(integrator, seedArray, numSteps);
}
else
{
vtkm::worklet::Streamline streamline;
vtkm::worklet::StreamlineResult res = streamline.Run(integrator, seedArray, numSteps);
vtkm::cont::DataSet outData;
vtkm::cont::CoordinateSystem outputCoords("coordinates", res.positions);
outData.AddCellSet(res.polyLines);
outData.AddCoordinateSystem(outputCoords);
renderAndWriteDataSet(outData);
}
}
#include <vtkm/io/reader/VTKDataSetReader.h>
#include <vtkm/io/writer/VTKDataSetWriter.h>
int main(int argc, char** argv)
{
auto opts = vtkm::cont::InitializeOptions::DefaultAnyDevice;
auto config = vtkm::cont::Initialize(argc, argv, opts);
std::cout << "TemporalAdvection Example" << std::endl;
std::cout << "Parameters are [options] numSteps stepSize advectionType" << std::endl << std::endl;
std::cout << "advectionType Particles=0 Streamlines=1" << std::endl;
// Sample data to use this example can be found in the data directory of the
// VTK-m repo in the location temporal_datasets.
// These example with these datasets can be used for this example as :
// ./Temporal_Advection DoubleGyre_0.vtk 0.0 DoubleGyre_5.vtk 5.0
// velocity 500 0.025 pathlines.vtk
std::cout
<< "Parameters : [options] slice1 time1 slice2 time2 field num_steps step_size output\n"
<< "slice1 : Time slice 1, sample data in vtk-m/data/temporal_datasets/Double_Gyre0.vtk\n"
<< "time1 : simulation time for slice 1, for sample data use 0.0\n"
<< "slice2 : Time slice 2, sample data in vtk-m/data/temporal_datasets/Double_Gyre5.vtk\n"
<< "time2 : simulation time for slice 2, for sample data use 5.0\n"
<< "field : active velocity field in the data set, for sample data use 'velocity'\n"
<< "num_steps : maximum number of steps for advection, for sample data use 500\n"
<< "step_size : the size of a single step during advection, for sample data use 0.025\n"
<< "output : the name of the output file" << std::endl;
vtkm::Id numSteps;
vtkm::Float32 stepSize;
vtkm::Id advectionType;
if (argc < 4)
if (argc < 8)
{
std::cout << "Wrong number of parameters provided" << std::endl;
exit(EXIT_FAILURE);
}
numSteps = atoi(argv[1]);
stepSize = static_cast<vtkm::Float32>(atof(argv[2]));
advectionType = atoi(argv[3]);
std::string fieldName, datasetName1, datasetName2, outputName;
vtkm::FloatDefault time1, time2;
RunTest(numSteps, stepSize, advectionType);
vtkm::Id numSteps;
vtkm::Float32 stepSize;
datasetName1 = std::string(argv[1]);
time1 = static_cast<vtkm::FloatDefault>(atof(argv[2]));
datasetName2 = std::string(argv[3]);
time2 = static_cast<vtkm::FloatDefault>(atof(argv[4]));
fieldName = std::string(argv[5]);
numSteps = atoi(argv[6]);
stepSize = static_cast<vtkm::Float32>(atof(argv[7]));
outputName = std::string(argv[8]);
vtkm::io::reader::VTKDataSetReader reader1(datasetName1);
vtkm::cont::DataSet ds1 = reader1.ReadDataSet();
vtkm::io::reader::VTKDataSetReader reader2(datasetName2);
vtkm::cont::DataSet ds2 = reader2.ReadDataSet();
// Use the coordinate system as seeds for performing advection
vtkm::cont::ArrayHandle<vtkm::Vec3f> seeds;
vtkm::cont::ArrayCopy(ds1.GetCoordinateSystem().GetData(), seeds);
// Instantiate the filter by providing necessary parameters.
// Necessary parameters are :
vtkm::filter::Pathline pathlineFilter;
pathlineFilter.SetActiveField(fieldName);
// 1. The current and next time slice. The current time slice is passed
// through the parameter to the Execute method.
pathlineFilter.SetNextDataSet(ds2);
// 2. The current and next times, these times will be used to interpolate
// the velocities for particle positions in space and time.
pathlineFilter.SetCurrentTime(time1);
pathlineFilter.SetNextTime(time2);
// 3. Maximum number of steps the particle is allowed to take until termination.
pathlineFilter.SetNumberOfSteps(numSteps);
// 4. Length for each step.
pathlineFilter.SetStepSize(stepSize);
// 5. Seeds for advection.
pathlineFilter.SetSeeds(seeds);
vtkm::cont::DataSet output = pathlineFilter.Execute(ds1);
// The way to verify if the code produces correct streamlines
// is to do a visual test by using VisIt/ParaView to visualize
// the file written by this method.
vtkm::io::writer::VTKDataSetWriter writer(outputName);
writer.WriteDataSet(output);
return 0;
}

@ -1,64 +0,0 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_BaseComponent_h
#define vtk_m_BaseComponent_h
#include <vtkm/Matrix.h>
#include <vtkm/TypeTraits.h>
#include <vtkm/VecTraits.h>
namespace vtkm
{
namespace detail
{
template <typename VecType, typename DimensionalityTag>
struct BaseComponentImpl;
template <typename VecType>
struct BaseComponentImpl<VecType, vtkm::TypeTraitsVectorTag>
{
private:
using ComponentType = typename vtkm::VecTraits<VecType>::ComponentType;
public:
using Type =
typename BaseComponentImpl<ComponentType,
typename vtkm::TypeTraits<ComponentType>::DimensionalityTag>::Type;
};
template <typename VecType>
struct BaseComponentImpl<VecType, vtkm::TypeTraitsMatrixTag>
: BaseComponentImpl<VecType, vtkm::TypeTraitsVectorTag>
{
};
template <typename ScalarType>
struct BaseComponentImpl<ScalarType, vtkm::TypeTraitsScalarTag>
{
using Type = ScalarType;
};
} // namespace detail
// Finds the base component type of a Vec. If you have a Vec of Vecs, it will
// descend all Vecs until you get to the scalar type.
template <typename VecType>
struct BaseComponent
{
using Type =
typename detail::BaseComponentImpl<VecType,
typename vtkm::TypeTraits<VecType>::DimensionalityTag>::Type;
};
} // namespace vtkm
#endif //vtk_m_BaseComponent_h

@ -18,7 +18,6 @@ vtkm_install_headers(
set(headers
Assert.h
BaseComponent.h
BinaryPredicates.h
BinaryOperators.h
Bitset.h

@ -103,13 +103,10 @@ struct ListTagEmpty : detail::ListRoot
/// A tag that is a construction of two other tags joined together. This struct
/// can be subclassed and still behave like a list tag.
template <typename ListTag1, typename ListTag2>
template <typename... ListTags>
struct ListTagJoin : detail::ListRoot
{
VTKM_IS_LIST_TAG(ListTag1);
VTKM_IS_LIST_TAG(ListTag2);
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTag1>,
internal::ListTagAsBrigandList<ListTag2>>::type;
using list = typename detail::ListJoin<internal::ListTagAsBrigandList<ListTags>...>::type;
};

@ -541,6 +541,7 @@ private:
public:
using ComponentType = T;
using BaseComponentType = typename vtkm::VecTraits<T>::BaseComponentType;
static constexpr vtkm::IdComponent NUM_COMPONENTS = NumRow * NumCol;
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
@ -567,6 +568,15 @@ public:
{
GetComponent(matrix, component) = value;
}
template <typename NewComponentType>
using ReplaceComponentType = vtkm::Matrix<NewComponentType, NumRow, NumCol>;
template <typename NewComponentType>
using ReplaceBaseComponentType =
vtkm::Matrix<typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<NewComponentType>,
NumRow,
NumCol>;
};
//---------------------------------------------------------------------------

@ -147,6 +147,7 @@ struct VecTraits<vtkm::VecAxisAlignedPointCoordinates<NumDimensions>>
using VecType = vtkm::VecAxisAlignedPointCoordinates<NumDimensions>;
using ComponentType = vtkm::Vec3f;
using BaseComponentType = vtkm::FloatDefault;
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
@ -161,6 +162,13 @@ struct VecTraits<vtkm::VecAxisAlignedPointCoordinates<NumDimensions>>
return vector[componentIndex];
}
// These are a bit of a hack since VecAxisAlignedPointCoordinates only supports one component
// type. Using these might not work as expected.
template <typename NewComponentType>
using ReplaceComponentType = vtkm::Vec<NewComponentType, NUM_COMPONENTS>;
template <typename NewComponentType>
using ReplaceBaseComponenttype = vtkm::Vec<vtkm::Vec<NewComponentType, 3>, NUM_COMPONENTS>;
template <vtkm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest)
{

@ -99,6 +99,7 @@ struct VecTraits<vtkm::VecFromPortal<PortalType>>
using VecType = vtkm::VecFromPortal<PortalType>;
using ComponentType = typename VecType::ComponentType;
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
using IsSizeStatic = vtkm::VecTraitsTagSizeVariable;

@ -136,6 +136,7 @@ struct VecTraits<vtkm::VecFromPortalPermute<IndexVecType, PortalType>>
using VecType = vtkm::VecFromPortalPermute<IndexVecType, PortalType>;
using ComponentType = typename VecType::ComponentType;
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
using IsSizeStatic = vtkm::VecTraitsTagSizeVariable;

@ -66,10 +66,19 @@ template <class VecType>
struct VTKM_NEVER_EXPORT VecTraits
{
#ifdef VTKM_DOXYGEN_ONLY
/// Type of the components in the vector.
/// \brief Type of the components in the vector.
///
/// If the type is really a scalar, then the component type is the same as the scalar type.
///
using ComponentType = typename VecType::ComponentType;
/// \brief Base component type in the vector.
///
/// Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it
/// returns the base scalar type at the end of the composition (T in this example).
///
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
/// \brief Number of components in the vector.
///
/// This is only defined for vectors of a static size.
@ -111,6 +120,27 @@ struct VTKM_NEVER_EXPORT VecTraits
vtkm::IdComponent component,
ComponentType value);
/// \brief Get a vector of the same type but with a different component.
///
/// This type resolves to another vector with a different component type. For example,
/// vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2> is vtkm::Vec<T2, N>.
/// This replacement is not recursive. So VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>
/// is vtkm::Vec<T2, N>.
///
template <typename NewComponentType>
using ReplaceComponentType = VecTemplate<NewComponentType, N>;
/// \brief Get a vector of the same type but with a different base component.
///
/// This type resolves to another vector with a different base component type. The replacement
/// is recursive for nested types. For example,
/// VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> is Vec<Vec<T2, M>, N>.
///
template <typename NewComponentType>
using ReplaceBaseComponentType = VecTemplate<
typename VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
N>;
/// Copies the components in the given vector into a given Vec object.
///
template <vktm::IdComponent destSize>
@ -158,10 +188,19 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
{
using VecType = vtkm::Vec<T, Size>;
/// Type of the components in the vector.
/// \brief Type of the components in the vector.
///
/// If the type is really a scalar, then the component type is the same as the scalar type.
///
using ComponentType = typename VecType::ComponentType;
/// \brief Base component type in the vector.
///
/// Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it
/// returns the base scalar type at the end of the composition (T in this example).
///
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
/// Number of components in the vector.
///
static constexpr vtkm::IdComponent NUM_COMPONENTS = VecType::NUM_COMPONENTS;
@ -208,6 +247,27 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::Vec<T, Size>>
vector[component] = value;
}
/// \brief Get a vector of the same type but with a different component.
///
/// This type resolves to another vector with a different component type. For example,
/// vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2> is vtkm::Vec<T2, N>.
/// This replacement is not recursive. So VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>
/// is vtkm::Vec<T2, N>.
///
template <typename NewComponentType>
using ReplaceComponentType = vtkm::Vec<NewComponentType, Size>;
/// \brief Get a vector of the same type but with a different base component.
///
/// This type resolves to another vector with a different base component type. The replacement
/// is recursive for nested types. For example,
/// VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> is Vec<Vec<T2, M>, N>.
///
template <typename NewComponentType>
using ReplaceBaseComponentType = vtkm::Vec<
typename vtkm::VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
Size>;
/// Converts whatever type this vector is into the standard VTKm Tuple.
///
template <vtkm::IdComponent destSize>
@ -222,10 +282,19 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::VecC<T>>
{
using VecType = vtkm::VecC<T>;
/// Type of the components in the vector.
/// \brief Type of the components in the vector.
///
/// If the type is really a scalar, then the component type is the same as the scalar type.
///
using ComponentType = typename VecType::ComponentType;
/// \brief Base component type in the vector.
///
/// Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it
/// returns the base scalar type at the end of the composition (T in this example).
///
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
/// Number of components in the given vector.
///
VTKM_EXEC_CONT
@ -273,6 +342,26 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::VecC<T>>
vector[component] = value;
}
/// \brief Get a vector of the same type but with a different component.
///
/// This type resolves to another vector with a different component type. For example,
/// vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2> is vtkm::Vec<T2, N>.
/// This replacement is not recursive. So VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>
/// is vtkm::Vec<T2, N>.
///
template <typename NewComponentType>
using ReplaceComponentType = vtkm::VecC<NewComponentType>;
/// \brief Get a vector of the same type but with a different base component.
///
/// This type resolves to another vector with a different base component type. The replacement
/// is recursive for nested types. For example,
/// VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> is Vec<Vec<T2, M>, N>.
///
template <typename NewComponentType>
using ReplaceBaseComponentType = vtkm::VecC<
typename vtkm::VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>>;
/// Converts whatever type this vector is into the standard VTKm Tuple.
///
template <vtkm::IdComponent destSize>
@ -287,10 +376,19 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::VecCConst<T>>
{
using VecType = vtkm::VecCConst<T>;
/// Type of the components in the vector.
/// \brief Type of the components in the vector.
///
/// If the type is really a scalar, then the component type is the same as the scalar type.
///
using ComponentType = typename VecType::ComponentType;
/// \brief Base component type in the vector.
///
/// Similar to ComponentType except that for nested vectors (e.g. Vec<Vec<T, M>, N>), it
/// returns the base scalar type at the end of the composition (T in this example).
///
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
/// Number of components in the given vector.
///
VTKM_EXEC_CONT
@ -333,6 +431,26 @@ struct VTKM_NEVER_EXPORT VecTraits<vtkm::VecCConst<T>>
vector[component] = value;
}
/// \brief Get a vector of the same type but with a different component.
///
/// This type resolves to another vector with a different component type. For example,
/// vtkm::VecTraits<vtkm::Vec<T, N>>::ReplaceComponentType<T2> is vtkm::Vec<T2, N>.
/// This replacement is not recursive. So VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2>
/// is vtkm::Vec<T2, N>.
///
template <typename NewComponentType>
using ReplaceComponentType = vtkm::VecCConst<NewComponentType>;
/// \brief Get a vector of the same type but with a different base component.
///
/// This type resolves to another vector with a different base component type. The replacement
/// is recursive for nested types. For example,
/// VecTraits<Vec<Vec<T, M>, N>::ReplaceComponentType<T2> is Vec<Vec<T2, M>, N>.
///
template <typename NewComponentType>
using ReplaceBaseComponentType = vtkm::VecCConst<
typename vtkm::VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>>;
/// Converts whatever type this vector is into the standard VTKm Tuple.
///
template <vtkm::IdComponent destSize>
@ -350,6 +468,7 @@ template <typename ScalarType>
struct VTKM_NEVER_EXPORT VecTraitsBasic
{
using ComponentType = ScalarType;
using BaseComponentType = ScalarType;
static constexpr vtkm::IdComponent NUM_COMPONENTS = 1;
using HasMultipleComponents = vtkm::VecTraitsTagSingleComponent;
using IsSizeStatic = vtkm::VecTraitsTagSizeStatic;
@ -372,6 +491,12 @@ struct VTKM_NEVER_EXPORT VecTraitsBasic
vector = value;
}
template <typename NewComponentType>
using ReplaceComponentType = NewComponentType;
template <typename NewComponentType>
using ReplaceBaseComponentType = NewComponentType;
template <vtkm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(const ScalarType& src, vtkm::Vec<ScalarType, destSize>& dest)
{

@ -103,6 +103,7 @@ struct VecTraits<vtkm::VecVariable<T, MaxSize>>
using VecType = vtkm::VecVariable<T, MaxSize>;
using ComponentType = typename VecType::ComponentType;
using BaseComponentType = typename vtkm::VecTraits<ComponentType>::BaseComponentType;
using HasMultipleComponents = vtkm::VecTraitsTagMultipleComponents;
using IsSizeStatic = vtkm::VecTraitsTagSizeVariable;
@ -131,6 +132,14 @@ struct VecTraits<vtkm::VecVariable<T, MaxSize>>
vector[componentIndex] = value;
}
template <typename NewComponentType>
using ReplaceComponentType = vtkm::VecVariable<NewComponentType, MaxSize>;
template <typename NewComponentType>
using ReplaceBaseComponentType = vtkm::VecVariable<
typename vtkm::VecTraits<ComponentType>::template ReplaceBaseComponentType<NewComponentType>,
MaxSize>;
template <vtkm::IdComponent destSize>
VTKM_EXEC_CONT static void CopyInto(const VecType& src, vtkm::Vec<ComponentType, destSize>& dest)
{

@ -317,6 +317,19 @@ struct ScanExclusiveByKeyFunctor
}
};
template <typename T>
struct ScanExtendedFunctor
{
template <typename Device, typename... Args>
VTKM_CONT bool operator()(Device, Args&&... args)
{
VTKM_IS_DEVICE_ADAPTER_TAG(Device);
vtkm::cont::DeviceAdapterAlgorithm<Device>::ScanExtended(
PrepareArgForExec<Device>(std::forward<Args>(args))...);
return true;
}
};
struct ScheduleFunctor
{
template <typename Device, typename... Args>
@ -976,6 +989,42 @@ struct Algorithm
}
template <typename T, class CIn, class COut>
VTKM_CONT static void ScanExtended(vtkm::cont::DeviceAdapterId devId,
const vtkm::cont::ArrayHandle<T, CIn>& input,
vtkm::cont::ArrayHandle<T, COut>& output)
{
detail::ScanExtendedFunctor<T> functor;
vtkm::cont::TryExecuteOnDevice(devId, functor, input, output);
}
template <typename T, class CIn, class COut>
VTKM_CONT static void ScanExtended(const vtkm::cont::ArrayHandle<T, CIn>& input,
vtkm::cont::ArrayHandle<T, COut>& output)
{
ScanExtended(vtkm::cont::DeviceAdapterTagAny(), input, output);
}
template <typename T, class CIn, class COut, class BinaryFunctor>
VTKM_CONT static void ScanExtended(vtkm::cont::DeviceAdapterId devId,
const vtkm::cont::ArrayHandle<T, CIn>& input,
vtkm::cont::ArrayHandle<T, COut>& output,
BinaryFunctor binaryFunctor,
const T& initialValue)
{
detail::ScanExtendedFunctor<T> functor;
vtkm::cont::TryExecuteOnDevice(devId, functor, input, output, binaryFunctor, initialValue);
}
template <typename T, class CIn, class COut, class BinaryFunctor>
VTKM_CONT static void ScanExtended(const vtkm::cont::ArrayHandle<T, CIn>& input,
vtkm::cont::ArrayHandle<T, COut>& output,
BinaryFunctor binaryFunctor,
const T& initialValue)
{
ScanExtended(vtkm::cont::DeviceAdapterTagAny(), input, output, binaryFunctor, initialValue);
}
template <class Functor>
VTKM_CONT static void Schedule(vtkm::cont::DeviceAdapterId devId,
Functor functor,

@ -23,23 +23,16 @@ namespace vtkm
{
namespace cont
{
/// \brief Does a deep copy from one array to another array.
///
/// Given a source \c ArrayHandle and a destination \c ArrayHandle, this function allocates the
/// destination \c ArrayHandle to the correct size and deeply copies all the values from the source
/// to the destination.
///
/// This method will attempt to copy the data using the device that the input
/// data is already valid on. If the input data is only valid in the control
/// environment, the runtime device tracker is used to try to find another
/// device.
///
template <typename InValueType, typename InStorage, typename OutValueType, typename OutStorage>
VTKM_CONT inline void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InStorage>& source,
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination)
namespace detail
{
// normal element-wise copy:
template <typename InArrayType, typename OutArrayType>
void ArrayCopyImpl(const InArrayType& in, OutArrayType& out, std::false_type /* Copy storage */)
{
// Find the device that already has a copy of the data:
vtkm::cont::DeviceAdapterId devId = source.GetDeviceAdapterId();
vtkm::cont::DeviceAdapterId devId = in.GetDeviceAdapterId();
// If the data is not on any device, let the runtime tracker pick an available
// parallel copy algorithm.
@ -48,14 +41,14 @@ VTKM_CONT inline void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InSto
devId = vtkm::cont::make_DeviceAdapterId(VTKM_DEVICE_ADAPTER_ANY);
}
bool success = vtkm::cont::Algorithm::Copy(devId, source, destination);
bool success = vtkm::cont::Algorithm::Copy(devId, in, out);
if (!success && devId.GetValue() != VTKM_DEVICE_ADAPTER_ANY)
{ // Retry on any device if the first attempt failed.
VTKM_LOG_S(vtkm::cont::LogLevel::Error,
"Failed to run ArrayCopy on device '" << devId.GetName()
<< "'. Retrying on any device.");
success = vtkm::cont::Algorithm::Copy(vtkm::cont::DeviceAdapterTagAny{}, source, destination);
success = vtkm::cont::Algorithm::Copy(vtkm::cont::DeviceAdapterTagAny{}, in, out);
}
if (!success)
@ -63,6 +56,60 @@ VTKM_CONT inline void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InSto
throw vtkm::cont::ErrorExecution("Failed to run ArrayCopy on any device.");
}
}
// Copy storage for implicit arrays, must be of same type:
template <typename ArrayType>
void ArrayCopyImpl(const ArrayType& in, ArrayType& out, std::true_type /* Copy storage */)
{
// This is only called if in/out are the same type and the handle is not
// writable. This allows read-only implicit array handles to be copied.
auto newStorage = in.GetStorage();
out = ArrayType(newStorage);
}
} // namespace detail
/// \brief Does a deep copy from one array to another array.
///
/// Given a source \c ArrayHandle and a destination \c ArrayHandle, this
/// function allocates the destination \c ArrayHandle to the correct size and
/// deeply copies all the values from the source to the destination.
///
/// This method will attempt to copy the data using the device that the input
/// data is already valid on. If the input data is only valid in the control
/// environment, the runtime device tracker is used to try to find another
/// device.
///
/// This should work on some non-writable array handles as well, as long as
/// both \a source and \a destination are the same type.
///
template <typename InValueType, typename InStorage, typename OutValueType, typename OutStorage>
VTKM_CONT void ArrayCopy(const vtkm::cont::ArrayHandle<InValueType, InStorage>& source,
vtkm::cont::ArrayHandle<OutValueType, OutStorage>& destination)
{
using InArrayType = vtkm::cont::ArrayHandle<InValueType, InStorage>;
using OutArrayType = vtkm::cont::ArrayHandle<OutValueType, OutStorage>;
using SameTypes = std::is_same<InArrayType, OutArrayType>;
using IsWritable = vtkm::cont::internal::IsWritableArrayHandle<OutArrayType>;
// There are three cases handled here:
// 1. Output is writable:
// -> Do element-wise copy (normal copy behavior)
// 2. Output is not writable and arrays are same type:
// -> just copy storage (special case for implicit array cloning)
// 3. Output is not writable and arrays are different types:
// -> fail (cannot copy)
// Give a nice error message for case 3:
VTKM_STATIC_ASSERT_MSG(IsWritable::value || SameTypes::value,
"Cannot copy to a read-only array with a different "
"type than the source.");
using JustCopyStorage = std::integral_constant<bool, SameTypes::value && !IsWritable::value>;
// Static dispatch cases 1 & 2
detail::ArrayCopyImpl(source, destination, JustCopyStorage{});
}
}
} // namespace vtkm::cont

@ -74,15 +74,11 @@ struct IsInValidArrayHandle
{
};
/// Checks to see if the ArrayHandle allows
/// writing, as some ArrayHandles (Implicit) don't support writing.
/// This check is compatible with the C++11 type_traits.
/// It contains a typedef named type that is either
/// std::true_type or std::false_type.
/// Both of these have a typedef named value with the respective boolean value.
///
namespace detail
{
template <typename ArrayHandle>
struct IsWritableArrayHandle
struct IsWritableArrayHandleImpl
{
private:
template <typename U,
@ -98,6 +94,17 @@ public:
using type = decltype(hasSet<PortalType>(0));
static constexpr bool value = type::value;
};
}
/// Checks to see if the ArrayHandle allows
/// writing, as some ArrayHandles (Implicit) don't support writing.
/// This check is compatible with the C++11 type_traits.
/// It contains a typedef named type that is either
/// std::true_type or std::false_type.
/// Both of these have a typedef named value with the respective boolean value.
///
template <typename ArrayHandle>
using IsWritableArrayHandle = typename detail::IsWritableArrayHandleImpl<ArrayHandle>::type;
/// Checks to see if the given object is an array handle. This check is
/// compatible with C++11 type_traits. It a typedef named \c type that is

@ -14,8 +14,8 @@
#include <vtkm/cont/Logging.h>
#include <vtkm/BaseComponent.h>
#include <vtkm/Range.h>
#include <vtkm/VecTraits.h>
#include <limits>
@ -70,8 +70,8 @@ private:
{
#ifdef VTKM_ENABLE_LOGGING
using DstValueType = T;
using SrcComp = typename vtkm::BaseComponent<SrcValueType>::Type;
using DstComp = typename vtkm::BaseComponent<DstValueType>::Type;
using SrcComp = typename vtkm::VecTraits<SrcValueType>::BaseComponentType;
using DstComp = typename vtkm::VecTraits<DstValueType>::BaseComponentType;
using SrcLimits = std::numeric_limits<SrcComp>;
using DstLimits = std::numeric_limits<DstComp>;

@ -41,6 +41,7 @@ struct ArrayPortalMultiplexerGetNumberOfValuesFunctor
struct ArrayPortalMultiplexerGetFunctor
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename PortalType>
VTKM_EXEC_CONT typename PortalType::ValueType operator()(const PortalType& portal,
vtkm::Id index) const noexcept
@ -51,6 +52,7 @@ struct ArrayPortalMultiplexerGetFunctor
struct ArrayPortalMultiplexerSetFunctor
{
VTKM_SUPPRESS_EXEC_WARNINGS
template <typename PortalType>
VTKM_EXEC_CONT void operator()(const PortalType& portal,
vtkm::Id index,
@ -211,6 +213,20 @@ public:
{
}
VTKM_CONT bool IsValid() const { return this->ArrayHandleVariant.IsValid(); }
template <typename S>
VTKM_CONT void SetArray(vtkm::cont::ArrayHandle<ValueType, S>&& rhs)
{
this->ArrayHandleVariant = std::move(rhs);
}
template <typename S>
VTKM_CONT void SetArray(const vtkm::cont::ArrayHandle<ValueType, S>& src)
{
this->ArrayHandleVariant = src;
}
private:
struct GetPortalFunctor
{
@ -243,22 +259,56 @@ public:
VTKM_CONT vtkm::Id GetNumberOfValues() const
{
return this->ArrayHandleVariant.CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{});
if (this->IsValid())
{
return this->ArrayHandleVariant.CastAndCall(detail::MultiplexerGetNumberOfValuesFunctor{});
}
else
{
return 0;
}
}
VTKM_CONT void Allocate(vtkm::Id numberOfValues)
{
this->ArrayHandleVariant.CastAndCall(detail::MultiplexerAllocateFunctor{}, numberOfValues);
if (this->IsValid())
{
this->ArrayHandleVariant.CastAndCall(detail::MultiplexerAllocateFunctor{}, numberOfValues);
}
else if (numberOfValues > 0)
{
throw vtkm::cont::ErrorBadValue(
"Attempted to allocate an ArrayHandleMultiplexer with no underlying array.");
}
else
{
// Special case, OK to perform "0" allocation on invalid array.
}
}
VTKM_CONT void Shrink(vtkm::Id numberOfValues)
{
this->ArrayHandleVariant.CastAndCall(detail::MultiplexerShrinkFunctor{}, numberOfValues);
if (this->IsValid())
{
this->ArrayHandleVariant.CastAndCall(detail::MultiplexerShrinkFunctor{}, numberOfValues);
}
else if (numberOfValues > 0)
{
throw vtkm::cont::ErrorBadValue(
"Attempted to allocate an ArrayHandleMultiplexer with no underlying array.");
}
else
{
// Special case, OK to perform "0" allocation on invalid array.
}
}
VTKM_CONT void ReleaseResources()
{
this->ArrayHandleVariant.CastAndCall(detail::MultiplexerReleaseResourcesFunctor{});
if (this->IsValid())
{
this->ArrayHandleVariant.CastAndCall(detail::MultiplexerReleaseResourcesFunctor{});
}
}
VTKM_CONT ArrayHandleVariantType& GetArrayHandleVariant() { return this->ArrayHandleVariant; }
@ -462,8 +512,31 @@ public:
: Superclass(StorageType(std::move(rhs)))
{
}
VTKM_CONT bool IsValid() const { return this->GetStorage().IsValid(); }
template <typename S>
VTKM_CONT void SetArray(vtkm::cont::ArrayHandle<ValueType, S>&& rhs)
{
this->GetStorage().SetArray(std::move(rhs));
}
template <typename S>
VTKM_CONT void SetArray(const vtkm::cont::ArrayHandle<ValueType, S>& src)
{
this->GetStorage().SetArray(src);
}
};
/// \brief Converts a \c vtkm::ListTag to an \c ArrayHandleMultiplexer
///
/// The argument of this template must be a vtkm::ListTag and furthermore all the types in
/// the list tag must be some type of \c ArrayHandle. The templated type gets aliased to
/// an \c ArrayHandleMultiplexer that can store any of these ArrayHandle types.
///
template <typename ListTag>
using ArrayHandleMultiplexerFromListTag = vtkm::ListTagApply<ListTag, ArrayHandleMultiplexer>;
} // namespace cont
} // namespace vtkm

@ -1,80 +0,0 @@
//============================================================================
// 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/AssignerMultiBlock.h>
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/thirdparty/diy/diy.h>
#include <algorithm> // std::lower_bound
#include <numeric> // std::iota
namespace vtkm
{
namespace cont
{
VTKM_CONT
AssignerMultiBlock::AssignerMultiBlock(const vtkm::cont::MultiBlock& mb)
: AssignerMultiBlock(mb.GetNumberOfBlocks())
{
}
VTKM_CONT
AssignerMultiBlock::AssignerMultiBlock(vtkm::Id num_blocks)
: vtkmdiy::StaticAssigner(vtkm::cont::EnvironmentTracker::GetCommunicator().size(), 1)
, IScanBlockCounts()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
if (comm.size() > 1)
{
vtkm::Id iscan;
vtkmdiy::mpi::scan(comm, num_blocks, iscan, std::plus<vtkm::Id>());
vtkmdiy::mpi::all_gather(comm, iscan, this->IScanBlockCounts);
}
else
{
this->IScanBlockCounts.push_back(num_blocks);
}
this->set_nblocks(static_cast<int>(this->IScanBlockCounts.back()));
}
VTKM_CONT
void AssignerMultiBlock::local_gids(int my_rank, std::vector<int>& gids) const
{
const size_t s_rank = static_cast<size_t>(my_rank);
if (my_rank == 0)
{
assert(this->IScanBlockCounts.size() > 0);
gids.resize(static_cast<size_t>(this->IScanBlockCounts[s_rank]));
std::iota(gids.begin(), gids.end(), 0);
}
else if (my_rank > 0 && s_rank < this->IScanBlockCounts.size())
{
gids.resize(
static_cast<size_t>(this->IScanBlockCounts[s_rank] - this->IScanBlockCounts[s_rank - 1]));
std::iota(gids.begin(), gids.end(), static_cast<int>(this->IScanBlockCounts[s_rank - 1]));
}
}
VTKM_CONT
int AssignerMultiBlock::rank(int gid) const
{
return static_cast<int>(
std::lower_bound(this->IScanBlockCounts.begin(), this->IScanBlockCounts.end(), gid + 1) -
this->IScanBlockCounts.begin());
}
} // vtkm::cont
} // vtkm

@ -0,0 +1,81 @@
//============================================================================
// 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/AssignerPartitionedDataSet.h>
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <vtkm/thirdparty/diy/diy.h>
#include <algorithm> // std::lower_bound
#include <numeric> // std::iota
namespace vtkm
{
namespace cont
{
VTKM_CONT
AssignerPartitionedDataSet::AssignerPartitionedDataSet(const vtkm::cont::PartitionedDataSet& pds)
: AssignerPartitionedDataSet(pds.GetNumberOfPartitions())
{
}
VTKM_CONT
AssignerPartitionedDataSet::AssignerPartitionedDataSet(vtkm::Id num_partitions)
: vtkmdiy::StaticAssigner(vtkm::cont::EnvironmentTracker::GetCommunicator().size(), 1)
, IScanPartitionCounts()
{
auto comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
if (comm.size() > 1)
{
vtkm::Id iscan;
vtkmdiy::mpi::scan(comm, num_partitions, iscan, std::plus<vtkm::Id>());
vtkmdiy::mpi::all_gather(comm, iscan, this->IScanPartitionCounts);
}
else
{
this->IScanPartitionCounts.push_back(num_partitions);
}
this->set_nblocks(static_cast<int>(this->IScanPartitionCounts.back()));
}
VTKM_CONT
void AssignerPartitionedDataSet::local_gids(int my_rank, std::vector<int>& gids) const
{
const size_t s_rank = static_cast<size_t>(my_rank);
if (my_rank == 0)
{
assert(this->IScanPartitionCounts.size() > 0);
gids.resize(static_cast<size_t>(this->IScanPartitionCounts[s_rank]));
std::iota(gids.begin(), gids.end(), 0);
}
else if (my_rank > 0 && s_rank < this->IScanPartitionCounts.size())
{
gids.resize(static_cast<size_t>(this->IScanPartitionCounts[s_rank] -
this->IScanPartitionCounts[s_rank - 1]));
std::iota(gids.begin(), gids.end(), static_cast<int>(this->IScanPartitionCounts[s_rank - 1]));
}
}
VTKM_CONT
int AssignerPartitionedDataSet::rank(int gid) const
{
return static_cast<int>(std::lower_bound(this->IScanPartitionCounts.begin(),
this->IScanPartitionCounts.end(),
gid + 1) -
this->IScanPartitionCounts.begin());
}
} // vtkm::cont
} // vtkm

@ -7,8 +7,8 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#ifndef vtk_m_cont_AssignerMultiBlock_h
#define vtk_m_cont_AssignerMultiBlock_h
#ifndef vtk_m_cont_AssignerPartitionedDataSet_h
#define vtk_m_cont_AssignerPartitionedDataSet_h
#include <vtkm/cont/vtkm_cont_export.h>
@ -31,31 +31,32 @@ namespace vtkm
namespace cont
{
class MultiBlock;
class PartitionedDataSet;
/// \brief Assigner for `MultiBlock` blocks.
/// \brief Assigner for PartitionedDataSet partitions.
///
/// `AssignerMultiBlock` is a `vtkmdiy::StaticAssigner` implementation that uses
/// `MultiBlock`'s block distribution to build global-id/rank associations
/// needed for several `diy` operations.
/// It uses a contiguous assignment strategy to map blocks to global ids i.e.
/// blocks on rank 0 come first, then rank 1, etc. Any rank may have 0 blocks.
/// `AssignerPartitionedDataSet` is a `vtkmdiy::StaticAssigner` implementation
/// that uses `PartitionedDataSet`'s partition distribution to build
/// global-id/rank associations needed for several `diy` operations.
/// It uses a contiguous assignment strategy to map partitions to global ids,
/// i.e. partitions on rank 0 come first, then rank 1, etc. Any rank may have 0
/// partitions.
///
/// AssignerMultiBlock uses collectives in the constructor hence it is
/// AssignerPartitionedDataSet uses collectives in the constructor hence it is
/// essential it gets created on all ranks irrespective of whether the rank has
/// any blocks.
/// any partitions.
///
class VTKM_CONT_EXPORT AssignerMultiBlock : public vtkmdiy::StaticAssigner
class VTKM_CONT_EXPORT AssignerPartitionedDataSet : public vtkmdiy::StaticAssigner
{
public:
/// Initialize the assigner using a multiblock dataset.
/// Initialize the assigner using a partitioned dataset.
/// This may initialize collective operations to populate the assigner with
/// information about blocks on all ranks.
/// information about partitions on all ranks.
VTKM_CONT
AssignerMultiBlock(const vtkm::cont::MultiBlock& mb);
AssignerPartitionedDataSet(const vtkm::cont::PartitionedDataSet& pds);
VTKM_CONT
AssignerMultiBlock(vtkm::Id num_blocks);
AssignerPartitionedDataSet(vtkm::Id num_partitions);
///@{
/// vtkmdiy::Assigner API implementation.
@ -66,7 +67,7 @@ public:
int rank(int gid) const override;
//@}
private:
std::vector<vtkm::Id> IScanBlockCounts;
std::vector<vtkm::Id> IScanPartitionCounts;
};
}
}

@ -11,6 +11,7 @@
#define vtk_m_cont_AtomicArray_h
#include <vtkm/ListTag.h>
#include <vtkm/StaticAssert.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DeviceAdapter.h>
#include <vtkm/cont/ExecutionObjectBase.h>
@ -23,7 +24,8 @@ namespace cont
/// \brief A type list containing types that can be used with an AtomicArray.
///
struct AtomicArrayTypeListTag : vtkm::ListTagBase<vtkm::Int32, vtkm::Int64>
struct AtomicArrayTypeListTag
: vtkm::ListTagBase<vtkm::UInt32, vtkm::Int32, vtkm::UInt64, vtkm::Int64>
{
};
@ -37,14 +39,19 @@ struct AtomicArrayTypeListTag : vtkm::ListTagBase<vtkm::Int32, vtkm::Int64>
/// vtkm::cont::ArrayHandle that is used as the underlying storage for the
/// AtomicArray
///
/// Supported Operations: add / compare and swap (CAS)
/// Supported Operations: get / add / compare and swap (CAS). See
/// AtomicArrayExecutionObject for details.
///
/// Supported Types: 32 / 64 bit signed integers
/// Supported Types: 32 / 64 bit signed/unsigned integers.
///
///
template <typename T>
class AtomicArray : public vtkm::cont::ExecutionObjectBase
{
static constexpr bool ValueTypeIsValid = vtkm::ListContains<AtomicArrayTypeListTag, T>::value;
VTKM_STATIC_ASSERT_MSG(ValueTypeIsValid, "AtomicArray used with unsupported ValueType.");
public:
using ValueType = T;
@ -54,8 +61,7 @@ public:
{
}
template <typename StorageType>
VTKM_CONT AtomicArray(vtkm::cont::ArrayHandle<T, StorageType> handle)
VTKM_CONT AtomicArray(vtkm::cont::ArrayHandle<T> handle)
: Handle(handle)
{
}

@ -11,7 +11,7 @@
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <numeric> // for std::accumulate
@ -31,14 +31,15 @@ vtkm::Bounds BoundsCompute(const vtkm::cont::DataSet& dataset, vtkm::Id coordina
//-----------------------------------------------------------------------------
VTKM_CONT
vtkm::Bounds BoundsCompute(const vtkm::cont::MultiBlock& multiblock,
vtkm::Bounds BoundsCompute(const vtkm::cont::PartitionedDataSet& pds,
vtkm::Id coordinate_system_index)
{
return std::accumulate(multiblock.begin(),
multiblock.end(),
return std::accumulate(pds.begin(),
pds.end(),
vtkm::Bounds(),
[=](const vtkm::Bounds& val, const vtkm::cont::DataSet& block) {
return val + vtkm::cont::BoundsCompute(block, coordinate_system_index);
[=](const vtkm::Bounds& val, const vtkm::cont::DataSet& partition) {
return val +
vtkm::cont::BoundsCompute(partition, coordinate_system_index);
});
}
@ -59,13 +60,13 @@ vtkm::Bounds BoundsCompute(const vtkm::cont::DataSet& dataset, const std::string
//-----------------------------------------------------------------------------
VTKM_CONT
vtkm::Bounds BoundsCompute(const vtkm::cont::MultiBlock& multiblock, const std::string& name)
vtkm::Bounds BoundsCompute(const vtkm::cont::PartitionedDataSet& pds, const std::string& name)
{
return std::accumulate(multiblock.begin(),
multiblock.end(),
return std::accumulate(pds.begin(),
pds.end(),
vtkm::Bounds(),
[=](const vtkm::Bounds& val, const vtkm::cont::DataSet& block) {
return val + vtkm::cont::BoundsCompute(block, name);
[=](const vtkm::Bounds& val, const vtkm::cont::DataSet& partition) {
return val + vtkm::cont::BoundsCompute(partition, name);
});
}
}

@ -19,19 +19,19 @@ namespace cont
{
class DataSet;
class MultiBlock;
class PartitionedDataSet;
//@{
/// \brief Functions to compute bounds for a dataset or multiblock
/// \brief Functions to compute bounds for a single dataSset or partition dataset
///
/// These are utility functions that compute bounds for the dataset or
/// multiblock. When VTK-m is operating in an distributed environment, these
/// are bounds on the local process. To get global bounds across all ranks,
/// use `vtkm::cont::BoundsGlobalCompute` instead.
/// These are utility functions that compute bounds for a single dataset or
/// partitioned dataset. When VTK-m is operating in an distributed environment,
/// these are bounds on the local process. To get global bounds across all
/// ranks, use `vtkm::cont::BoundsGlobalCompute` instead.
///
/// Note that if the provided CoordinateSystem does not exists, empty bounds
/// are returned. Likewise, for MultiBlock, blocks without the chosen CoordinateSystem
/// are skipped.
/// are returned. Likewise, for PartitionedDataSet, partitions without the
/// chosen CoordinateSystem are skipped.
VTKM_CONT_EXPORT
VTKM_CONT
vtkm::Bounds BoundsCompute(const vtkm::cont::DataSet& dataset,
@ -39,7 +39,7 @@ vtkm::Bounds BoundsCompute(const vtkm::cont::DataSet& dataset,
VTKM_CONT_EXPORT
VTKM_CONT
vtkm::Bounds BoundsCompute(const vtkm::cont::MultiBlock& multiblock,
vtkm::Bounds BoundsCompute(const vtkm::cont::PartitionedDataSet& pds,
vtkm::Id coordinate_system_index = 0);
VTKM_CONT_EXPORT
@ -49,7 +49,7 @@ vtkm::Bounds BoundsCompute(const vtkm::cont::DataSet& dataset,
VTKM_CONT_EXPORT
VTKM_CONT
vtkm::Bounds BoundsCompute(const vtkm::cont::MultiBlock& multiblock,
vtkm::Bounds BoundsCompute(const vtkm::cont::PartitionedDataSet& pds,
const std::string& coordinate_system_name);
//@}
}

@ -13,7 +13,7 @@
#include <vtkm/cont/CoordinateSystem.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/FieldRangeGlobalCompute.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <numeric> // for std::accumulate
@ -50,10 +50,10 @@ vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::DataSet& dataset,
//-----------------------------------------------------------------------------
VTKM_CONT
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::MultiBlock& multiblock,
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::PartitionedDataSet& pds,
vtkm::Id coordinate_system_index)
{
return detail::MergeBoundsGlobal(vtkm::cont::BoundsCompute(multiblock, coordinate_system_index));
return detail::MergeBoundsGlobal(vtkm::cont::BoundsCompute(pds, coordinate_system_index));
}
//-----------------------------------------------------------------------------
@ -65,9 +65,9 @@ vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::DataSet& dataset, const std::
//-----------------------------------------------------------------------------
VTKM_CONT
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::MultiBlock& multiblock, const std::string& name)
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::PartitionedDataSet& pds, const std::string& name)
{
return detail::MergeBoundsGlobal(vtkm::cont::BoundsCompute(multiblock, name));
return detail::MergeBoundsGlobal(vtkm::cont::BoundsCompute(pds, name));
}
}
}

@ -19,19 +19,20 @@ namespace cont
{
class DataSet;
class MultiBlock;
class PartitionedDataSet;
//@{
/// \brief Functions to compute bounds for a dataset or multiblock globally
/// \brief Functions to compute bounds for a single dataset or partitioned
/// dataset globally
///
/// These are utility functions that compute bounds for the dataset or
/// multiblock globally i.e. across all ranks when operating in a distributed
/// environment. When VTK-m not operating in an distributed environment, these
/// behave same as `vtkm::cont::BoundsCompute`.
/// These are utility functions that compute bounds for a single dataset or
/// partitioned dataset globally i.e. across all ranks when operating in a
/// distributed environment. When VTK-m not operating in an distributed
/// environment, these behave same as `vtkm::cont::BoundsCompute`.
///
/// Note that if the provided CoordinateSystem does not exists, empty bounds
/// are returned. Likewise, for MultiBlock, blocks without the chosen CoordinateSystem
/// are skipped.
/// are returned. Likewise, for PartitionedDataSet, partitions without the
/// chosen CoordinateSystem are skipped.
VTKM_CONT_EXPORT
VTKM_CONT
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::DataSet& dataset,
@ -39,7 +40,7 @@ vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::DataSet& dataset,
VTKM_CONT_EXPORT
VTKM_CONT
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::MultiBlock& multiblock,
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::PartitionedDataSet& pds,
vtkm::Id coordinate_system_index = 0);
VTKM_CONT_EXPORT
@ -49,7 +50,7 @@ vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::DataSet& dataset,
VTKM_CONT_EXPORT
VTKM_CONT
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::MultiBlock& multiblock,
vtkm::Bounds BoundsGlobalCompute(const vtkm::cont::PartitionedDataSet& pds,
const std::string& coordinate_system_name);
//@}
}

@ -43,7 +43,7 @@ set(headers
ArrayPortal.h
ArrayPortalToIterators.h
ArrayRangeCompute.h
AssignerMultiBlock.h
AssignerPartitionedDataSet.h
AtomicArray.h
BitField.h
BoundsCompute.h
@ -93,7 +93,7 @@ set(headers
Initialize.h
Invoker.h
Logging.h
MultiBlock.h
PartitionedDataSet.h
PointLocator.h
PointLocatorUniformGrid.h
RuntimeDeviceInformation.h
@ -152,7 +152,7 @@ set(sources
set(device_sources
ArrayHandleVirtual.cxx
ArrayRangeCompute.cxx
AssignerMultiBlock.cxx
AssignerPartitionedDataSet.cxx
BoundsCompute.cxx
BoundsGlobalCompute.cxx
CellLocator.cxx
@ -175,7 +175,7 @@ set(sources
Field.cxx
FieldRangeCompute.cxx
FieldRangeGlobalCompute.cxx
MultiBlock.cxx
PartitionedDataSet.cxx
PointLocator.cxx
PointLocatorUniformGrid.cxx
RuntimeDeviceInformation.cxx

@ -33,6 +33,7 @@ template <typename T, typename S, typename U, typename V>
class CellSetExplicit;
template <typename T, typename S>
class CellSetPermutation;
class CellSetExtrude;
/// A Generic interface to CastAndCall. The default implementation simply calls
/// DynamicObject's CastAndCall, but specializations of this function exist for
@ -106,6 +107,15 @@ void CastAndCall(const vtkm::cont::CellSetPermutation<PermutationType, CellSetTy
f(cellset, std::forward<Args>(args)...);
}
/// A specialization of CastAndCall for basic CellSetExtrude types,
/// Since the type is already known no deduction is needed.
/// This specialization is used to simplify numerous worklet algorithms
template <typename Functor, typename... Args>
void CastAndCall(const vtkm::cont::CellSetExtrude& cellset, Functor&& f, Args&&... args)
{
f(cellset, std::forward<Args>(args)...);
}
/// CastAndCall if the condition is true.
template <typename... Args>
void ConditionalCastAndCall(std::true_type, Args&&... args)

@ -27,29 +27,8 @@ namespace cont
class VTKM_CONT_EXPORT CellSet
{
public:
VTKM_CONT
CellSet(const std::string& name)
: Name(name)
{
}
VTKM_CONT
CellSet(const vtkm::cont::CellSet& src)
: Name(src.Name)
{
}
VTKM_CONT
CellSet& operator=(const vtkm::cont::CellSet& src)
{
this->Name = src.Name;
return *this;
}
virtual ~CellSet();
std::string GetName() const { return this->Name; }
virtual vtkm::Id GetNumberOfCells() const = 0;
virtual vtkm::Id GetNumberOfFaces() const = 0;
@ -68,9 +47,6 @@ public:
virtual void PrintSummary(std::ostream&) const = 0;
virtual void ReleaseResourcesExecution() = 0;
protected:
std::string Name;
};
namespace internal

@ -98,7 +98,7 @@ public:
typename VisitCellsWithPointsConnectivityType::ConnectivityArrayType;
using IndexOffsetArrayType = typename VisitCellsWithPointsConnectivityType::IndexOffsetArrayType;
VTKM_CONT CellSetExplicit(const std::string& name = std::string());
VTKM_CONT CellSetExplicit();
VTKM_CONT CellSetExplicit(const Thisclass& src);
VTKM_CONT CellSetExplicit(Thisclass&& src) noexcept;
@ -377,7 +377,6 @@ private:
public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs)
{
vtkmdiy::save(bb, cs.GetName());
vtkmdiy::save(bb, cs.GetNumberOfPoints());
vtkmdiy::save(
bb, cs.GetShapesArray(vtkm::TopologyElementTagCell{}, vtkm::TopologyElementTagPoint{}));
@ -391,8 +390,6 @@ public:
static VTKM_CONT void load(BinaryBuffer& bb, Type& cs)
{
std::string name;
vtkmdiy::load(bb, name);
vtkm::Id numberOfPoints = 0;
vtkmdiy::load(bb, numberOfPoints);
vtkm::cont::ArrayHandle<vtkm::UInt8, ShapeST> shapes;
@ -404,7 +401,7 @@ public:
vtkm::cont::ArrayHandle<vtkm::Id, OffsetST> offsets;
vtkmdiy::load(bb, offsets);
cs = Type(name);
cs = Type{};
cs.Fill(numberOfPoints, shapes, counts, connectivity, offsets);
}
};

@ -25,8 +25,8 @@ template <typename ShapeStorageTag,
VTKM_CONT CellSetExplicit<ShapeStorageTag,
NumIndicesStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::CellSetExplicit(const std::string& name)
: CellSet(name)
OffsetsStorageTag>::CellSetExplicit()
: CellSet()
, Data(std::make_shared<Internals>())
{
}
@ -103,7 +103,7 @@ void CellSetExplicit<ShapeStorageTag,
ConnectivityStorageTag,
OffsetsStorageTag>::PrintSummary(std::ostream& out) const
{
out << " ExplicitCellSet: " << this->Name << std::endl;
out << " ExplicitCellSet: " << std::endl;
out << " VisitCellsWithPoints: " << std::endl;
this->Data->VisitCellsWithPoints.PrintSummary(out);
out << " VisitPointsWithCells: " << std::endl;

@ -19,8 +19,8 @@ namespace vtkm
namespace cont
{
CellSetExtrude::CellSetExtrude(const std::string& name)
: vtkm::cont::CellSet(name)
CellSetExtrude::CellSetExtrude()
: vtkm::cont::CellSet()
, IsPeriodic(false)
, NumberOfPointsPerPlane(0)
, NumberOfCellsPerPlane(0)
@ -33,9 +33,8 @@ CellSetExtrude::CellSetExtrude(const vtkm::cont::ArrayHandle<vtkm::Int32>& conn,
vtkm::Int32 numberOfPointsPerPlane,
vtkm::Int32 numberOfPlanes,
const vtkm::cont::ArrayHandle<vtkm::Int32>& nextNode,
bool periodic,
const std::string& name)
: vtkm::cont::CellSet(name)
bool periodic)
: vtkm::cont::CellSet()
, IsPeriodic(periodic)
, NumberOfPointsPerPlane(numberOfPointsPerPlane)
, NumberOfCellsPerPlane(
@ -47,6 +46,81 @@ CellSetExtrude::CellSetExtrude(const vtkm::cont::ArrayHandle<vtkm::Int32>& conn,
{
}
CellSetExtrude::CellSetExtrude(const CellSetExtrude& src)
: CellSet(src)
, IsPeriodic(src.IsPeriodic)
, NumberOfPointsPerPlane(src.NumberOfPointsPerPlane)
, NumberOfCellsPerPlane(src.NumberOfCellsPerPlane)
, NumberOfPlanes(src.NumberOfPlanes)
, Connectivity(src.Connectivity)
, NextNode(src.NextNode)
, ReverseConnectivityBuilt(src.ReverseConnectivityBuilt)
, RConnectivity(src.RConnectivity)
, ROffsets(src.ROffsets)
, RCounts(src.RCounts)
, PrevNode(src.PrevNode)
{
}
CellSetExtrude::CellSetExtrude(CellSetExtrude&& src) noexcept
: CellSet(std::forward<CellSet>(src)),
IsPeriodic(src.IsPeriodic),
NumberOfPointsPerPlane(src.NumberOfPointsPerPlane),
NumberOfCellsPerPlane(src.NumberOfCellsPerPlane),
NumberOfPlanes(src.NumberOfPlanes),
Connectivity(std::move(src.Connectivity)),
NextNode(std::move(src.NextNode)),
ReverseConnectivityBuilt(src.ReverseConnectivityBuilt),
RConnectivity(std::move(src.RConnectivity)),
ROffsets(std::move(src.ROffsets)),
RCounts(std::move(src.RCounts)),
PrevNode(std::move(src.PrevNode))
{
}
CellSetExtrude& CellSetExtrude::operator=(const CellSetExtrude& src)
{
this->CellSet::operator=(src);
this->IsPeriodic = src.IsPeriodic;
this->NumberOfPointsPerPlane = src.NumberOfPointsPerPlane;
this->NumberOfCellsPerPlane = src.NumberOfCellsPerPlane;
this->NumberOfPlanes = src.NumberOfPlanes;
this->Connectivity = src.Connectivity;
this->NextNode = src.NextNode;
this->ReverseConnectivityBuilt = src.ReverseConnectivityBuilt;
this->RConnectivity = src.RConnectivity;
this->ROffsets = src.ROffsets;
this->RCounts = src.RCounts;
this->PrevNode = src.PrevNode;
return *this;
}
CellSetExtrude& CellSetExtrude::operator=(CellSetExtrude&& src) noexcept
{
this->CellSet::operator=(std::forward<CellSet>(src));
this->IsPeriodic = src.IsPeriodic;
this->NumberOfPointsPerPlane = src.NumberOfPointsPerPlane;
this->NumberOfCellsPerPlane = src.NumberOfCellsPerPlane;
this->NumberOfPlanes = src.NumberOfPlanes;
this->Connectivity = std::move(src.Connectivity);
this->NextNode = std::move(src.NextNode);
this->ReverseConnectivityBuilt = src.ReverseConnectivityBuilt;
this->RConnectivity = std::move(src.RConnectivity);
this->ROffsets = std::move(src.ROffsets);
this->RCounts = std::move(src.RCounts);
this->PrevNode = std::move(src.PrevNode);
return *this;
}
CellSetExtrude::~CellSetExtrude()
{
}
vtkm::Int32 CellSetExtrude::GetNumberOfPlanes() const
{
return this->NumberOfPlanes;
@ -167,7 +241,7 @@ vtkm::Id2 CellSetExtrude::GetSchedulingRange(vtkm::TopologyElementTagPoint) cons
void CellSetExtrude::PrintSummary(std::ostream& out) const
{
out << " vtkmCellSetSingleType: " << this->Name << std::endl;
out << " vtkmCellSetSingleType: " << std::endl;
out << " NumberOfCellsPerPlane: " << this->NumberOfCellsPerPlane << std::endl;
out << " NumberOfPointsPerPlane: " << this->NumberOfPointsPerPlane << std::endl;
out << " NumberOfPlanes: " << this->NumberOfPlanes << std::endl;

@ -29,14 +29,21 @@ namespace cont
class VTKM_CONT_EXPORT CellSetExtrude : public CellSet
{
public:
VTKM_CONT CellSetExtrude(const std::string& name = "extrude");
VTKM_CONT CellSetExtrude();
VTKM_CONT CellSetExtrude(const vtkm::cont::ArrayHandle<vtkm::Int32>& conn,
vtkm::Int32 numberOfPointsPerPlane,
vtkm::Int32 numberOfPlanes,
const vtkm::cont::ArrayHandle<vtkm::Int32>& nextNode,
bool periodic,
const std::string& name = "extrude");
bool periodic);
VTKM_CONT CellSetExtrude(const CellSetExtrude& src);
VTKM_CONT CellSetExtrude(CellSetExtrude&& src) noexcept;
VTKM_CONT CellSetExtrude& operator=(const CellSetExtrude& src);
VTKM_CONT CellSetExtrude& operator=(CellSetExtrude&& src) noexcept;
virtual ~CellSetExtrude();
vtkm::Int32 GetNumberOfPlanes() const;
@ -126,11 +133,10 @@ template <typename T>
CellSetExtrude make_CellSetExtrude(const vtkm::cont::ArrayHandle<vtkm::Int32>& conn,
const vtkm::cont::ArrayHandleExtrudeCoords<T>& coords,
const vtkm::cont::ArrayHandle<vtkm::Int32>& nextNode,
bool periodic = true,
const std::string name = "extrude")
bool periodic = true)
{
return CellSetExtrude{
conn, coords.GetNumberOfPointsPerPlane(), coords.GetNumberOfPlanes(), nextNode, periodic, name
conn, coords.GetNumberOfPointsPerPlane(), coords.GetNumberOfPlanes(), nextNode, periodic
};
}
@ -138,15 +144,13 @@ template <typename T>
CellSetExtrude make_CellSetExtrude(const std::vector<vtkm::Int32>& conn,
const vtkm::cont::ArrayHandleExtrudeCoords<T>& coords,
const std::vector<vtkm::Int32>& nextNode,
bool periodic = true,
const std::string name = "extrude")
bool periodic = true)
{
return CellSetExtrude{ vtkm::cont::make_ArrayHandle(conn),
static_cast<vtkm::Int32>(coords.GetNumberOfPointsPerPlane()),
coords.GetNumberOfPlanes(),
vtkm::cont::make_ArrayHandle(nextNode),
periodic,
name };
periodic };
}
}
} // vtkm::cont
@ -183,7 +187,6 @@ private:
public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs)
{
vtkmdiy::save(bb, cs.GetName());
vtkmdiy::save(bb, cs.GetNumberOfPointsPerPlane());
vtkmdiy::save(bb, cs.GetNumberOfPlanes());
vtkmdiy::save(bb, cs.GetIsPeriodic());
@ -193,21 +196,19 @@ public:
static VTKM_CONT void load(BinaryBuffer& bb, Type& cs)
{
std::string name;
vtkm::Int32 numberOfPointsPerPlane;
vtkm::Int32 numberOfPlanes;
bool isPeriodic;
vtkm::cont::ArrayHandle<vtkm::Int32> conn;
vtkm::cont::ArrayHandle<vtkm::Int32> nextNode;
vtkmdiy::load(bb, name);
vtkmdiy::load(bb, numberOfPointsPerPlane);
vtkmdiy::load(bb, numberOfPlanes);
vtkmdiy::load(bb, isPeriodic);
vtkmdiy::load(bb, conn);
vtkmdiy::load(bb, nextNode);
cs = Type{ conn, numberOfPointsPerPlane, numberOfPlanes, nextNode, isPeriodic, name };
cs = Type{ conn, numberOfPointsPerPlane, numberOfPlanes, nextNode, isPeriodic };
}
};

@ -243,17 +243,16 @@ public:
VTKM_CONT
CellSetPermutation(const PermutationArrayHandleType& validCellIds,
const OriginalCellSetType& cellset,
const std::string& name = std::string())
: CellSet(name)
const OriginalCellSetType& cellset)
: CellSet()
, ValidCellIds(validCellIds)
, FullCellSet(cellset)
{
}
VTKM_CONT
CellSetPermutation(const std::string& name = std::string())
: CellSet(name)
CellSetPermutation()
: CellSet()
, ValidCellIds()
, FullCellSet()
{
@ -446,17 +445,15 @@ private:
public:
VTKM_CONT
CellSetPermutation(const PermutationArrayHandleType2& validCellIds,
const CellSetPermutation<CellSetType, PermutationArrayHandleType1>& cellset,
const std::string& name = std::string())
const CellSetPermutation<CellSetType, PermutationArrayHandleType1>& cellset)
: Superclass(vtkm::cont::make_ArrayHandlePermutation(validCellIds, cellset.GetValidCellIds()),
cellset.GetFullCellSet(),
name)
cellset.GetFullCellSet())
{
}
VTKM_CONT
CellSetPermutation(const std::string& name = std::string())
: Superclass(name)
CellSetPermutation()
: Superclass()
{
}
@ -471,19 +468,6 @@ public:
std::shared_ptr<CellSet> NewInstance() const { return std::make_shared<CellSetPermutation>(); }
};
template <typename OriginalCellSet, typename PermutationArrayHandleType>
vtkm::cont::CellSetPermutation<OriginalCellSet, PermutationArrayHandleType> make_CellSetPermutation(
const PermutationArrayHandleType& cellIndexMap,
const OriginalCellSet& cellSet,
const std::string& name)
{
VTKM_IS_CELL_SET(OriginalCellSet);
VTKM_IS_ARRAY_HANDLE(PermutationArrayHandleType);
return vtkm::cont::CellSetPermutation<OriginalCellSet, PermutationArrayHandleType>(
cellIndexMap, cellSet, name);
}
template <typename OriginalCellSet, typename PermutationArrayHandleType>
vtkm::cont::CellSetPermutation<OriginalCellSet, PermutationArrayHandleType> make_CellSetPermutation(
const PermutationArrayHandleType& cellIndexMap,
@ -492,7 +476,8 @@ vtkm::cont::CellSetPermutation<OriginalCellSet, PermutationArrayHandleType> make
VTKM_IS_CELL_SET(OriginalCellSet);
VTKM_IS_ARRAY_HANDLE(PermutationArrayHandleType);
return vtkm::cont::make_CellSetPermutation(cellIndexMap, cellSet, cellSet.GetName());
return vtkm::cont::CellSetPermutation<OriginalCellSet, PermutationArrayHandleType>(cellIndexMap,
cellSet);
}
}
} // namespace vtkm::cont
@ -529,21 +514,18 @@ private:
public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs)
{
vtkmdiy::save(bb, cs.GetName());
vtkmdiy::save(bb, cs.GetFullCellSet());
vtkmdiy::save(bb, cs.GetValidCellIds());
}
static VTKM_CONT void load(BinaryBuffer& bb, Type& cs)
{
std::string name;
vtkmdiy::load(bb, name);
CSType fullCS;
vtkmdiy::load(bb, fullCS);
AHValidCellIds validCellIds;
vtkmdiy::load(bb, validCellIds);
cs = make_CellSetPermutation(validCellIds, fullCS, name);
cs = make_CellSetPermutation(validCellIds, fullCS);
}
};

@ -46,8 +46,8 @@ class VTKM_ALWAYS_EXPORT CellSetSingleType
public:
VTKM_CONT
CellSetSingleType(const std::string& name = std::string())
: Superclass(name)
CellSetSingleType()
: Superclass()
, ExpectedNumberOfCellsAdded(-1)
, CellShapeAsId(CellShapeTagEmpty::Id)
, NumberOfPointsPerCell(0)
@ -63,6 +63,15 @@ public:
{
}
VTKM_CONT
CellSetSingleType(Thisclass&& src) noexcept : Superclass(std::forward<Superclass>(src)),
ExpectedNumberOfCellsAdded(-1),
CellShapeAsId(src.CellShapeAsId),
NumberOfPointsPerCell(src.NumberOfPointsPerCell)
{
}
VTKM_CONT
Thisclass& operator=(const Thisclass& src)
{
@ -72,6 +81,15 @@ public:
return *this;
}
VTKM_CONT
Thisclass& operator=(Thisclass&& src) noexcept
{
this->Superclass::operator=(std::forward<Superclass>(src));
this->CellShapeAsId = src.CellShapeAsId;
this->NumberOfPointsPerCell = src.NumberOfPointsPerCell;
return *this;
}
virtual ~CellSetSingleType() {}
/// First method to add cells -- one at a time.
@ -224,7 +242,7 @@ public:
virtual void PrintSummary(std::ostream& out) const override
{
out << " CellSetSingleType: " << this->Name << " Type " << this->CellShapeAsId << std::endl;
out << " CellSetSingleType ShapeType " << this->CellShapeAsId << std::endl;
out << " VisitCellsWithPoints: " << std::endl;
this->Data->VisitCellsWithPoints.PrintSummary(out);
out << " VisitPointsWithCells: " << std::endl;
@ -304,7 +322,6 @@ private:
public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs)
{
vtkmdiy::save(bb, cs.GetName());
vtkmdiy::save(bb, cs.GetNumberOfPoints());
vtkmdiy::save(bb, cs.GetCellShape(0));
vtkmdiy::save(bb, cs.GetNumberOfPointsInCell(0));
@ -314,8 +331,6 @@ public:
static VTKM_CONT void load(BinaryBuffer& bb, Type& cs)
{
std::string name;
vtkmdiy::load(bb, name);
vtkm::Id numberOfPoints = 0;
vtkmdiy::load(bb, numberOfPoints);
vtkm::UInt8 shape;
@ -325,7 +340,7 @@ public:
vtkm::cont::ArrayHandle<vtkm::Id, ConnectivityST> connectivity;
vtkmdiy::load(bb, connectivity);
cs = Type(name);
cs = Type{};
cs.Fill(numberOfPoints, shape, count, connectivity);
}
};

@ -35,18 +35,6 @@ public:
using SchedulingRangeType = typename InternalsType::SchedulingRangeType;
CellSetStructured(const std::string& name = std::string())
: CellSet(name)
, Structure()
{
}
CellSetStructured(const Thisclass& src);
CellSetStructured(Thisclass&& src) noexcept;
Thisclass& operator=(const Thisclass& src);
Thisclass& operator=(Thisclass&& src) noexcept;
vtkm::Id GetNumberOfCells() const override { return this->Structure.GetNumberOfCells(); }
vtkm::Id GetNumberOfPoints() const override { return this->Structure.GetNumberOfPoints(); }
@ -174,20 +162,17 @@ private:
public:
static VTKM_CONT void save(BinaryBuffer& bb, const Type& cs)
{
vtkmdiy::save(bb, cs.GetName());
vtkmdiy::save(bb, cs.GetPointDimensions());
vtkmdiy::save(bb, cs.GetGlobalPointIndexStart());
}
static VTKM_CONT void load(BinaryBuffer& bb, Type& cs)
{
std::string name;
vtkmdiy::load(bb, name);
typename Type::SchedulingRangeType dims, start;
vtkmdiy::load(bb, dims);
vtkmdiy::load(bb, start);
cs = Type(name);
cs = Type{};
cs.SetPointDimensions(dims);
cs.SetGlobalPointIndexStart(start);
}

@ -15,38 +15,6 @@ namespace vtkm
namespace cont
{
template <vtkm::IdComponent DIMENSION>
CellSetStructured<DIMENSION>::CellSetStructured(const CellSetStructured<DIMENSION>& src)
: CellSet(src)
, Structure(src.Structure)
{
}
template <vtkm::IdComponent DIMENSION>
CellSetStructured<DIMENSION>::CellSetStructured(CellSetStructured<DIMENSION>&& src) noexcept
: CellSet(std::forward<CellSet>(src)),
Structure(std::move(src.Structure))
{
}
template <vtkm::IdComponent DIMENSION>
CellSetStructured<DIMENSION>& CellSetStructured<DIMENSION>::operator=(
const CellSetStructured<DIMENSION>& src)
{
this->CellSet::operator=(src);
this->Structure = src.Structure;
return *this;
}
template <vtkm::IdComponent DIMENSION>
CellSetStructured<DIMENSION>& CellSetStructured<DIMENSION>::operator=(
CellSetStructured<DIMENSION>&& src) noexcept
{
this->CellSet::operator=(std::forward<CellSet>(src));
this->Structure = std::move(src.Structure);
return *this;
}
template <vtkm::IdComponent DIMENSION>
template <typename TopologyElement>
typename CellSetStructured<DIMENSION>::SchedulingRangeType
@ -73,7 +41,7 @@ typename CellSetStructured<DIMENSION>::template ExecutionTypes<DeviceAdapter,
template <vtkm::IdComponent DIMENSION>
void CellSetStructured<DIMENSION>::PrintSummary(std::ostream& out) const
{
out << " StructuredCellSet: " << this->GetName() << std::endl;
out << " StructuredCellSet: " << std::endl;
this->Structure.PrintSummary(out);
}
}

@ -18,13 +18,27 @@ void DataSet::Clear()
{
this->CoordSystems.clear();
this->Fields.clear();
this->CellSets.clear();
this->CellSet = this->CellSet.NewInstance();
}
vtkm::Id DataSet::GetNumberOfCells() const
{
return this->CellSet.GetNumberOfCells();
}
vtkm::Id DataSet::GetNumberOfPoints() const
{
if (this->CoordSystems.empty())
{
return 0;
}
return this->CoordSystems[0].GetNumberOfPoints();
}
void DataSet::CopyStructure(const vtkm::cont::DataSet& source)
{
this->CoordSystems = source.CoordSystems;
this->CellSets = source.CellSets;
this->CellSet = source.CellSet;
}
const vtkm::cont::Field& DataSet::GetField(vtkm::Id index) const
@ -33,6 +47,12 @@ const vtkm::cont::Field& DataSet::GetField(vtkm::Id index) const
return this->Fields[static_cast<std::size_t>(index)];
}
vtkm::cont::Field& DataSet::GetField(vtkm::Id index)
{
VTKM_ASSERT((index >= 0) && (index < this->GetNumberOfFields()));
return this->Fields[static_cast<std::size_t>(index)];
}
vtkm::Id DataSet::GetFieldIndex(const std::string& name, vtkm::cont::Field::Association assoc) const
{
bool found;
@ -53,6 +73,12 @@ const vtkm::cont::CoordinateSystem& DataSet::GetCoordinateSystem(vtkm::Id index)
return this->CoordSystems[static_cast<std::size_t>(index)];
}
vtkm::cont::CoordinateSystem& DataSet::GetCoordinateSystem(vtkm::Id index)
{
VTKM_ASSERT((index >= 0) && (index < this->GetNumberOfCoordinateSystems()));
return this->CoordSystems[static_cast<std::size_t>(index)];
}
vtkm::Id DataSet::GetCoordinateSystemIndex(const std::string& name) const
{
vtkm::Id index = -1;
@ -83,39 +109,20 @@ const vtkm::cont::CoordinateSystem& DataSet::GetCoordinateSystem(const std::stri
return this->GetCoordinateSystem(index);
}
const vtkm::cont::DynamicCellSet& DataSet::GetCellSet(vtkm::Id index) const
vtkm::cont::CoordinateSystem& DataSet::GetCoordinateSystem(const std::string& name)
{
VTKM_ASSERT((index >= 0) && (index < this->GetNumberOfCellSets()));
return this->CellSets[static_cast<std::size_t>(index)];
}
vtkm::Id DataSet::GetCellSetIndex(const std::string& name) const
{
vtkm::Id index = -1;
for (auto i = this->CellSets.begin(); i != this->CellSets.end(); ++i)
{
if (i->GetName() == name)
{
index = static_cast<vtkm::Id>(std::distance(this->CellSets.begin(), i));
break;
}
}
return index;
}
const vtkm::cont::DynamicCellSet& DataSet::GetCellSet(const std::string& name) const
{
vtkm::Id index = this->GetCellSetIndex(name);
vtkm::Id index = this->GetCoordinateSystemIndex(name);
if (index < 0)
{
std::string error_message("No cell set with the name " + name + " valid names are: \n");
for (const auto& cs : this->CellSets)
std::string error_message("No coordinate system with the name " + name +
" valid names are: \n");
for (const auto& cs : this->CoordSystems)
{
error_message += cs.GetName() + "\n";
}
throw vtkm::cont::ErrorBadValue(error_message);
}
return this->GetCellSet(index);
return this->GetCoordinateSystem(index);
}
void DataSet::PrintSummary(std::ostream& out) const
@ -127,17 +134,16 @@ void DataSet::PrintSummary(std::ostream& out) const
this->CoordSystems[index].PrintSummary(out);
}
out << " CellSets[" << this->GetNumberOfCellSets() << "]\n";
for (vtkm::Id index = 0; index < this->GetNumberOfCellSets(); index++)
{
this->GetCellSet(index).PrintSummary(out);
}
out << " CellSet \n";
this->GetCellSet().PrintSummary(out);
out << " Fields[" << this->GetNumberOfFields() << "]\n";
for (vtkm::Id index = 0; index < this->GetNumberOfFields(); index++)
{
this->GetField(index).PrintSummary(out);
}
out.flush();
}
vtkm::Id DataSet::FindFieldIndex(const std::string& name,

@ -30,11 +30,23 @@ class VTKM_CONT_EXPORT DataSet
public:
VTKM_CONT void Clear();
/// Get the number of cells contained in this DataSet
VTKM_CONT vtkm::Id GetNumberOfCells() const;
/// Get the number of points contained in this DataSet
///
/// Note: All coordinate systems for a DataSet are expected
/// to have the same number of points.
VTKM_CONT vtkm::Id GetNumberOfPoints() const;
VTKM_CONT void AddField(const Field& field) { this->Fields.push_back(field); }
VTKM_CONT
const vtkm::cont::Field& GetField(vtkm::Id index) const;
VTKM_CONT
vtkm::cont::Field& GetField(vtkm::Id index);
VTKM_CONT
bool HasField(const std::string& name,
vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::ANY) const
@ -70,6 +82,7 @@ public:
/// Returns the first field that matches the provided name and association
/// Will throw an exception if no match is found
//@{
VTKM_CONT
const vtkm::cont::Field& GetField(
const std::string& name,
@ -78,22 +91,47 @@ public:
return this->GetField(this->GetFieldIndex(name, assoc));
}
VTKM_CONT
vtkm::cont::Field& GetField(
const std::string& name,
vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::ANY)
{
return this->GetField(this->GetFieldIndex(name, assoc));
}
//@}
/// Returns the first cell field that matches the provided name.
/// Will throw an exception if no match is found
//@{
VTKM_CONT
const vtkm::cont::Field& GetCellField(const std::string& name) const
{
return this->GetField(name, vtkm::cont::Field::Association::CELL_SET);
}
VTKM_CONT
vtkm::cont::Field& GetCellField(const std::string& name)
{
return this->GetField(name, vtkm::cont::Field::Association::CELL_SET);
}
//@}
/// Returns the first point field that matches the provided name.
/// Will throw an exception if no match is found
//@{
VTKM_CONT
const vtkm::cont::Field& GetPointField(const std::string& name) const
{
return this->GetField(name, vtkm::cont::Field::Association::POINTS);
}
VTKM_CONT
vtkm::cont::Field& GetPointField(const std::string& name)
{
return this->GetField(name, vtkm::cont::Field::Association::POINTS);
}
//@}
VTKM_CONT
void AddCoordinateSystem(const vtkm::cont::CoordinateSystem& cs)
{
@ -109,6 +147,9 @@ public:
VTKM_CONT
const vtkm::cont::CoordinateSystem& GetCoordinateSystem(vtkm::Id index = 0) const;
VTKM_CONT
vtkm::cont::CoordinateSystem& GetCoordinateSystem(vtkm::Id index = 0);
/// Returns the index for the first CoordinateSystem whose
/// name matches the provided string.
/// Will return -1 if no match is found
@ -117,44 +158,29 @@ public:
/// Returns the first CoordinateSystem that matches the provided name.
/// Will throw an exception if no match is found
//@{
VTKM_CONT
const vtkm::cont::CoordinateSystem& GetCoordinateSystem(const std::string& name) const;
VTKM_CONT
void AddCellSet(const vtkm::cont::DynamicCellSet& cellSet) { this->CellSets.push_back(cellSet); }
vtkm::cont::CoordinateSystem& GetCoordinateSystem(const std::string& name);
//@}
VTKM_CONT
void SetCellSet(const vtkm::cont::DynamicCellSet& cellSet) { this->CellSet = cellSet; }
template <typename CellSetType>
VTKM_CONT void AddCellSet(const CellSetType& cellSet)
VTKM_CONT void SetCellSet(const CellSetType& cellSet)
{
VTKM_IS_CELL_SET(CellSetType);
this->CellSets.push_back(vtkm::cont::DynamicCellSet(cellSet));
this->CellSet = vtkm::cont::DynamicCellSet(cellSet);
}
VTKM_CONT
bool HasCellSet(const std::string& name) const { return this->GetCellSetIndex(name) >= 0; }
const vtkm::cont::DynamicCellSet& GetCellSet() const { return this->CellSet; }
VTKM_CONT
const vtkm::cont::DynamicCellSet& GetCellSet(vtkm::Id index = 0) const;
/// Returns the index for the first cell set whose
/// name matches the provided string.
/// Will return -1 if no match is found
VTKM_CONT
vtkm::Id GetCellSetIndex(const std::string& name) const;
/// Returns the first DynamicCellSet that matches the provided name.
/// Will throw an exception if no match is found
VTKM_CONT
const vtkm::cont::DynamicCellSet& GetCellSet(const std::string& name) const;
VTKM_CONT
vtkm::IdComponent GetNumberOfCellSets() const
{
return static_cast<vtkm::IdComponent>(this->CellSets.size());
}
vtkm::cont::DynamicCellSet& GetCellSet() { return this->CellSet; }
VTKM_CONT
vtkm::IdComponent GetNumberOfFields() const
@ -168,7 +194,7 @@ public:
return static_cast<vtkm::IdComponent>(this->CoordSystems.size());
}
/// Copies the structure i.e. coordinates systems and cellsets from the source
/// Copies the structure i.e. coordinates systems and cellset from the source
/// dataset. The fields are left unchanged.
VTKM_CONT
void CopyStructure(const vtkm::cont::DataSet& source);
@ -179,7 +205,7 @@ public:
private:
std::vector<vtkm::cont::CoordinateSystem> CoordSystems;
std::vector<vtkm::cont::Field> Fields;
std::vector<vtkm::cont::DynamicCellSet> CellSets;
vtkm::cont::DynamicCellSet CellSet;
VTKM_CONT
vtkm::Id FindFieldIndex(const std::string& name,
@ -234,12 +260,7 @@ public:
vtkmdiy::save(bb, dataset.GetCoordinateSystem(i));
}
vtkm::IdComponent numberOfCellSets = dataset.GetNumberOfCellSets();
vtkmdiy::save(bb, numberOfCellSets);
for (vtkm::IdComponent i = 0; i < numberOfCellSets; ++i)
{
vtkmdiy::save(bb, dataset.GetCellSet(i).ResetCellSetList(CellSetTypesList{}));
}
vtkmdiy::save(bb, dataset.GetCellSet().ResetCellSetList(CellSetTypesList{}));
vtkm::IdComponent numberOfFields = dataset.GetNumberOfFields();
vtkmdiy::save(bb, numberOfFields);
@ -263,14 +284,9 @@ public:
dataset.AddCoordinateSystem(coords);
}
vtkm::IdComponent numberOfCellSets = 0;
vtkmdiy::load(bb, numberOfCellSets);
for (vtkm::IdComponent i = 0; i < numberOfCellSets; ++i)
{
vtkm::cont::DynamicCellSetBase<CellSetTypesList> cells;
vtkmdiy::load(bb, cells);
dataset.AddCellSet(vtkm::cont::DynamicCellSet(cells));
}
vtkm::cont::DynamicCellSetBase<CellSetTypesList> cells;
vtkmdiy::load(bb, cells);
dataset.SetCellSet(vtkm::cont::DynamicCellSet(cells));
vtkm::IdComponent numberOfFields = 0;
vtkmdiy::load(bb, numberOfFields);

@ -22,11 +22,9 @@ DataSetBuilderExplicitIterative::DataSetBuilderExplicitIterative()
VTKM_CONT
void DataSetBuilderExplicitIterative::Begin(const std::string& coordName,
const std::string& cellName)
void DataSetBuilderExplicitIterative::Begin(const std::string& coordName)
{
this->coordNm = coordName;
this->cellNm = cellName;
this->points.resize(0);
this->shapes.resize(0);
this->numIdx.resize(0);
@ -38,11 +36,11 @@ VTKM_CONT
vtkm::cont::DataSet DataSetBuilderExplicitIterative::Create()
{
DataSetBuilderExplicit dsb;
return dsb.Create(points, shapes, numIdx, connectivity, coordNm, cellNm);
return dsb.Create(points, shapes, numIdx, connectivity, coordNm);
}
VTKM_CONT
vtkm::Id DataSetBuilderExplicitIterative::AddPoint(const vtkm::Vec3f_32& pt)
vtkm::Id DataSetBuilderExplicitIterative::AddPoint(const vtkm::Vec3f& pt)
{
points.push_back(pt);
vtkm::Id id = static_cast<vtkm::Id>(points.size());
@ -51,9 +49,9 @@ vtkm::Id DataSetBuilderExplicitIterative::AddPoint(const vtkm::Vec3f_32& pt)
}
VTKM_CONT
vtkm::Id DataSetBuilderExplicitIterative::AddPoint(const vtkm::Float32& x,
const vtkm::Float32& y,
const vtkm::Float32& z)
vtkm::Id DataSetBuilderExplicitIterative::AddPoint(const vtkm::FloatDefault& x,
const vtkm::FloatDefault& y,
const vtkm::FloatDefault& z)
{
points.push_back(vtkm::make_Vec(x, y, z));
vtkm::Id id = static_cast<vtkm::Id>(points.size());

@ -45,12 +45,11 @@ public:
const std::vector<vtkm::UInt8>& shapes,
const std::vector<vtkm::IdComponent>& numIndices,
const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords",
const std::string& cellNm = "cells")
const std::string& coordsNm = "coords")
{
std::vector<T> yVals(xVals.size(), 0), zVals(xVals.size(), 0);
return DataSetBuilderExplicit::Create(
xVals, yVals, zVals, shapes, numIndices, connectivity, coordsNm, cellNm);
xVals, yVals, zVals, shapes, numIndices, connectivity, coordsNm);
}
template <typename T>
@ -59,12 +58,11 @@ public:
const std::vector<vtkm::UInt8>& shapes,
const std::vector<vtkm::IdComponent>& numIndices,
const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords",
const std::string& cellNm = "cells")
const std::string& coordsNm = "coords")
{
std::vector<T> zVals(xVals.size(), 0);
return DataSetBuilderExplicit::Create(
xVals, yVals, zVals, shapes, numIndices, connectivity, coordsNm, cellNm);
xVals, yVals, zVals, shapes, numIndices, connectivity, coordsNm);
}
template <typename T>
@ -74,8 +72,7 @@ public:
const std::vector<vtkm::UInt8>& shapes,
const std::vector<vtkm::IdComponent>& numIndices,
const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords",
const std::string& cellNm = "cells");
const std::string& coordsNm = "coords");
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(
@ -85,11 +82,10 @@ public:
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords",
const std::string& cellNm = "cells")
const std::string& coordsNm = "coords")
{
return DataSetBuilderExplicit::BuildDataSet(
xVals, yVals, zVals, shapes, numIndices, connectivity, coordsNm, cellNm);
xVals, yVals, zVals, shapes, numIndices, connectivity, coordsNm);
}
template <typename T>
@ -97,8 +93,7 @@ public:
const std::vector<vtkm::UInt8>& shapes,
const std::vector<vtkm::IdComponent>& numIndices,
const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords",
const std::string& cellNm = "cells");
const std::string& coordsNm = "coords");
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(
@ -106,11 +101,9 @@ public:
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords",
const std::string& cellNm = "cells")
const std::string& coordsNm = "coords")
{
return DataSetBuilderExplicit::BuildDataSet(
coords, shapes, numIndices, connectivity, coordsNm, cellNm);
return DataSetBuilderExplicit::BuildDataSet(coords, shapes, numIndices, connectivity, coordsNm);
}
template <typename T, typename CellShapeTag>
@ -118,8 +111,7 @@ public:
CellShapeTag tag,
vtkm::IdComponent numberOfPointsPerCell,
const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords",
const std::string& cellNm = "cells");
const std::string& coordsNm = "coords");
template <typename T, typename CellShapeTag>
VTKM_CONT static vtkm::cont::DataSet Create(
@ -127,11 +119,10 @@ public:
CellShapeTag tag,
vtkm::IdComponent numberOfPointsPerCell,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm = "coords",
const std::string& cellNm = "cells")
const std::string& coordsNm = "coords")
{
return DataSetBuilderExplicit::BuildDataSet(
coords, tag, numberOfPointsPerCell, connectivity, coordsNm, cellNm);
coords, tag, numberOfPointsPerCell, connectivity, coordsNm);
}
private:
@ -143,8 +134,7 @@ private:
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm);
const std::string& coordsNm);
template <typename T>
VTKM_CONT static vtkm::cont::DataSet BuildDataSet(
@ -152,8 +142,7 @@ private:
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm);
const std::string& coordsNm);
template <typename T, typename CellShapeTag>
VTKM_CONT static vtkm::cont::DataSet BuildDataSet(
@ -161,8 +150,7 @@ private:
CellShapeTag tag,
vtkm::IdComponent numberOfPointsPerCell,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm);
const std::string& coordsNm);
};
template <typename T>
@ -173,8 +161,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
const std::vector<vtkm::UInt8>& shapes,
const std::vector<vtkm::IdComponent>& numIndices,
const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm)
const std::string& coordsNm)
{
VTKM_ASSERT(xVals.size() == yVals.size() && yVals.size() == zVals.size() && xVals.size() > 0);
@ -190,7 +177,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
DataSetBuilderExplicit::CopyInto(numIndices, Nc);
DataSetBuilderExplicit::CopyInto(connectivity, Cc);
return DataSetBuilderExplicit::BuildDataSet(Xc, Yc, Zc, Sc, Nc, Cc, coordsNm, cellNm);
return DataSetBuilderExplicit::BuildDataSet(Xc, Yc, Zc, Sc, Nc, Cc, coordsNm);
}
template <typename T>
@ -201,8 +188,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet(
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm)
const std::string& coordsNm)
{
VTKM_ASSERT(X.GetNumberOfValues() == Y.GetNumberOfValues() &&
Y.GetNumberOfValues() == Z.GetNumberOfValues() && X.GetNumberOfValues() > 0 &&
@ -212,10 +198,10 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet(
dataSet.AddCoordinateSystem(
vtkm::cont::CoordinateSystem(coordsNm, make_ArrayHandleCompositeVector(X, Y, Z)));
vtkm::Id nPts = X.GetNumberOfValues();
vtkm::cont::CellSetExplicit<> cellSet(cellNm);
vtkm::cont::CellSetExplicit<> cellSet;
cellSet.Fill(nPts, shapes, numIndices, connectivity);
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
return dataSet;
}
@ -226,8 +212,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
const std::vector<vtkm::UInt8>& shapes,
const std::vector<vtkm::IdComponent>& numIndices,
const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm)
const std::string& coordsNm)
{
vtkm::cont::ArrayHandle<Vec<T, 3>> coordsArray;
DataSetBuilderExplicit::CopyInto(coords, coordsArray);
@ -239,7 +224,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
DataSetBuilderExplicit::CopyInto(numIndices, Nc);
DataSetBuilderExplicit::CopyInto(connectivity, Cc);
return DataSetBuilderExplicit::Create(coordsArray, Sc, Nc, Cc, coordsNm, cellNm);
return DataSetBuilderExplicit::Create(coordsArray, Sc, Nc, Cc, coordsNm);
}
template <typename T>
@ -248,17 +233,16 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet(
const vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes,
const vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm)
const std::string& coordsNm)
{
vtkm::cont::DataSet dataSet;
dataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem(coordsNm, coords));
vtkm::Id nPts = static_cast<vtkm::Id>(coords.GetNumberOfValues());
vtkm::cont::CellSetExplicit<> cellSet(cellNm);
vtkm::cont::CellSetExplicit<> cellSet;
cellSet.Fill(nPts, shapes, numIndices, connectivity);
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
return dataSet;
}
@ -269,8 +253,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
CellShapeTag tag,
vtkm::IdComponent numberOfPointsPerCell,
const std::vector<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm)
const std::string& coordsNm)
{
vtkm::cont::ArrayHandle<Vec<T, 3>> coordsArray;
DataSetBuilderExplicit::CopyInto(coords, coordsArray);
@ -278,8 +261,7 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::Create(
vtkm::cont::ArrayHandle<vtkm::Id> Cc;
DataSetBuilderExplicit::CopyInto(connectivity, Cc);
return DataSetBuilderExplicit::Create(
coordsArray, tag, numberOfPointsPerCell, Cc, coordsNm, cellNm);
return DataSetBuilderExplicit::Create(coordsArray, tag, numberOfPointsPerCell, Cc, coordsNm);
}
template <typename T, typename CellShapeTag>
@ -288,17 +270,16 @@ inline VTKM_CONT vtkm::cont::DataSet DataSetBuilderExplicit::BuildDataSet(
CellShapeTag tag,
vtkm::IdComponent numberOfPointsPerCell,
const vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
const std::string& coordsNm,
const std::string& cellNm)
const std::string& coordsNm)
{
(void)tag; //C4100 false positive workaround
vtkm::cont::DataSet dataSet;
dataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem(coordsNm, coords));
vtkm::cont::CellSetSingleType<> cellSet(cellNm);
vtkm::cont::CellSetSingleType<> cellSet;
cellSet.Fill(coords.GetNumberOfValues(), tag.Id, numberOfPointsPerCell, connectivity);
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
return dataSet;
}
@ -310,29 +291,32 @@ public:
DataSetBuilderExplicitIterative();
VTKM_CONT
void Begin(const std::string& coordName = "coords", const std::string& cellName = "cells");
void Begin(const std::string& coordName = "coords");
//Define points.
VTKM_CONT
vtkm::cont::DataSet Create();
VTKM_CONT
vtkm::Id AddPoint(const vtkm::Vec3f_32& pt);
vtkm::Id AddPoint(const vtkm::Vec3f& pt);
VTKM_CONT
vtkm::Id AddPoint(const vtkm::Float32& x, const vtkm::Float32& y, const vtkm::Float32& z = 0);
vtkm::Id AddPoint(const vtkm::FloatDefault& x,
const vtkm::FloatDefault& y,
const vtkm::FloatDefault& z = 0);
template <typename T>
VTKM_CONT vtkm::Id AddPoint(const T& x, const T& y, const T& z = 0)
{
return AddPoint(
static_cast<vtkm::Float32>(x), static_cast<vtkm::Float32>(y), static_cast<vtkm::Float32>(z));
return AddPoint(static_cast<vtkm::FloatDefault>(x),
static_cast<vtkm::FloatDefault>(y),
static_cast<vtkm::FloatDefault>(z));
}
template <typename T>
VTKM_CONT vtkm::Id AddPoint(const vtkm::Vec<T, 3>& pt)
{
return AddPoint(static_cast<vtkm::Vec3f_32>(pt));
return AddPoint(static_cast<vtkm::Vec3f>(pt));
}
//Define cells.
@ -349,9 +333,9 @@ public:
void AddCellPoint(vtkm::Id pointIndex);
private:
std::string coordNm, cellNm;
std::string coordNm;
std::vector<vtkm::Vec3f_32> points;
std::vector<vtkm::Vec3f> points;
std::vector<vtkm::UInt8> shapes;
std::vector<vtkm::IdComponent> numIdx;
std::vector<vtkm::Id> connectivity;

@ -50,46 +50,41 @@ public:
//1D grids.
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const std::vector<T>& xvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
std::vector<T> yvals(1, 0), zvals(1, 0);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(vtkm::Id nx,
T* xvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
T yvals = 0, zvals = 0;
return DataSetBuilderRectilinear::BuildDataSet(
nx, 1, 1, xvals, &yvals, &zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(nx, 1, 1, xvals, &yvals, &zvals, coordNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const vtkm::cont::ArrayHandle<T>& xvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
vtkm::cont::ArrayHandle<T> yvals, zvals;
yvals.Allocate(1);
yvals.GetPortalControl().Set(0, 0.0);
zvals.Allocate(1);
zvals.GetPortalControl().Set(0, 0.0);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm);
}
//2D grids.
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const std::vector<T>& xvals,
const std::vector<T>& yvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
std::vector<T> zvals(1, 0);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm);
}
template <typename T>
@ -97,24 +92,21 @@ public:
vtkm::Id ny,
T* xvals,
T* yvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
T zvals = 0;
return DataSetBuilderRectilinear::BuildDataSet(
nx, ny, 1, xvals, yvals, &zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(nx, ny, 1, xvals, yvals, &zvals, coordNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const vtkm::cont::ArrayHandle<T>& xvals,
const vtkm::cont::ArrayHandle<T>& yvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
vtkm::cont::ArrayHandle<T> zvals;
zvals.Allocate(1);
zvals.GetPortalControl().Set(0, 0.0);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm);
}
//3D grids.
@ -125,31 +117,27 @@ public:
T* xvals,
T* yvals,
T* zvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
return DataSetBuilderRectilinear::BuildDataSet(
nx, ny, nz, xvals, yvals, zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(nx, ny, nz, xvals, yvals, zvals, coordNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const std::vector<T>& xvals,
const std::vector<T>& yvals,
const std::vector<T>& zvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const vtkm::cont::ArrayHandle<T>& xvals,
const vtkm::cont::ArrayHandle<T>& yvals,
const vtkm::cont::ArrayHandle<T>& zvals,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(xvals, yvals, zvals, coordNm);
}
private:
@ -157,15 +145,14 @@ private:
VTKM_CONT static vtkm::cont::DataSet BuildDataSet(const std::vector<T>& xvals,
const std::vector<T>& yvals,
const std::vector<T>& zvals,
std::string coordNm,
std::string cellNm)
const std::string& coordNm)
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> Xc, Yc, Zc;
DataSetBuilderRectilinear::CopyInto(xvals, Xc);
DataSetBuilderRectilinear::CopyInto(yvals, Yc);
DataSetBuilderRectilinear::CopyInto(zvals, Zc);
return DataSetBuilderRectilinear::BuildDataSet(Xc, Yc, Zc, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(Xc, Yc, Zc, coordNm);
}
template <typename T>
@ -175,23 +162,21 @@ private:
const T* xvals,
const T* yvals,
const T* zvals,
std::string coordNm,
std::string cellNm)
const std::string& coordNm)
{
vtkm::cont::ArrayHandle<vtkm::FloatDefault> Xc, Yc, Zc;
DataSetBuilderRectilinear::CopyInto(xvals, nx, Xc);
DataSetBuilderRectilinear::CopyInto(yvals, ny, Yc);
DataSetBuilderRectilinear::CopyInto(zvals, nz, Zc);
return DataSetBuilderRectilinear::BuildDataSet(Xc, Yc, Zc, coordNm, cellNm);
return DataSetBuilderRectilinear::BuildDataSet(Xc, Yc, Zc, coordNm);
}
template <typename T>
VTKM_CONT static vtkm::cont::DataSet BuildDataSet(const vtkm::cont::ArrayHandle<T>& X,
const vtkm::cont::ArrayHandle<T>& Y,
const vtkm::cont::ArrayHandle<T>& Z,
std::string coordNm,
std::string cellNm)
const std::string& coordNm)
{
vtkm::cont::DataSet dataSet;
@ -229,21 +214,21 @@ private:
if (ndims == 1)
{
vtkm::cont::CellSetStructured<1> cellSet(cellNm);
vtkm::cont::CellSetStructured<1> cellSet;
cellSet.SetPointDimensions(dims[0]);
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
}
else if (ndims == 2)
{
vtkm::cont::CellSetStructured<2> cellSet(cellNm);
vtkm::cont::CellSetStructured<2> cellSet;
cellSet.SetPointDimensions(vtkm::make_Vec(dims[0], dims[1]));
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
}
else if (ndims == 3)
{
vtkm::cont::CellSetStructured<3> cellSet(cellNm);
vtkm::cont::CellSetStructured<3> cellSet;
cellSet.SetPointDimensions(vtkm::make_Vec(dims[0], dims[1], dims[2]));
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
}
else
{

@ -22,39 +22,31 @@ DataSetBuilderUniform::DataSetBuilderUniform()
VTKM_CONT
vtkm::cont::DataSet DataSetBuilderUniform::Create(const vtkm::Id& dimension,
std::string coordNm,
std::string cellNm)
const std::string& coordNm)
{
return CreateDataSet(vtkm::Id3(dimension, 1, 1), VecType(0), VecType(1), coordNm, cellNm);
return CreateDataSet(vtkm::Id3(dimension, 1, 1), VecType(0), VecType(1), coordNm);
}
VTKM_CONT
vtkm::cont::DataSet DataSetBuilderUniform::Create(const vtkm::Id2& dimensions,
std::string coordNm,
std::string cellNm)
const std::string& coordNm)
{
return CreateDataSet(
vtkm::Id3(dimensions[0], dimensions[1], 1), VecType(0), VecType(1), coordNm, cellNm);
return CreateDataSet(vtkm::Id3(dimensions[0], dimensions[1], 1), VecType(0), VecType(1), coordNm);
}
VTKM_CONT
vtkm::cont::DataSet DataSetBuilderUniform::Create(const vtkm::Id3& dimensions,
std::string coordNm,
std::string cellNm)
const std::string& coordNm)
{
return CreateDataSet(vtkm::Id3(dimensions[0], dimensions[1], dimensions[2]),
VecType(0),
VecType(1),
coordNm,
cellNm);
return CreateDataSet(
vtkm::Id3(dimensions[0], dimensions[1], dimensions[2]), VecType(0), VecType(1), coordNm);
}
VTKM_CONT
vtkm::cont::DataSet DataSetBuilderUniform::CreateDataSet(const vtkm::Id3& dimensions,
const vtkm::Vec3f& origin,
const vtkm::Vec3f& spacing,
std::string coordNm,
std::string cellNm)
const std::string& coordNm)
{
vtkm::Id dims[3] = { 1, 1, 1 };
int ndims = 0;
@ -77,21 +69,21 @@ vtkm::cont::DataSet DataSetBuilderUniform::CreateDataSet(const vtkm::Id3& dimens
if (ndims == 1)
{
vtkm::cont::CellSetStructured<1> cellSet(cellNm);
vtkm::cont::CellSetStructured<1> cellSet;
cellSet.SetPointDimensions(dims[0]);
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
}
else if (ndims == 2)
{
vtkm::cont::CellSetStructured<2> cellSet(cellNm);
vtkm::cont::CellSetStructured<2> cellSet;
cellSet.SetPointDimensions(vtkm::Id2(dims[0], dims[1]));
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
}
else if (ndims == 3)
{
vtkm::cont::CellSetStructured<3> cellSet(cellNm);
vtkm::cont::CellSetStructured<3> cellSet;
cellSet.SetPointDimensions(vtkm::Id3(dims[0], dims[1], dims[2]));
dataSet.AddCellSet(cellSet);
dataSet.SetCellSet(cellSet);
}
else
{

@ -31,29 +31,25 @@ public:
VTKM_CONT static vtkm::cont::DataSet Create(const vtkm::Id& dimension,
const T& origin,
const T& spacing,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
return DataSetBuilderUniform::CreateDataSet(
vtkm::Id3(dimension, 1, 1),
VecType(static_cast<vtkm::FloatDefault>(origin), 0, 0),
VecType(static_cast<vtkm::FloatDefault>(spacing), 1, 1),
coordNm,
cellNm);
coordNm);
}
VTKM_CONT
static vtkm::cont::DataSet Create(const vtkm::Id& dimension,
std::string coordNm = "coords",
std::string cellNm = "cells");
const std::string& coordNm = "coords");
//2D uniform grids.
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const vtkm::Id2& dimensions,
const vtkm::Vec<T, 2>& origin,
const vtkm::Vec<T, 2>& spacing,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
return DataSetBuilderUniform::CreateDataSet(vtkm::Id3(dimensions[0], dimensions[1], 1),
VecType(static_cast<vtkm::FloatDefault>(origin[0]),
@ -62,22 +58,19 @@ public:
VecType(static_cast<vtkm::FloatDefault>(spacing[0]),
static_cast<vtkm::FloatDefault>(spacing[1]),
1),
coordNm,
cellNm);
coordNm);
}
VTKM_CONT
static vtkm::cont::DataSet Create(const vtkm::Id2& dimensions,
std::string coordNm = "coords",
std::string cellNm = "cells");
const std::string& coordNm = "coords");
//3D uniform grids.
template <typename T>
VTKM_CONT static vtkm::cont::DataSet Create(const vtkm::Id3& dimensions,
const vtkm::Vec<T, 3>& origin,
const vtkm::Vec<T, 3>& spacing,
std::string coordNm = "coords",
std::string cellNm = "cells")
const std::string& coordNm = "coords")
{
return DataSetBuilderUniform::CreateDataSet(
vtkm::Id3(dimensions[0], dimensions[1], dimensions[2]),
@ -87,22 +80,19 @@ public:
VecType(static_cast<vtkm::FloatDefault>(spacing[0]),
static_cast<vtkm::FloatDefault>(spacing[1]),
static_cast<vtkm::FloatDefault>(spacing[2])),
coordNm,
cellNm);
coordNm);
}
VTKM_CONT
static vtkm::cont::DataSet Create(const vtkm::Id3& dimensions,
std::string coordNm = "coords",
std::string cellNm = "cells");
const std::string& coordNm = "coords");
private:
VTKM_CONT
static vtkm::cont::DataSet CreateDataSet(const vtkm::Id3& dimensions,
const vtkm::Vec3f& origin,
const vtkm::Vec3f& spacing,
std::string coordNm,
std::string cellNm);
const std::string& coordNm);
};
} // namespace cont

@ -64,83 +64,36 @@ public:
VTKM_CONT
static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const vtkm::cont::VariantArrayHandle& field,
const std::string& cellSetName)
const vtkm::cont::VariantArrayHandle& field)
{
dataSet.AddField(make_FieldCell(fieldName, cellSetName, field));
dataSet.AddField(make_FieldCell(fieldName, field));
}
template <typename T, typename Storage>
VTKM_CONT static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const vtkm::cont::ArrayHandle<T, Storage>& field,
const std::string& cellSetName)
const vtkm::cont::ArrayHandle<T, Storage>& field)
{
dataSet.AddField(make_FieldCell(fieldName, cellSetName, field));
dataSet.AddField(make_FieldCell(fieldName, field));
}
template <typename T>
VTKM_CONT static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const std::vector<T>& field,
const std::string& cellSetName)
const std::vector<T>& field)
{
dataSet.AddField(
make_Field(fieldName, vtkm::cont::Field::Association::CELL_SET, field, vtkm::CopyFlag::On));
}
template <typename T>
VTKM_CONT static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const T* field,
const vtkm::Id& n)
{
dataSet.AddField(make_Field(
fieldName, vtkm::cont::Field::Association::CELL_SET, cellSetName, field, vtkm::CopyFlag::On));
}
template <typename T>
VTKM_CONT static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const T* field,
const vtkm::Id& n,
const std::string& cellSetName)
{
dataSet.AddField(make_Field(fieldName,
vtkm::cont::Field::Association::CELL_SET,
cellSetName,
field,
n,
vtkm::CopyFlag::On));
}
VTKM_CONT
static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const vtkm::cont::VariantArrayHandle& field,
vtkm::Id cellSetIndex = 0)
{
std::string cellSetName = dataSet.GetCellSet(cellSetIndex).GetName();
DataSetFieldAdd::AddCellField(dataSet, fieldName, field, cellSetName);
}
template <typename T, typename Storage>
VTKM_CONT static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const vtkm::cont::ArrayHandle<T, Storage>& field,
vtkm::Id cellSetIndex = 0)
{
std::string cellSetName = dataSet.GetCellSet(cellSetIndex).GetName();
DataSetFieldAdd::AddCellField(dataSet, fieldName, field, cellSetName);
}
template <typename T>
VTKM_CONT static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const std::vector<T>& field,
vtkm::Id cellSetIndex = 0)
{
std::string cellSetName = dataSet.GetCellSet(cellSetIndex).GetName();
DataSetFieldAdd::AddCellField(dataSet, fieldName, field, cellSetName);
}
template <typename T>
VTKM_CONT static void AddCellField(vtkm::cont::DataSet& dataSet,
const std::string& fieldName,
const T* field,
const vtkm::Id& n,
vtkm::Id cellSetIndex = 0)
{
std::string cellSetName = dataSet.GetCellSet(cellSetIndex).GetName();
DataSetFieldAdd::AddCellField(dataSet, fieldName, field, n, cellSetName);
fieldName, vtkm::cont::Field::Association::CELL_SET, field, n, vtkm::CopyFlag::On));
}
};
}

@ -378,6 +378,55 @@ struct DeviceAdapterAlgorithm
const vtkm::cont::ArrayHandle<U, VIn>& values,
vtkm::cont::ArrayHandle<U, VOut>& output);
/// \brief Compute an extended prefix sum operation on the input ArrayHandle.
///
/// Computes an extended prefix sum operation on the \c input ArrayHandle,
/// storing the results in the \c output ArrayHandle. This produces an output
/// array that contains both an inclusive scan (in elements [1, size)) and an
/// exclusive scan (in elements [0, size-1)). By using ArrayHandleView,
/// arrays containing both inclusive and exclusive scans can be generated
/// from an extended scan with minimal memory usage.
///
/// This algorithm may also be more efficient than ScanInclusive and
/// ScanExclusive on some devices, since it may be able to avoid copying the
/// total sum to the control environment to return.
///
/// ScanExtended is similar to the stl partial sum function, exception that
/// ScanExtended doesn't do a serial summation. This means that if you have
/// defined a custom plus operator for T it must be associative, or you will
/// get inconsistent results.
///
/// This overload of ScanExtended uses vtkm::Add for the binary functor, and
/// uses zero for the initial value of the scan operation.
///
template <typename T, class CIn, class COut>
VTKM_CONT static void ScanExtended(const vtkm::cont::ArrayHandle<T, CIn>& input,
vtkm::cont::ArrayHandle<T, COut>& output);
/// \brief Compute an extended prefix sum operation on the input ArrayHandle.
///
/// Computes an extended prefix sum operation on the \c input ArrayHandle,
/// storing the results in the \c output ArrayHandle. This produces an output
/// array that contains both an inclusive scan (in elements [1, size)) and an
/// exclusive scan (in elements [0, size-1)). By using ArrayHandleView,
/// arrays containing both inclusive and exclusive scans can be generated
/// from an extended scan with minimal memory usage.
///
/// This algorithm may also be more efficient than ScanInclusive and
/// ScanExclusive on some devices, since it may be able to avoid copying the
/// total sum to the control environment to return.
///
/// ScanExtended is similar to the stl partial sum function, exception that
/// ScanExtended doesn't do a serial summation. This means that if you have
/// defined a custom plus operator for T it must be associative, or you will
/// get inconsistent results.
///
template <typename T, class CIn, class COut, class BinaryFunctor>
VTKM_CONT static void ScanExtended(const vtkm::cont::ArrayHandle<T, CIn>& input,
vtkm::cont::ArrayHandle<T, COut>& output,
BinaryFunctor binaryFunctor,
const T& initialValue);
/// \brief Schedule many instances of a function to run on concurrent threads.
///
/// Calls the \c functor on several threads. This is the function used in the
@ -683,15 +732,6 @@ public:
#endif
};
/// \brief Class providing a device-specific support for atomic operations.
///
/// The class provide the actual implementation used by
/// vtkm::cont::DeviceAdapterAtomicArrayImplementation.
///
/// TODO combine this with AtomicInterfaceExecution.
template <typename T, typename DeviceTag>
class DeviceAdapterAtomicArrayImplementation;
/// \brief Class providing a device-specific support for atomic operations.
///
/// AtomicInterfaceControl provides atomic operations for the control

@ -174,9 +174,6 @@ public:
VTKM_CONT
const vtkm::cont::CellSet* GetCellSetBase() const { return this->CellSet.get(); }
VTKM_CONT
std::string GetName() const { return this->CellSet ? this->CellSet->GetName() : std::string{}; }
VTKM_CONT
vtkm::Id GetNumberOfCells() const
{

@ -20,36 +20,16 @@ VTKM_CONT
Field::Field(std::string name, Association association, const vtkm::cont::VariantArrayHandle& data)
: Name(name)
, FieldAssociation(association)
, AssocCellSetName()
, Data(data)
, Range()
, ModifiedFlag(true)
{
VTKM_ASSERT(this->FieldAssociation == Association::WHOLE_MESH ||
this->FieldAssociation == Association::POINTS);
}
/// constructors for cell set associations
VTKM_CONT
Field::Field(std::string name,
Association association,
const std::string& cellSetName,
const vtkm::cont::VariantArrayHandle& data)
: Name(name)
, FieldAssociation(association)
, AssocCellSetName(cellSetName)
, Data(data)
, Range()
, ModifiedFlag(true)
{
VTKM_ASSERT(this->FieldAssociation == Association::CELL_SET);
}
VTKM_CONT
Field::Field(const vtkm::cont::Field& src)
: Name(src.Name)
, FieldAssociation(src.FieldAssociation)
, AssocCellSetName(src.AssocCellSetName)
, Data(src.Data)
, Range(src.Range)
, ModifiedFlag(src.ModifiedFlag)
@ -59,7 +39,6 @@ Field::Field(const vtkm::cont::Field& src)
VTKM_CONT
Field::Field(vtkm::cont::Field&& src) noexcept : Name(std::move(src.Name)),
FieldAssociation(std::move(src.FieldAssociation)),
AssocCellSetName(std::move(src.AssocCellSetName)),
Data(std::move(src.Data)),
Range(std::move(src.Range)),
ModifiedFlag(std::move(src.ModifiedFlag))
@ -71,7 +50,6 @@ Field& Field::operator=(const vtkm::cont::Field& src)
{
this->Name = src.Name;
this->FieldAssociation = src.FieldAssociation;
this->AssocCellSetName = src.AssocCellSetName;
this->Data = src.Data;
this->Range = src.Range;
this->ModifiedFlag = src.ModifiedFlag;
@ -83,7 +61,6 @@ Field& Field::operator=(vtkm::cont::Field&& src) noexcept
{
this->Name = std::move(src.Name);
this->FieldAssociation = std::move(src.FieldAssociation);
this->AssocCellSetName = std::move(src.AssocCellSetName);
this->Data = std::move(src.Data);
this->Range = std::move(src.Range);
this->ModifiedFlag = std::move(src.ModifiedFlag);

@ -58,7 +58,6 @@ public:
VTKM_CONT
Field() = default;
/// constructors for points / whole mesh
VTKM_CONT
Field(std::string name, Association association, const vtkm::cont::VariantArrayHandle& data);
@ -70,22 +69,6 @@ public:
{
}
/// constructors for cell set associations
VTKM_CONT
Field(std::string name,
Association association,
const std::string& cellSetName,
const vtkm::cont::VariantArrayHandle& data);
template <typename T, typename Storage>
VTKM_CONT Field(std::string name,
Association association,
const std::string& cellSetName,
const vtkm::cont::ArrayHandle<T, Storage>& data)
: Field(name, association, cellSetName, vtkm::cont::VariantArrayHandle{ data })
{
}
Field(const vtkm::cont::Field& src);
Field(vtkm::cont::Field&& src) noexcept;
@ -96,7 +79,6 @@ public:
VTKM_CONT const std::string& GetName() const { return this->Name; }
VTKM_CONT Association GetAssociation() const { return this->FieldAssociation; }
VTKM_CONT std::string GetAssocCellSet() const { return this->AssocCellSetName; }
const vtkm::cont::VariantArrayHandle& GetData() const;
vtkm::cont::VariantArrayHandle& GetData();
@ -161,8 +143,6 @@ private:
std::string Name; ///< name of field
Association FieldAssociation = Association::ANY;
std::string AssocCellSetName; ///< only populate if assoc is cells
vtkm::cont::VariantArrayHandle Data;
mutable vtkm::cont::ArrayHandle<vtkm::Range> Range;
mutable bool ModifiedFlag = true;
@ -211,50 +191,8 @@ vtkm::cont::Field make_Field(std::string name,
return vtkm::cont::Field(name, association, vtkm::cont::make_ArrayHandle(data, copy));
}
template <typename T>
vtkm::cont::Field make_Field(std::string name,
Field::Association association,
const std::string& cellSetName,
const T* data,
vtkm::Id size,
vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
{
return vtkm::cont::Field(
name, association, cellSetName, vtkm::cont::make_ArrayHandle(data, size, copy));
}
template <typename T>
vtkm::cont::Field make_Field(std::string name,
Field::Association association,
const std::string& cellSetName,
const std::vector<T>& data,
vtkm::CopyFlag copy = vtkm::CopyFlag::Off)
{
return vtkm::cont::Field(
name, association, cellSetName, vtkm::cont::make_ArrayHandle(data, copy));
}
//@}
/// Convenience functions to build a point or cell field from vtkm::cont::ArrayHandle
/// If \c association is CELL_SET it will
template <typename T, typename S>
vtkm::cont::Field make_Field(std::string name,
Field::Association association,
const std::string& cellSetName,
const vtkm::cont::ArrayHandle<T, S>& data)
{
if (association == Field::Association::CELL_SET)
{
return vtkm::cont::Field(name, association, cellSetName, data);
}
else
{
return vtkm::cont::Field(name, association, data);
}
}
/// Convenience function to build point fields from vtkm::cont::ArrayHandle
template <typename T, typename S>
vtkm::cont::Field make_FieldPoint(std::string name, const vtkm::cont::ArrayHandle<T, S>& data)
@ -271,20 +209,17 @@ inline vtkm::cont::Field make_FieldPoint(std::string name,
/// Convenience function to build cell fields from vtkm::cont::ArrayHandle
template <typename T, typename S>
vtkm::cont::Field make_FieldCell(std::string name,
const std::string& cellSetName,
const vtkm::cont::ArrayHandle<T, S>& data)
vtkm::cont::Field make_FieldCell(std::string name, const vtkm::cont::ArrayHandle<T, S>& data)
{
return vtkm::cont::Field(name, vtkm::cont::Field::Association::CELL_SET, cellSetName, data);
return vtkm::cont::Field(name, vtkm::cont::Field::Association::CELL_SET, data);
}
/// Convenience function to build cell fields from vtkm::cont::VariantArrayHandle
inline vtkm::cont::Field make_FieldCell(std::string name,
const std::string& cellSetName,
const vtkm::cont::VariantArrayHandle& data)
{
return vtkm::cont::Field(name, vtkm::cont::Field::Association::CELL_SET, cellSetName, data);
return vtkm::cont::Field(name, vtkm::cont::Field::Association::CELL_SET, data);
}
} // namespace cont
@ -343,10 +278,6 @@ public:
vtkmdiy::save(bb, field.GetName());
vtkmdiy::save(bb, static_cast<int>(field.GetAssociation()));
if (field.GetAssociation() == vtkm::cont::Field::Association::CELL_SET)
{
vtkmdiy::save(bb, field.GetAssocCellSet());
}
vtkmdiy::save(bb, field.GetData().ResetTypes(TypeList{}));
}
@ -361,19 +292,8 @@ public:
auto assoc = static_cast<vtkm::cont::Field::Association>(assocVal);
vtkm::cont::VariantArrayHandleBase<TypeList> data;
if (assoc == vtkm::cont::Field::Association::CELL_SET)
{
std::string assocCellSetName;
vtkmdiy::load(bb, assocCellSetName);
vtkmdiy::load(bb, data);
field =
vtkm::cont::Field(name, assoc, assocCellSetName, vtkm::cont::VariantArrayHandle(data));
}
else
{
vtkmdiy::load(bb, data);
field = vtkm::cont::Field(name, assoc, vtkm::cont::VariantArrayHandle(data));
}
vtkmdiy::load(bb, data);
field = vtkm::cont::Field(name, assoc, vtkm::cont::VariantArrayHandle(data));
}
};

@ -29,12 +29,11 @@ vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeCompute(const vtkm::cont::DataSet
//-----------------------------------------------------------------------------
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeCompute(const vtkm::cont::MultiBlock& multiblock,
vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeCompute(const vtkm::cont::PartitionedDataSet& pds,
const std::string& name,
vtkm::cont::Field::Association assoc)
{
return vtkm::cont::detail::FieldRangeComputeImpl(
multiblock, name, assoc, VTKM_DEFAULT_TYPE_LIST_TAG());
return vtkm::cont::detail::FieldRangeComputeImpl(pds, name, assoc, VTKM_DEFAULT_TYPE_LIST_TAG());
}
}
} // namespace vtkm::cont

@ -12,7 +12,7 @@
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/MultiBlock.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <vtkm/cont/FieldRangeCompute.hxx>
@ -20,9 +20,10 @@ namespace vtkm
{
namespace cont
{
/// \brief Compute ranges for fields in a DataSet or MultiBlock.
/// \brief Compute ranges for fields in a DataSet or PartitionedDataSet.
///
/// These methods to compute ranges for fields in a dataset or a multiblock.
/// These methods to compute ranges for fields in a single dataset or a
/// partitioned dataset.
/// When using VTK-m in a hybrid-parallel environment with distributed processing,
/// this class uses ranges for locally available data alone. Use FieldRangeGlobalCompute
/// to compute ranges globally across all ranks even in distributed mode.
@ -51,28 +52,30 @@ VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeCompute(
//@}
//{@
/// Returns the range for a field from a multiblock. If the field is not present on any
/// of the blocks, an empty ArrayHandle will be returned. If the field is present on some blocks,
/// but not all, those blocks without the field are skipped.
/// Returns the range for a field from a PartitionedDataSet. If the field is
/// not present on any of the partitions, an empty ArrayHandle will be
/// returned. If the field is present on some partitions, but not all, those
/// partitions without the field are skipped.
///
/// The returned array handle will have as many values as the maximum number of
/// components for the selected field across all partitions.
///
/// The returned array handle will have as many values as the maximum number of components for
/// the selected field across all blocks.
VTKM_CONT_EXPORT
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeCompute(
const vtkm::cont::MultiBlock& multiblock,
const vtkm::cont::PartitionedDataSet& pds,
const std::string& name,
vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::ANY);
template <typename TypeList>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeCompute(
const vtkm::cont::MultiBlock& multiblock,
const vtkm::cont::PartitionedDataSet& pds,
const std::string& name,
vtkm::cont::Field::Association assoc,
TypeList)
{
VTKM_IS_LIST_TAG(TypeList);
return vtkm::cont::detail::FieldRangeComputeImpl(multiblock, name, assoc, TypeList());
return vtkm::cont::detail::FieldRangeComputeImpl(pds, name, assoc, TypeList());
}
//@}

@ -10,6 +10,12 @@
#ifndef vtk_m_cont_FieldRangeCompute_hxx
#define vtk_m_cont_FieldRangeCompute_hxx
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/PartitionedDataSet.h>
#include <vtkm/Range.h>
#include <numeric> // for std::accumulate
namespace vtkm
@ -42,26 +48,27 @@ VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeComputeImpl(
template <typename TypeList>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeComputeImpl(
const vtkm::cont::MultiBlock& multiblock,
const vtkm::cont::PartitionedDataSet& pds,
const std::string& name,
vtkm::cont::Field::Association assoc,
TypeList)
{
std::vector<vtkm::Range> result_vector = std::accumulate(
multiblock.begin(),
multiblock.end(),
pds.begin(),
pds.end(),
std::vector<vtkm::Range>(),
[&](const std::vector<vtkm::Range>& accumulated_value, const vtkm::cont::DataSet& dataset) {
vtkm::cont::ArrayHandle<vtkm::Range> block_range =
vtkm::cont::ArrayHandle<vtkm::Range> partition_range =
vtkm::cont::detail::FieldRangeComputeImpl(dataset, name, assoc, TypeList());
std::vector<vtkm::Range> result = accumulated_value;
// if the current block has more components than we have seen so far,
// if the current partition has more components than we have seen so far,
// resize the result to fit all components.
result.resize(std::max(result.size(), static_cast<size_t>(block_range.GetNumberOfValues())));
result.resize(
std::max(result.size(), static_cast<size_t>(partition_range.GetNumberOfValues())));
auto portal = block_range.GetPortalConstControl();
auto portal = partition_range.GetPortalConstControl();
std::transform(vtkm::cont::ArrayPortalToIteratorBegin(portal),
vtkm::cont::ArrayPortalToIteratorEnd(portal),
result.begin(),

@ -33,11 +33,11 @@ vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalCompute(const vtkm::cont::D
//-----------------------------------------------------------------------------
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalCompute(
const vtkm::cont::MultiBlock& multiblock,
const vtkm::cont::PartitionedDataSet& pds,
const std::string& name,
vtkm::cont::Field::Association assoc)
{
return detail::FieldRangeGlobalComputeImpl(multiblock, name, assoc, VTKM_DEFAULT_TYPE_LIST_TAG());
return detail::FieldRangeGlobalComputeImpl(pds, name, assoc, VTKM_DEFAULT_TYPE_LIST_TAG());
}
//-----------------------------------------------------------------------------

@ -20,7 +20,8 @@ namespace cont
{
/// \brief utility functions to compute global ranges for dataset fields.
///
/// These functions compute global ranges for fields in a dataset or a multiblock.
/// These functions compute global ranges for fields in a single DataSet or a
/// PartitionedDataSet.
/// In non-distributed environments, this is exactly same as `FieldRangeCompute`. In
/// distributed environments, however, the range is computed locally on each rank
/// and then a reduce-all collective is performed to reduces the ranges on all ranks.
@ -49,28 +50,29 @@ VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalCompute(
//@}
//{@
/// Returns the range for a field from a multiblock. If the field is not present on any
/// of the blocks, an empty ArrayHandle will be returned. If the field is present on some blocks,
/// but not all, those blocks without the field are skipped.
/// Returns the range for a field from a PartitionedDataSet. If the field is
/// not present on any of the partitions, an empty ArrayHandle will be
/// returned. If the field is present on some partitions, but not all, those
/// partitions without the field are skipped.
///
/// The returned array handle will have as many values as the maximum number of components for
/// the selected field across all blocks.
/// The returned array handle will have as many values as the maximum number of
/// components for the selected field across all partitions.
VTKM_CONT_EXPORT
VTKM_CONT
vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalCompute(
const vtkm::cont::MultiBlock& multiblock,
const vtkm::cont::PartitionedDataSet& pds,
const std::string& name,
vtkm::cont::Field::Association assoc = vtkm::cont::Field::Association::ANY);
template <typename TypeList>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalCompute(
const vtkm::cont::MultiBlock& multiblock,
const vtkm::cont::PartitionedDataSet& pds,
const std::string& name,
vtkm::cont::Field::Association assoc,
TypeList)
{
VTKM_IS_LIST_TAG(TypeList);
return detail::FieldRangeGlobalComputeImpl(multiblock, name, assoc, TypeList());
return detail::FieldRangeGlobalComputeImpl(pds, name, assoc, TypeList());
}
//@}
}

@ -35,12 +35,12 @@ VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalComputeImpl(
template <typename TypeList>
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Range> FieldRangeGlobalComputeImpl(
const vtkm::cont::MultiBlock& multiblock,
const vtkm::cont::PartitionedDataSet& pds,
const std::string& name,
vtkm::cont::Field::Association assoc,
TypeList)
{
auto lrange = vtkm::cont::FieldRangeCompute(multiblock, name, assoc, TypeList());
auto lrange = vtkm::cont::FieldRangeCompute(pds, name, assoc, TypeList());
return vtkm::cont::detail::MergeRangesGlobal(lrange);
}
}

@ -431,6 +431,7 @@ VTKM_CONT_EXPORT
VTKM_CONT
std::string GetStackTrace(vtkm::Int32 skip = 0);
//@{
/// Convert a size in bytes to a human readable string (e.g. "64 bytes",
/// "1.44 MiB", "128 GiB", etc). @a prec controls the fixed point precision
/// of the stringified number.
@ -438,12 +439,27 @@ VTKM_CONT_EXPORT
VTKM_CONT
std::string GetHumanReadableSize(vtkm::UInt64 bytes, int prec = 2);
template <typename T>
VTKM_CONT inline std::string GetHumanReadableSize(T&& bytes, int prec = 2)
{
return GetHumanReadableSize(static_cast<vtkm::UInt64>(std::forward<T>(bytes)), prec);
}
//@}
//@{
/// Returns "%1 (%2 bytes)" where %1 is the result from GetHumanReadableSize
/// and two is the exact number of bytes.
VTKM_CONT_EXPORT
VTKM_CONT
std::string GetSizeString(vtkm::UInt64 bytes, int prec = 2);
template <typename T>
VTKM_CONT inline std::string GetSizeString(T&& bytes, int prec = 2)
{
return GetSizeString(static_cast<vtkm::UInt64>(std::forward<T>(bytes)), prec);
}
//@}
/**
* Use RTTI information to retrieve the name of the type T. If logging is
* enabled and the platform supports it, the type name will also be demangled.

@ -1,143 +0,0 @@
//============================================================================
// 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/StaticAssert.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/ErrorExecution.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/MultiBlock.h>
namespace vtkm
{
namespace cont
{
VTKM_CONT
MultiBlock::MultiBlock(const vtkm::cont::DataSet& ds)
{
this->Blocks.insert(this->Blocks.end(), ds);
}
VTKM_CONT
MultiBlock::MultiBlock(const vtkm::cont::MultiBlock& src)
{
this->Blocks = src.GetBlocks();
}
VTKM_CONT
MultiBlock::MultiBlock(const std::vector<vtkm::cont::DataSet>& mblocks)
{
this->Blocks = mblocks;
}
VTKM_CONT
MultiBlock::MultiBlock(vtkm::Id size)
{
this->Blocks.reserve(static_cast<std::size_t>(size));
}
VTKM_CONT
MultiBlock::MultiBlock()
{
}
VTKM_CONT
MultiBlock::~MultiBlock()
{
}
VTKM_CONT
MultiBlock& MultiBlock::operator=(const vtkm::cont::MultiBlock& src)
{
this->Blocks = src.GetBlocks();
return *this;
}
VTKM_CONT
vtkm::cont::Field MultiBlock::GetField(const std::string& field_name, const int& block_index)
{
assert(block_index >= 0);
assert(static_cast<std::size_t>(block_index) < this->Blocks.size());
return this->Blocks[static_cast<std::size_t>(block_index)].GetField(field_name);
}
VTKM_CONT
vtkm::Id MultiBlock::GetNumberOfBlocks() const
{
return static_cast<vtkm::Id>(this->Blocks.size());
}
VTKM_CONT
const vtkm::cont::DataSet& MultiBlock::GetBlock(vtkm::Id blockId) const
{
return this->Blocks[static_cast<std::size_t>(blockId)];
}
VTKM_CONT
const std::vector<vtkm::cont::DataSet>& MultiBlock::GetBlocks() const
{
return this->Blocks;
}
VTKM_CONT
void MultiBlock::AddBlock(const vtkm::cont::DataSet& ds)
{
this->Blocks.insert(this->Blocks.end(), ds);
return;
}
void MultiBlock::AddBlocks(const std::vector<vtkm::cont::DataSet>& mblocks)
{
this->Blocks.insert(this->Blocks.end(), mblocks.begin(), mblocks.end());
return;
}
VTKM_CONT
void MultiBlock::InsertBlock(vtkm::Id index, const vtkm::cont::DataSet& ds)
{
if (index <= static_cast<vtkm::Id>(this->Blocks.size()))
this->Blocks.insert(this->Blocks.begin() + index, ds);
else
{
std::string msg = "invalid insert position\n ";
throw ErrorExecution(msg);
}
}
VTKM_CONT
void MultiBlock::ReplaceBlock(vtkm::Id index, const vtkm::cont::DataSet& ds)
{
if (index < static_cast<vtkm::Id>(this->Blocks.size()))
this->Blocks.at(static_cast<std::size_t>(index)) = ds;
else
{
std::string msg = "invalid replace position\n ";
throw ErrorExecution(msg);
}
}
VTKM_CONT
void MultiBlock::PrintSummary(std::ostream& stream) const
{
stream << "block "
<< "\n";
for (size_t block_index = 0; block_index < this->Blocks.size(); ++block_index)
{
stream << "block " << block_index << "\n";
this->Blocks[block_index].PrintSummary(stream);
}
}
}
} // namespace vtkm::cont

@ -1,92 +0,0 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_MultiBlock_h
#define vtk_m_cont_MultiBlock_h
#include <limits>
#include <vtkm/StaticAssert.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/Field.h>
namespace vtkm
{
namespace cont
{
class VTKM_CONT_EXPORT MultiBlock
{
public:
/// create a new MultiBlock containng a single DataSet "ds"
VTKM_CONT
MultiBlock(const vtkm::cont::DataSet& ds);
/// create a new MultiBlock with the existing one "src"
VTKM_CONT
MultiBlock(const vtkm::cont::MultiBlock& src);
/// create a new MultiBlock with a DataSet vector "mblocks"
VTKM_CONT
explicit MultiBlock(const std::vector<vtkm::cont::DataSet>& mblocks);
/// create a new MultiBlock with the capacity set to be "size"
VTKM_CONT
explicit MultiBlock(vtkm::Id size);
VTKM_CONT
MultiBlock();
VTKM_CONT
MultiBlock& operator=(const vtkm::cont::MultiBlock& src);
VTKM_CONT
~MultiBlock();
/// get the field "field_name" from block "block_index"
VTKM_CONT
vtkm::cont::Field GetField(const std::string& field_name, const int& block_index);
VTKM_CONT
vtkm::Id GetNumberOfBlocks() const;
VTKM_CONT
const vtkm::cont::DataSet& GetBlock(vtkm::Id blockId) const;
VTKM_CONT
const std::vector<vtkm::cont::DataSet>& GetBlocks() const;
/// add DataSet "ds" to the end of the contained DataSet vector
VTKM_CONT
void AddBlock(const vtkm::cont::DataSet& ds);
/// add DataSet "ds" to position "index" of the contained DataSet vector
VTKM_CONT
void InsertBlock(vtkm::Id index, const vtkm::cont::DataSet& ds);
/// replace the "index" positioned element of the contained DataSet vector with "ds"
VTKM_CONT
void ReplaceBlock(vtkm::Id index, const vtkm::cont::DataSet& ds);
/// append the DataSet vector "mblocks" to the end of the contained one
VTKM_CONT
void AddBlocks(const std::vector<vtkm::cont::DataSet>& mblocks);
VTKM_CONT
void PrintSummary(std::ostream& stream) const;
//@{
/// API to support range-based for loops on blocks.
std::vector<DataSet>::iterator begin() noexcept { return this->Blocks.begin(); }
std::vector<DataSet>::iterator end() noexcept { return this->Blocks.end(); }
std::vector<DataSet>::const_iterator begin() const noexcept { return this->Blocks.begin(); }
std::vector<DataSet>::const_iterator end() const noexcept { return this->Blocks.end(); }
std::vector<DataSet>::const_iterator cbegin() const noexcept { return this->Blocks.begin(); }
std::vector<DataSet>::const_iterator cend() const noexcept { return this->Blocks.end(); }
//@}
private:
std::vector<vtkm::cont::DataSet> Blocks;
};
}
} // namespace vtkm::cont
#endif

@ -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/StaticAssert.h>
#include <vtkm/cont/ArrayCopy.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/EnvironmentTracker.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <vtkm/cont/Field.h>
#include <vtkm/cont/PartitionedDataSet.h>
namespace vtkm
{
namespace cont
{
VTKM_CONT
PartitionedDataSet::PartitionedDataSet(const vtkm::cont::DataSet& ds)
{
this->Partitions.insert(this->Partitions.end(), ds);
}
VTKM_CONT
PartitionedDataSet::PartitionedDataSet(const vtkm::cont::PartitionedDataSet& src)
{
this->Partitions = src.GetPartitions();
}
VTKM_CONT
PartitionedDataSet::PartitionedDataSet(const std::vector<vtkm::cont::DataSet>& partitions)
{
this->Partitions = partitions;
}
VTKM_CONT
PartitionedDataSet::PartitionedDataSet(vtkm::Id size)
{
this->Partitions.reserve(static_cast<std::size_t>(size));
}
VTKM_CONT
PartitionedDataSet::PartitionedDataSet()
{
}
VTKM_CONT
PartitionedDataSet::~PartitionedDataSet()
{
}
VTKM_CONT
PartitionedDataSet& PartitionedDataSet::operator=(const vtkm::cont::PartitionedDataSet& src)
{
this->Partitions = src.GetPartitions();
return *this;
}
VTKM_CONT
vtkm::cont::Field PartitionedDataSet::GetField(const std::string& field_name, int partition_index)
{
assert(partition_index >= 0);
assert(static_cast<std::size_t>(partition_index) < this->Partitions.size());
return this->Partitions[static_cast<std::size_t>(partition_index)].GetField(field_name);
}
VTKM_CONT
vtkm::Id PartitionedDataSet::GetNumberOfPartitions() const
{
return static_cast<vtkm::Id>(this->Partitions.size());
}
VTKM_CONT
const vtkm::cont::DataSet& PartitionedDataSet::GetPartition(vtkm::Id blockId) const
{
return this->Partitions[static_cast<std::size_t>(blockId)];
}
VTKM_CONT
const std::vector<vtkm::cont::DataSet>& PartitionedDataSet::GetPartitions() const
{
return this->Partitions;
}
VTKM_CONT
void PartitionedDataSet::AppendPartition(const vtkm::cont::DataSet& ds)
{
this->Partitions.insert(this->Partitions.end(), ds);
}
VTKM_CONT
void PartitionedDataSet::AppendPartitions(const std::vector<vtkm::cont::DataSet>& partitions)
{
this->Partitions.insert(this->Partitions.end(), partitions.begin(), partitions.end());
}
VTKM_CONT
void PartitionedDataSet::InsertPartition(vtkm::Id index, const vtkm::cont::DataSet& ds)
{
if (index <= static_cast<vtkm::Id>(this->Partitions.size()))
{
this->Partitions.insert(this->Partitions.begin() + index, ds);
}
else
{
std::string msg = "invalid insert position\n ";
throw ErrorBadValue(msg);
}
}
VTKM_CONT
void PartitionedDataSet::ReplacePartition(vtkm::Id index, const vtkm::cont::DataSet& ds)
{
if (index < static_cast<vtkm::Id>(this->Partitions.size()))
this->Partitions.at(static_cast<std::size_t>(index)) = ds;
else
{
std::string msg = "invalid replace position\n ";
throw ErrorBadValue(msg);
}
}
VTKM_CONT
void PartitionedDataSet::PrintSummary(std::ostream& stream) const
{
stream << "PartitionedDataSet [" << this->Partitions.size() << " partitions]:\n";
for (size_t part = 0; part < this->Partitions.size(); ++part)
{
stream << "Partition " << part << ":\n";
this->Partitions[part].PrintSummary(stream);
}
}
}
} // namespace vtkm::cont

@ -0,0 +1,111 @@
//============================================================================
// 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.
//============================================================================
#ifndef vtk_m_cont_PartitionedDataSet_h
#define vtk_m_cont_PartitionedDataSet_h
#include <limits>
#include <vtkm/StaticAssert.h>
#include <vtkm/cont/ArrayHandle.h>
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/DeviceAdapterAlgorithm.h>
#include <vtkm/cont/Field.h>
namespace vtkm
{
namespace cont
{
class VTKM_CONT_EXPORT PartitionedDataSet
{
using StorageVec = std::vector<vtkm::cont::DataSet>;
public:
using iterator = typename StorageVec::iterator;
using const_iterator = typename StorageVec::const_iterator;
using value_type = typename StorageVec::value_type;
using reference = typename StorageVec::reference;
using const_reference = typename StorageVec::const_reference;
/// create a new PartitionedDataSet containng a single DataSet @a ds
VTKM_CONT
PartitionedDataSet(const vtkm::cont::DataSet& ds);
/// create a new PartitionedDataSet with the existing one @a src
VTKM_CONT
PartitionedDataSet(const vtkm::cont::PartitionedDataSet& src);
/// create a new PartitionedDataSet with a DataSet vector @a partitions.
VTKM_CONT
explicit PartitionedDataSet(const std::vector<vtkm::cont::DataSet>& partitions);
/// create a new PartitionedDataSet with the capacity set to be @a size
VTKM_CONT
explicit PartitionedDataSet(vtkm::Id size);
VTKM_CONT
PartitionedDataSet();
VTKM_CONT
PartitionedDataSet& operator=(const vtkm::cont::PartitionedDataSet& src);
VTKM_CONT
~PartitionedDataSet();
/// get the field @a field_name from partition @a partition_index
VTKM_CONT
vtkm::cont::Field GetField(const std::string& field_name, int partition_index);
VTKM_CONT
vtkm::Id GetNumberOfPartitions() const;
VTKM_CONT
const vtkm::cont::DataSet& GetPartition(vtkm::Id partId) const;
VTKM_CONT
const std::vector<vtkm::cont::DataSet>& GetPartitions() const;
/// add DataSet @a ds to the end of the contained DataSet vector
VTKM_CONT
void AppendPartition(const vtkm::cont::DataSet& ds);
/// add DataSet @a ds to position @a index of the contained DataSet vector
VTKM_CONT
void InsertPartition(vtkm::Id index, const vtkm::cont::DataSet& ds);
/// replace the @a index positioned element of the contained DataSet vector
/// with @a ds
VTKM_CONT
void ReplacePartition(vtkm::Id index, const vtkm::cont::DataSet& ds);
/// append the DataSet vector "partitions" to the end of the contained one
VTKM_CONT
void AppendPartitions(const std::vector<vtkm::cont::DataSet>& partitions);
VTKM_CONT
void PrintSummary(std::ostream& stream) const;
//@{
/// API to support range-based for loops on partitions.
VTKM_CONT
iterator begin() noexcept { return this->Partitions.begin(); }
VTKM_CONT
iterator end() noexcept { return this->Partitions.end(); }
VTKM_CONT
const_iterator begin() const noexcept { return this->Partitions.begin(); }
VTKM_CONT
const_iterator end() const noexcept { return this->Partitions.end(); }
VTKM_CONT
const_iterator cbegin() const noexcept { return this->Partitions.cbegin(); }
VTKM_CONT
const_iterator cend() const noexcept { return this->Partitions.cend(); }
//@}
private:
std::vector<vtkm::cont::DataSet> Partitions;
};
}
} // namespace vtkm::cont
#endif

@ -169,6 +169,17 @@ void RuntimeDeviceTracker::ForceDevice(DeviceAdapterId deviceId)
}
}
VTKM_CONT
void RuntimeDeviceTracker::PrintSummary(std::ostream& out) const
{
for (vtkm::Int8 i = 1; i < VTKM_MAX_DEVICE_ADAPTER_ID; ++i)
{
auto dev = vtkm::cont::make_DeviceAdapterId(i);
out << " - Device " << static_cast<vtkm::Int32>(i) << " (" << dev.GetName()
<< "): Enabled=" << this->CanRunOn(dev) << "\n";
}
}
VTKM_CONT
ScopedRuntimeDeviceTracker::ScopedRuntimeDeviceTracker(vtkm::cont::DeviceAdapterId device,
RuntimeDeviceTrackerMode mode)

@ -110,6 +110,8 @@ public:
///
VTKM_CONT void ForceDevice(DeviceAdapterId deviceId);
VTKM_CONT void PrintSummary(std::ostream& out) const;
private:
friend struct ScopedRuntimeDeviceTracker;

@ -12,7 +12,7 @@
#include <vtkm/internal/IndicesExtrude.h>
#include <vtkm/BaseComponent.h>
#include <vtkm/VecTraits.h>
#include <vtkm/cont/ErrorBadType.h>
@ -371,7 +371,7 @@ struct VTKM_ALWAYS_EXPORT StorageTagExtrude
template <typename T>
class Storage<T, internal::StorageTagExtrude>
{
using BaseT = typename BaseComponent<T>::Type;
using BaseT = typename VecTraits<T>::BaseComponentType;
using HandleType = vtkm::cont::ArrayHandle<BaseT>;
using TPortalType = typename HandleType::PortalConstControl;
@ -461,7 +461,7 @@ private:
template <typename T, typename Device>
class VTKM_ALWAYS_EXPORT ArrayTransfer<T, internal::StorageTagExtrude, Device>
{
using BaseT = typename BaseComponent<T>::Type;
using BaseT = typename VecTraits<T>::BaseComponentType;
using TPortalType = decltype(vtkm::cont::ArrayHandle<BaseT>{}.PrepareForInput(Device{}));
public:

Some files were not shown because too many files have changed in this diff Show More