mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-10-05 01:49:02 +00:00
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). Ref #405
This commit is contained in:
parent
80fa659e3f
commit
63050f68fc
16
docs/changelog/multiblock_renamed_partitioneddataset.md
Normal file
16
docs/changelog/multiblock_renamed_partitioneddataset.md
Normal file
@ -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).
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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
|
81
vtkm/cont/AssignerPartitionedDataSet.cxx
Normal file
81
vtkm/cont/AssignerPartitionedDataSet.cxx
Normal file
@ -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,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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
143
vtkm/cont/PartitionedDataSet.cxx
Normal file
143
vtkm/cont/PartitionedDataSet.cxx
Normal file
@ -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
|
111
vtkm/cont/PartitionedDataSet.h
Normal file
111
vtkm/cont/PartitionedDataSet.h
Normal file
@ -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
|
@ -72,7 +72,7 @@ set(unit_tests
|
||||
UnitTestInitialize.cxx
|
||||
UnitTestLogging.cxx
|
||||
UnitTestMoveConstructors.cxx
|
||||
UnitTestMultiBlock.cxx
|
||||
UnitTestPartitionedDataSet.cxx
|
||||
UnitTestRuntimeDeviceInformation.cxx
|
||||
UnitTestRuntimeDeviceNames.cxx
|
||||
UnitTestScopedRuntimeDeviceTracker.cxx
|
||||
|
@ -118,12 +118,12 @@ void TryRangeComputeDS(const ValueType& min, const ValueType& max)
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
void TryRangeComputeMB(const ValueType& min, const ValueType& max)
|
||||
void TryRangeComputePDS(const ValueType& min, const ValueType& max)
|
||||
{
|
||||
std::cout << "Trying type (multiblock): " << vtkm::testing::TypeName<ValueType>::Name()
|
||||
std::cout << "Trying type (PartitionedDataSet): " << vtkm::testing::TypeName<ValueType>::Name()
|
||||
<< std::endl;
|
||||
|
||||
vtkm::cont::MultiBlock mb;
|
||||
vtkm::cont::PartitionedDataSet mb;
|
||||
for (int cc = 0; cc < 5; cc++)
|
||||
{
|
||||
// let's create a dummy dataset with a bunch of fields.
|
||||
@ -132,7 +132,7 @@ void TryRangeComputeMB(const ValueType& min, const ValueType& max)
|
||||
dataset,
|
||||
"pointvar",
|
||||
CreateArray(min, max, ARRAY_SIZE, typename vtkm::TypeTraits<ValueType>::DimensionalityTag()));
|
||||
mb.AddBlock(dataset);
|
||||
mb.AppendPartition(dataset);
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ranges = vtkm::cont::FieldRangeCompute(mb, "pointvar");
|
||||
@ -148,10 +148,10 @@ static void TestFieldRangeCompute()
|
||||
TryRangeComputeDS<vtkm::Int32>(-1024, 1024);
|
||||
TryRangeComputeDS<vtkm::Vec3f_32>(vtkm::make_Vec(1024, 0, -1024),
|
||||
vtkm::make_Vec(2048, 2048, 2048));
|
||||
TryRangeComputeMB<vtkm::Float64>(0, 1000);
|
||||
TryRangeComputeMB<vtkm::Int32>(-1024, 1024);
|
||||
TryRangeComputeMB<vtkm::Vec3f_32>(vtkm::make_Vec(1024, 0, -1024),
|
||||
vtkm::make_Vec(2048, 2048, 2048));
|
||||
TryRangeComputePDS<vtkm::Float64>(0, 1000);
|
||||
TryRangeComputePDS<vtkm::Int32>(-1024, 1024);
|
||||
TryRangeComputePDS<vtkm::Vec3f_32>(vtkm::make_Vec(1024, 0, -1024),
|
||||
vtkm::make_Vec(2048, 2048, 2048));
|
||||
};
|
||||
|
||||
int UnitTestFieldRangeCompute(int argc, char* argv[])
|
||||
|
@ -162,12 +162,12 @@ void TryRangeGlobalComputeDS(const ValueType& min, const ValueType& max)
|
||||
}
|
||||
|
||||
template <typename ValueType>
|
||||
void TryRangeGlobalComputeMB(const ValueType& min, const ValueType& max)
|
||||
void TryRangeGlobalComputePDS(const ValueType& min, const ValueType& max)
|
||||
{
|
||||
vtkmdiy::mpi::communicator comm = vtkm::cont::EnvironmentTracker::GetCommunicator();
|
||||
PRINT_INFO("Trying type (multiblock): " << vtkm::testing::TypeName<ValueType>::Name());
|
||||
PRINT_INFO("Trying type (PartitionedDataSet): " << vtkm::testing::TypeName<ValueType>::Name());
|
||||
|
||||
vtkm::cont::MultiBlock mb;
|
||||
vtkm::cont::PartitionedDataSet mb;
|
||||
for (int cc = 0; cc < 5; cc++)
|
||||
{
|
||||
// let's create a dummy dataset with a bunch of fields.
|
||||
@ -176,7 +176,7 @@ void TryRangeGlobalComputeMB(const ValueType& min, const ValueType& max)
|
||||
dataset,
|
||||
"pointvar",
|
||||
CreateArray(min, max, ARRAY_SIZE, typename vtkm::TypeTraits<ValueType>::DimensionalityTag()));
|
||||
mb.AddBlock(dataset);
|
||||
mb.AppendPartition(dataset);
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Range> ranges = vtkm::cont::FieldRangeGlobalCompute(mb, "pointvar");
|
||||
@ -195,10 +195,10 @@ static void TestFieldRangeGlobalCompute()
|
||||
TryRangeGlobalComputeDS<vtkm::Int32>(-1024, 1024);
|
||||
TryRangeGlobalComputeDS<vtkm::Vec3f_32>(vtkm::make_Vec(1024, 0, -1024),
|
||||
vtkm::make_Vec(2048, 2048, 2048));
|
||||
TryRangeGlobalComputeMB<vtkm::Float64>(0, 1000);
|
||||
TryRangeGlobalComputeMB<vtkm::Int32>(-1024, 1024);
|
||||
TryRangeGlobalComputeMB<vtkm::Vec3f_32>(vtkm::make_Vec(1024, 0, -1024),
|
||||
vtkm::make_Vec(2048, 2048, 2048));
|
||||
TryRangeGlobalComputePDS<vtkm::Float64>(0, 1000);
|
||||
TryRangeGlobalComputePDS<vtkm::Int32>(-1024, 1024);
|
||||
TryRangeGlobalComputePDS<vtkm::Vec3f_32>(vtkm::make_Vec(1024, 0, -1024),
|
||||
vtkm::make_Vec(2048, 2048, 2048));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/DataSetFieldAdd.h>
|
||||
#include <vtkm/cont/FieldRangeCompute.h>
|
||||
#include <vtkm/cont/MultiBlock.h>
|
||||
#include <vtkm/cont/PartitionedDataSet.h>
|
||||
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
@ -28,26 +28,26 @@
|
||||
#include <vtkm/thirdparty/diy/diy.h>
|
||||
|
||||
void DataSet_Compare(vtkm::cont::DataSet& LeftDateSet, vtkm::cont::DataSet& RightDateSet);
|
||||
static void MultiBlockTest()
|
||||
static void PartitionedDataSetTest()
|
||||
{
|
||||
vtkm::cont::testing::MakeTestDataSet testDataSet;
|
||||
vtkm::cont::MultiBlock multiblock;
|
||||
vtkm::cont::PartitionedDataSet pds;
|
||||
|
||||
vtkm::cont::DataSet TDset1 = testDataSet.Make2DUniformDataSet0();
|
||||
vtkm::cont::DataSet TDset2 = testDataSet.Make3DUniformDataSet0();
|
||||
|
||||
multiblock.AddBlock(TDset1);
|
||||
multiblock.AddBlock(TDset2);
|
||||
pds.AppendPartition(TDset1);
|
||||
pds.AppendPartition(TDset2);
|
||||
|
||||
VTKM_TEST_ASSERT(multiblock.GetNumberOfBlocks() == 2, "Incorrect number of blocks");
|
||||
VTKM_TEST_ASSERT(pds.GetNumberOfPartitions() == 2, "Incorrect number of partitions");
|
||||
|
||||
vtkm::cont::DataSet TestDSet = multiblock.GetBlock(0);
|
||||
vtkm::cont::DataSet TestDSet = pds.GetPartition(0);
|
||||
VTKM_TEST_ASSERT(TDset1.GetNumberOfFields() == TestDSet.GetNumberOfFields(),
|
||||
"Incorrect number of fields");
|
||||
VTKM_TEST_ASSERT(TDset1.GetNumberOfCoordinateSystems() == TestDSet.GetNumberOfCoordinateSystems(),
|
||||
"Incorrect number of coordinate systems");
|
||||
|
||||
TestDSet = multiblock.GetBlock(1);
|
||||
TestDSet = pds.GetPartition(1);
|
||||
VTKM_TEST_ASSERT(TDset2.GetNumberOfFields() == TestDSet.GetNumberOfFields(),
|
||||
"Incorrect number of fields");
|
||||
VTKM_TEST_ASSERT(TDset2.GetNumberOfCoordinateSystems() == TestDSet.GetNumberOfCoordinateSystems(),
|
||||
@ -59,11 +59,10 @@ static void MultiBlockTest()
|
||||
GlobalBound.Include(Set1Bounds);
|
||||
GlobalBound.Include(Set2Bounds);
|
||||
|
||||
VTKM_TEST_ASSERT(vtkm::cont::BoundsCompute(multiblock) == GlobalBound,
|
||||
"Global bounds info incorrect");
|
||||
VTKM_TEST_ASSERT(vtkm::cont::BoundsCompute(multiblock.GetBlock(0)) == Set1Bounds,
|
||||
VTKM_TEST_ASSERT(vtkm::cont::BoundsCompute(pds) == GlobalBound, "Global bounds info incorrect");
|
||||
VTKM_TEST_ASSERT(vtkm::cont::BoundsCompute(pds.GetPartition(0)) == Set1Bounds,
|
||||
"Local bounds info incorrect");
|
||||
VTKM_TEST_ASSERT(vtkm::cont::BoundsCompute(multiblock.GetBlock(1)) == Set2Bounds,
|
||||
VTKM_TEST_ASSERT(vtkm::cont::BoundsCompute(pds.GetPartition(1)) == Set2Bounds,
|
||||
"Local bounds info incorrect");
|
||||
|
||||
vtkm::Range Set1Field1Range;
|
||||
@ -84,59 +83,59 @@ static void MultiBlockTest()
|
||||
Field2GlobeRange.Include(Set2Field2Range);
|
||||
|
||||
using vtkm::cont::FieldRangeCompute;
|
||||
VTKM_TEST_ASSERT(FieldRangeCompute(multiblock, "pointvar").GetPortalConstControl().Get(0) ==
|
||||
VTKM_TEST_ASSERT(FieldRangeCompute(pds, "pointvar").GetPortalConstControl().Get(0) ==
|
||||
Field1GlobeRange,
|
||||
"Local field value range info incorrect");
|
||||
VTKM_TEST_ASSERT(FieldRangeCompute(multiblock, "cellvar").GetPortalConstControl().Get(0) ==
|
||||
VTKM_TEST_ASSERT(FieldRangeCompute(pds, "cellvar").GetPortalConstControl().Get(0) ==
|
||||
Field2GlobeRange,
|
||||
"Local field value range info incorrect");
|
||||
|
||||
vtkm::Range SourceRange; //test the validity of member function GetField(FieldName, BlockId)
|
||||
multiblock.GetField("cellvar", 0).GetRange(&SourceRange);
|
||||
pds.GetField("cellvar", 0).GetRange(&SourceRange);
|
||||
vtkm::Range TestRange;
|
||||
multiblock.GetBlock(0).GetField("cellvar").GetRange(&TestRange);
|
||||
pds.GetPartition(0).GetField("cellvar").GetRange(&TestRange);
|
||||
VTKM_TEST_ASSERT(TestRange == SourceRange, "Local field value info incorrect");
|
||||
|
||||
vtkm::cont::MultiBlock testblocks1;
|
||||
std::vector<vtkm::cont::DataSet> blocks = multiblock.GetBlocks();
|
||||
testblocks1.AddBlocks(blocks);
|
||||
VTKM_TEST_ASSERT(multiblock.GetNumberOfBlocks() == testblocks1.GetNumberOfBlocks(),
|
||||
"inconsistent number of blocks");
|
||||
vtkm::cont::PartitionedDataSet testblocks1;
|
||||
std::vector<vtkm::cont::DataSet> partitions = pds.GetPartitions();
|
||||
testblocks1.AppendPartitions(partitions);
|
||||
VTKM_TEST_ASSERT(pds.GetNumberOfPartitions() == testblocks1.GetNumberOfPartitions(),
|
||||
"inconsistent number of partitions");
|
||||
|
||||
vtkm::cont::MultiBlock testblocks2(2);
|
||||
testblocks2.InsertBlock(0, TDset1);
|
||||
testblocks2.InsertBlock(1, TDset2);
|
||||
vtkm::cont::PartitionedDataSet testblocks2(2);
|
||||
testblocks2.InsertPartition(0, TDset1);
|
||||
testblocks2.InsertPartition(1, TDset2);
|
||||
|
||||
TestDSet = testblocks2.GetBlock(0);
|
||||
TestDSet = testblocks2.GetPartition(0);
|
||||
DataSet_Compare(TDset1, TestDSet);
|
||||
|
||||
TestDSet = testblocks2.GetBlock(1);
|
||||
TestDSet = testblocks2.GetPartition(1);
|
||||
DataSet_Compare(TDset2, TestDSet);
|
||||
|
||||
testblocks2.ReplaceBlock(0, TDset2);
|
||||
testblocks2.ReplaceBlock(1, TDset1);
|
||||
testblocks2.ReplacePartition(0, TDset2);
|
||||
testblocks2.ReplacePartition(1, TDset1);
|
||||
|
||||
TestDSet = testblocks2.GetBlock(0);
|
||||
TestDSet = testblocks2.GetPartition(0);
|
||||
DataSet_Compare(TDset2, TestDSet);
|
||||
|
||||
TestDSet = testblocks2.GetBlock(1);
|
||||
TestDSet = testblocks2.GetPartition(1);
|
||||
DataSet_Compare(TDset1, TestDSet);
|
||||
}
|
||||
|
||||
void DataSet_Compare(vtkm::cont::DataSet& LeftDateSet, vtkm::cont::DataSet& RightDateSet)
|
||||
void DataSet_Compare(vtkm::cont::DataSet& leftDataSet, vtkm::cont::DataSet& rightDataSet)
|
||||
{
|
||||
for (vtkm::Id j = 0; j < LeftDateSet.GetNumberOfFields(); j++)
|
||||
for (vtkm::Id j = 0; j < leftDataSet.GetNumberOfFields(); j++)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> LDataArray;
|
||||
LeftDateSet.GetField(j).GetData().CopyTo(LDataArray);
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> RDataArray;
|
||||
RightDateSet.GetField(j).GetData().CopyTo(RDataArray);
|
||||
VTKM_TEST_ASSERT(LDataArray == RDataArray, "field value info incorrect");
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> lDataArray;
|
||||
leftDataSet.GetField(j).GetData().CopyTo(lDataArray);
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> rDataArray;
|
||||
rightDataSet.GetField(j).GetData().CopyTo(rDataArray);
|
||||
VTKM_TEST_ASSERT(lDataArray == rDataArray, "field value info incorrect");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int UnitTestMultiBlock(int argc, char* argv[])
|
||||
int UnitTestPartitionedDataSet(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(MultiBlockTest, argc, argv);
|
||||
return vtkm::cont::testing::Testing::Run(PartitionedDataSetTest, argc, argv);
|
||||
}
|
@ -14,7 +14,7 @@
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/Field.h>
|
||||
#include <vtkm/cont/Invoker.h>
|
||||
#include <vtkm/cont/MultiBlock.h>
|
||||
#include <vtkm/cont/PartitionedDataSet.h>
|
||||
|
||||
#include <vtkm/filter/CreateResult.h>
|
||||
#include <vtkm/filter/FieldSelection.h>
|
||||
@ -50,21 +50,22 @@ namespace filter
|
||||
/// vtkm::cont::DataSet dsInput = ...
|
||||
/// auto outputDS = filter.Execute(dsInput);
|
||||
///
|
||||
/// // or, execute on a vtkm::cont::MultiBlock
|
||||
/// vtkm::cont::MultiBlock mbInput = ...
|
||||
/// // or, execute on a vtkm::cont::PartitionedDataSet
|
||||
/// vtkm::cont::PartitionedDataSet mbInput = ...
|
||||
/// auto outputMB = filter.Execute(mbInput);
|
||||
/// \endcode
|
||||
///
|
||||
/// `Execute` methods take in the input dataset or multiblock to process and
|
||||
/// return the result. The type of the result is same as the input type, thus
|
||||
/// `Execute(DataSet&)` returns a DataSet while `Execute(MultiBlock&)` returns a
|
||||
/// MultiBlock.
|
||||
/// `Execute` methods take in the input DataSet or PartitionedDataSet to
|
||||
/// process and return the result. The type of the result is same as the input
|
||||
/// type, thus `Execute(DataSet&)` returns a DataSet while
|
||||
/// `Execute(PartitionedDataSet&)` returns a PartitionedDataSet.
|
||||
///
|
||||
/// The implementation for `Execute(DataSet&)` is merely provided for
|
||||
/// convenience. Internally, it creates MultiBlock with a single block for the
|
||||
/// input and then forwards the call to `Execute(MultiBlock&)`. The method
|
||||
/// returns the first block, if any, from the MultiBlock returned by the
|
||||
/// forwarded call. If the MultiBlock returned has more than 1 block, then
|
||||
/// convenience. Internally, it creates a PartitionedDataSet with a single
|
||||
/// partition for the input and then forwards the call to
|
||||
/// `Execute(PartitionedDataSet&)`. The method returns the first partition, if
|
||||
/// any, from the PartitionedDataSet returned by the forwarded call. If the
|
||||
/// PartitionedDataSet returned has more than 1 partition, then
|
||||
/// `vtkm::cont::ErrorFilterExecution` will be thrown.
|
||||
///
|
||||
/// \section FilterSubclassing Subclassing
|
||||
@ -83,22 +84,22 @@ namespace filter
|
||||
/// \code{cpp}
|
||||
///
|
||||
/// template <typename DerivedPolicy>
|
||||
/// void PreExecute(const vtkm::cont::MultiBlock& input,
|
||||
/// void PreExecute(const vtkm::cont::PartitionedDataSet& input,
|
||||
/// const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
|
||||
///
|
||||
/// template <typename DerivedPolicy>
|
||||
/// void PostExecute(const vtkm::cont::MultiBlock& input, vtkm::cont::MultiBlock& output
|
||||
/// void PostExecute(const vtkm::cont::PartitionedDataSet& input, vtkm::cont::PartitionedDataSet& output
|
||||
/// const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
|
||||
///
|
||||
/// \endcode
|
||||
///
|
||||
/// As the name suggests, these are called and the beginning and before the end
|
||||
/// of an `Filter::Execute` call. Most filters that don't need to handle
|
||||
/// multiblock datasets specially, e.g. clip, cut, iso-contour, need not worry
|
||||
/// PartitionedDataSet specially, e.g. clip, cut, iso-contour, need not worry
|
||||
/// about these methods or provide any implementation. If, however, your filter
|
||||
/// needs do to some initialization e.g. allocation buffers to accumulate
|
||||
/// results, or finalization e.g. reduce results across all blocks, then these
|
||||
/// methods provide convenient hooks for the same.
|
||||
/// results, or finalization e.g. reduce results across all partitions, then
|
||||
/// these methods provide convenient hooks for the same.
|
||||
///
|
||||
/// \subsection FilterPrepareForExecution PrepareForExecution
|
||||
///
|
||||
@ -108,11 +109,11 @@ namespace filter
|
||||
/// available; which one to implement depends on the nature of the filter.
|
||||
///
|
||||
/// Let's consider simple filters that do not need to do anything special to
|
||||
/// handle multiblock datasets e.g. clip, contour, etc. These are the filters
|
||||
/// where executing the filter on a MultiBlock simply means executing the filter
|
||||
/// on one block at a time and packing the output for each iteration info the
|
||||
/// result MultiBlock. For such filters, one must implement the following
|
||||
/// signature.
|
||||
/// handle PartitionedDataSet e.g. clip, contour, etc. These are the filters
|
||||
/// where executing the filter on a PartitionedDataSet simply means executing
|
||||
/// the filter on one partition at a time and packing the output for each
|
||||
/// iteration info the result PartitionedDataSet. For such filters, one must
|
||||
/// implement the following signature.
|
||||
///
|
||||
/// \code{cpp}
|
||||
///
|
||||
@ -127,21 +128,22 @@ namespace filter
|
||||
/// result and return it. If there are any errors, the subclass must throw an
|
||||
/// exception (e.g. `vtkm::cont::ErrorFilterExecution`).
|
||||
///
|
||||
/// In this case, the Filter superclass handles iterating over multiple blocks
|
||||
/// in the input MultiBlock and calling `PrepareForExecution` iteratively.
|
||||
/// In this case, the Filter superclass handles iterating over multiple
|
||||
/// partitions in the input PartitionedDataSet and calling
|
||||
/// `PrepareForExecution` iteratively.
|
||||
///
|
||||
/// The aforementioned approach is also suitable for filters that need special
|
||||
/// handling for multiblock datasets which can be modelled as PreExecute and
|
||||
/// handling for PartitionedDataSets which can be modelled as PreExecute and
|
||||
/// PostExecute steps (e.g. `vtkm::filter::Histogram`).
|
||||
///
|
||||
/// For more complex filters, like streamlines, particle tracking, where the
|
||||
/// processing of multiblock datasets cannot be modelled as a reduction of the
|
||||
/// processing of PartitionedDataSets cannot be modelled as a reduction of the
|
||||
/// results, one can implement the following signature.
|
||||
///
|
||||
/// \code{cpp}
|
||||
/// template <typename DerivedPolicy>
|
||||
/// vtkm::cont::MultiBlock PrepareForExecution(
|
||||
/// const vtkm::cont::MultiBlock& input,
|
||||
/// vtkm::cont::PartitionedDataSet PrepareForExecution(
|
||||
/// const vtkm::cont::PartitionedDataSet& input,
|
||||
/// const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
|
||||
/// \endcode
|
||||
///
|
||||
@ -163,8 +165,9 @@ namespace filter
|
||||
///
|
||||
/// \endcode
|
||||
///
|
||||
/// When present, this method will be called after each block execution to map
|
||||
/// an input field from the corresponding input block to the output block.
|
||||
/// When present, this method will be called after each partition execution to
|
||||
/// map an input field from the corresponding input partition to the output
|
||||
/// partition.
|
||||
///
|
||||
template <typename Derived>
|
||||
class Filter
|
||||
@ -235,14 +238,15 @@ public:
|
||||
//@}
|
||||
|
||||
//@{
|
||||
/// Executes the filter on the input MultiBlock and produces a result MultiBlock.
|
||||
/// Executes the filter on the input PartitionedDataSet and produces a result PartitionedDataSet.
|
||||
///
|
||||
/// On success, this the dataset produced. On error, vtkm::cont::ErrorExecution will be thrown.
|
||||
VTKM_CONT vtkm::cont::MultiBlock Execute(const vtkm::cont::MultiBlock& input);
|
||||
VTKM_CONT vtkm::cont::PartitionedDataSet Execute(const vtkm::cont::PartitionedDataSet& input);
|
||||
|
||||
template <typename DerivedPolicy>
|
||||
VTKM_CONT vtkm::cont::MultiBlock Execute(const vtkm::cont::MultiBlock& input,
|
||||
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
|
||||
VTKM_CONT vtkm::cont::PartitionedDataSet Execute(
|
||||
const vtkm::cont::PartitionedDataSet& input,
|
||||
const vtkm::filter::PolicyBase<DerivedPolicy>& policy);
|
||||
//@}
|
||||
|
||||
/// Map fields from input dataset to output.
|
||||
|
@ -171,22 +171,22 @@ InputType CallPrepareForExecutionInternal(std::true_type,
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// specialization for MultiBlock input when `PrepareForExecution` is not provided
|
||||
// specialization for PartitionedDataSet input when `PrepareForExecution` is not provided
|
||||
// by the subclass. we iterate over blocks and execute for each block
|
||||
// individually.
|
||||
template <typename Derived, typename DerivedPolicy>
|
||||
vtkm::cont::MultiBlock CallPrepareForExecutionInternal(
|
||||
vtkm::cont::PartitionedDataSet CallPrepareForExecutionInternal(
|
||||
std::false_type,
|
||||
Derived* self,
|
||||
const vtkm::cont::MultiBlock& input,
|
||||
const vtkm::cont::PartitionedDataSet& input,
|
||||
const vtkm::filter::PolicyBase<DerivedPolicy>& policy)
|
||||
{
|
||||
vtkm::cont::MultiBlock output;
|
||||
vtkm::cont::PartitionedDataSet output;
|
||||
for (const auto& inBlock : input)
|
||||
{
|
||||
vtkm::cont::DataSet outBlock = CallPrepareForExecution(self, inBlock, policy);
|
||||
CallMapFieldOntoOutput(self, inBlock, outBlock, policy);
|
||||
output.AddBlock(outBlock);
|
||||
output.AppendPartition(outBlock);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@ -254,8 +254,8 @@ inline VTKM_CONT vtkm::cont::DataSet Filter<Derived>::Execute(const vtkm::cont::
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Derived>
|
||||
inline VTKM_CONT vtkm::cont::MultiBlock Filter<Derived>::Execute(
|
||||
const vtkm::cont::MultiBlock& input)
|
||||
inline VTKM_CONT vtkm::cont::PartitionedDataSet Filter<Derived>::Execute(
|
||||
const vtkm::cont::PartitionedDataSet& input)
|
||||
{
|
||||
return this->Execute(input, vtkm::filter::PolicyDefault());
|
||||
}
|
||||
@ -272,23 +272,24 @@ inline VTKM_CONT vtkm::cont::DataSet Filter<Derived>::Execute(
|
||||
vtkm::cont::LogLevel::Perf, "Filter: '%s'", vtkm::cont::TypeToString<Derived>().c_str());
|
||||
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
vtkm::cont::MultiBlock output = self->Execute(vtkm::cont::MultiBlock(input), policy);
|
||||
if (output.GetNumberOfBlocks() > 1)
|
||||
vtkm::cont::PartitionedDataSet output =
|
||||
self->Execute(vtkm::cont::PartitionedDataSet(input), policy);
|
||||
if (output.GetNumberOfPartitions() > 1)
|
||||
{
|
||||
throw vtkm::cont::ErrorFilterExecution("Expecting at most 1 block.");
|
||||
}
|
||||
return output.GetNumberOfBlocks() == 1 ? output.GetBlock(0) : vtkm::cont::DataSet();
|
||||
return output.GetNumberOfPartitions() == 1 ? output.GetPartition(0) : vtkm::cont::DataSet();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template <typename Derived>
|
||||
template <typename DerivedPolicy>
|
||||
inline VTKM_CONT vtkm::cont::MultiBlock Filter<Derived>::Execute(
|
||||
const vtkm::cont::MultiBlock& input,
|
||||
inline VTKM_CONT vtkm::cont::PartitionedDataSet Filter<Derived>::Execute(
|
||||
const vtkm::cont::PartitionedDataSet& input,
|
||||
const vtkm::filter::PolicyBase<DerivedPolicy>& policy)
|
||||
{
|
||||
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf,
|
||||
"Filter (MultiBlock): '%s'",
|
||||
"Filter (PartitionedDataSet): '%s'",
|
||||
vtkm::cont::TypeToString<Derived>().c_str());
|
||||
|
||||
Derived* self = static_cast<Derived*>(this);
|
||||
@ -297,7 +298,7 @@ inline VTKM_CONT vtkm::cont::MultiBlock Filter<Derived>::Execute(
|
||||
internal::CallPreExecute(self, input, policy);
|
||||
|
||||
// Call `PrepareForExecution` (which should probably be renamed at some point)
|
||||
vtkm::cont::MultiBlock output = internal::CallPrepareForExecution(self, input, policy);
|
||||
vtkm::cont::PartitionedDataSet output = internal::CallPrepareForExecution(self, input, policy);
|
||||
|
||||
// Call `Derived::PostExecute<DerivedPolicy>(input, output, policy)` if defined.
|
||||
internal::CallPostExecute(self, input, output, policy);
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/DynamicCellSet.h>
|
||||
#include <vtkm/cont/Field.h>
|
||||
#include <vtkm/cont/MultiBlock.h>
|
||||
#include <vtkm/cont/PartitionedDataSet.h>
|
||||
|
||||
#include <vtkm/filter/Filter.h>
|
||||
#include <vtkm/filter/PolicyBase.h>
|
||||
|
@ -15,7 +15,7 @@
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/DynamicCellSet.h>
|
||||
#include <vtkm/cont/Field.h>
|
||||
#include <vtkm/cont/MultiBlock.h>
|
||||
#include <vtkm/cont/PartitionedDataSet.h>
|
||||
|
||||
#include <vtkm/filter/Filter.h>
|
||||
#include <vtkm/filter/PolicyBase.h>
|
||||
|
@ -14,7 +14,7 @@
|
||||
#include <vtkm/cont/CoordinateSystem.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/Field.h>
|
||||
#include <vtkm/cont/MultiBlock.h>
|
||||
#include <vtkm/cont/PartitionedDataSet.h>
|
||||
|
||||
#include <vtkm/filter/Filter.h>
|
||||
#include <vtkm/filter/PolicyBase.h>
|
||||
|
@ -65,16 +65,16 @@ public:
|
||||
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/ArrayCopy.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>
|
||||
@ -105,7 +105,7 @@ public:
|
||||
[]() -> void* { return new vtkm::cont::ArrayHandle<vtkm::Id>(); },
|
||||
[](void* ptr) { delete static_cast<vtkm::cont::ArrayHandle<vtkm::Id>*>(ptr); });
|
||||
|
||||
vtkm::cont::AssignerMultiBlock assigner(numLocalBlocks);
|
||||
vtkm::cont::AssignerPartitionedDataSet assigner(numLocalBlocks);
|
||||
vtkmdiy::RegularDecomposer<vtkmdiy::DiscreteBounds> decomposer(
|
||||
/*dims*/ 1, vtkmdiy::interval(0, assigner.nblocks() - 1), assigner.nblocks());
|
||||
decomposer.decompose(comm.rank(), assigner, master);
|
||||
@ -206,7 +206,7 @@ inline VTKM_CONT vtkm::cont::DataSet Histogram::DoExecute(
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename DerivedPolicy>
|
||||
inline VTKM_CONT void Histogram::PreExecute(const vtkm::cont::MultiBlock& input,
|
||||
inline VTKM_CONT void Histogram::PreExecute(const vtkm::cont::PartitionedDataSet& input,
|
||||
const vtkm::filter::PolicyBase<DerivedPolicy>&)
|
||||
{
|
||||
using TypeList = typename DerivedPolicy::FieldTypeList;
|
||||
@ -228,15 +228,15 @@ inline VTKM_CONT void Histogram::PreExecute(const vtkm::cont::MultiBlock& input,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
template <typename DerivedPolicy>
|
||||
inline VTKM_CONT void Histogram::PostExecute(const vtkm::cont::MultiBlock&,
|
||||
vtkm::cont::MultiBlock& result,
|
||||
inline VTKM_CONT void Histogram::PostExecute(const vtkm::cont::PartitionedDataSet&,
|
||||
vtkm::cont::PartitionedDataSet& result,
|
||||
const vtkm::filter::PolicyBase<DerivedPolicy>&)
|
||||
{
|
||||
// iterate and compute histogram 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()));
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ inline VTKM_CONT void Histogram::PostExecute(const vtkm::cont::MultiBlock&,
|
||||
this->GetOutputFieldName(), vtkm::cont::Field::Association::WHOLE_MESH, helper.ReduceAll());
|
||||
output.AddField(rfield);
|
||||
|
||||
result = vtkm::cont::MultiBlock(output);
|
||||
result = vtkm::cont::PartitionedDataSet(output);
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::filter
|
||||
|
@ -39,10 +39,10 @@ set(unit_tests
|
||||
UnitTestMaskFilter.cxx
|
||||
UnitTestMaskPointsFilter.cxx
|
||||
UnitTestMeshQualityFilter.cxx
|
||||
UnitTestMultiBlockFilters.cxx
|
||||
UnitTestMultiBlockHistogramFilter.cxx
|
||||
UnitTestNDEntropyFilter.cxx
|
||||
UnitTestNDHistogramFilter.cxx
|
||||
UnitTestPartitionedDataSetFilters.cxx
|
||||
UnitTestPartitionedDataSetHistogramFilter.cxx
|
||||
UnitTestPointAverageFilter.cxx
|
||||
UnitTestPointElevationFilter.cxx
|
||||
UnitTestPointTransform.cxx
|
||||
|
@ -1,124 +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/CellShape.h>
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/CellSetStructured.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/DataSetFieldAdd.h>
|
||||
|
||||
#include <vtkm/cont/MultiBlock.h>
|
||||
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
|
||||
#include <vtkm/exec/ConnectivityStructured.h>
|
||||
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/filter/CellAverage.h>
|
||||
|
||||
|
||||
template <typename T>
|
||||
vtkm::cont::MultiBlock MultiBlockBuilder(std::size_t BlockNum, std::string FieldName)
|
||||
{
|
||||
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
|
||||
vtkm::cont::DataSet dataSet;
|
||||
vtkm::cont::DataSetFieldAdd dsf;
|
||||
|
||||
vtkm::Vec<T, 2> origin(0);
|
||||
vtkm::Vec<T, 2> spacing(1);
|
||||
vtkm::cont::MultiBlock Blocks;
|
||||
for (vtkm::Id BlockId = 0; BlockId < static_cast<vtkm::Id>(BlockNum); BlockId++)
|
||||
{
|
||||
vtkm::Id2 dimensions((BlockId + 2) * (BlockId + 2), (BlockId + 2) * (BlockId + 2));
|
||||
|
||||
if (FieldName == "cellvar")
|
||||
{
|
||||
vtkm::Id numCells = (dimensions[0] - 1) * (dimensions[1] - 1);
|
||||
|
||||
std::vector<T> varC2D(static_cast<std::size_t>(numCells));
|
||||
for (vtkm::Id i = 0; i < numCells; i++)
|
||||
{
|
||||
varC2D[static_cast<std::size_t>(i)] = static_cast<T>(BlockId * i);
|
||||
}
|
||||
dataSet = dataSetBuilder.Create(vtkm::Id2(dimensions[0], dimensions[1]),
|
||||
vtkm::Vec<T, 2>(origin[0], origin[1]),
|
||||
vtkm::Vec<T, 2>(spacing[0], spacing[1]));
|
||||
dsf.AddCellField(dataSet, "cellvar", varC2D);
|
||||
}
|
||||
|
||||
if (FieldName == "pointvar")
|
||||
{
|
||||
vtkm::Id numPoints = dimensions[0] * dimensions[1];
|
||||
std::vector<T> varP2D(static_cast<std::size_t>(numPoints));
|
||||
for (vtkm::Id i = 0; i < numPoints; i++)
|
||||
{
|
||||
varP2D[static_cast<std::size_t>(i)] = static_cast<T>(BlockId);
|
||||
}
|
||||
dataSet = dataSetBuilder.Create(vtkm::Id2(dimensions[0], dimensions[1]),
|
||||
vtkm::Vec<T, 2>(origin[0], origin[1]),
|
||||
vtkm::Vec<T, 2>(spacing[0], spacing[1]));
|
||||
dsf.AddPointField(dataSet, "pointvar", varP2D);
|
||||
}
|
||||
|
||||
Blocks.AddBlock(dataSet);
|
||||
}
|
||||
return Blocks;
|
||||
}
|
||||
template <typename D>
|
||||
void Result_Verify(const vtkm::cont::MultiBlock& Result,
|
||||
D& Filter,
|
||||
const vtkm::cont::MultiBlock& Blocks,
|
||||
std::string FieldName)
|
||||
{
|
||||
VTKM_TEST_ASSERT(Result.GetNumberOfBlocks() == Blocks.GetNumberOfBlocks(),
|
||||
"result block number incorrect");
|
||||
const std::string outputFieldName = Filter.GetOutputFieldName();
|
||||
for (vtkm::Id j = 0; j < Result.GetNumberOfBlocks(); j++)
|
||||
{
|
||||
Filter.SetActiveField(FieldName);
|
||||
vtkm::cont::DataSet BlockResult = Filter.Execute(Blocks.GetBlock(j));
|
||||
|
||||
VTKM_TEST_ASSERT(Result.GetBlock(j).GetField(outputFieldName).GetNumberOfValues() ==
|
||||
BlockResult.GetField(outputFieldName).GetNumberOfValues(),
|
||||
"result vectors' size incorrect");
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> MBlockArray;
|
||||
Result.GetBlock(j).GetField(outputFieldName).GetData().CopyTo(MBlockArray);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> SDataSetArray;
|
||||
BlockResult.GetField(outputFieldName).GetData().CopyTo(SDataSetArray);
|
||||
|
||||
for (vtkm::Id i = 0; i < Result.GetBlock(j).GetField(outputFieldName).GetNumberOfValues(); i++)
|
||||
{
|
||||
VTKM_TEST_ASSERT(MBlockArray.GetPortalConstControl().Get(i) ==
|
||||
SDataSetArray.GetPortalConstControl().Get(i),
|
||||
"result values incorrect");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void TestMultiBlockFilters()
|
||||
{
|
||||
std::size_t BlockNum = 7;
|
||||
vtkm::cont::MultiBlock result;
|
||||
vtkm::cont::MultiBlock Blocks;
|
||||
|
||||
Blocks = MultiBlockBuilder<vtkm::Id>(BlockNum, "pointvar");
|
||||
vtkm::filter::CellAverage cellAverage;
|
||||
cellAverage.SetOutputFieldName("average");
|
||||
cellAverage.SetActiveField("pointvar");
|
||||
result = cellAverage.Execute(Blocks);
|
||||
Result_Verify(result, cellAverage, Blocks, std::string("pointvar"));
|
||||
}
|
||||
|
||||
int UnitTestMultiBlockFilters(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestMultiBlockFilters, argc, argv);
|
||||
}
|
126
vtkm/filter/testing/UnitTestPartitionedDataSetFilters.cxx
Normal file
126
vtkm/filter/testing/UnitTestPartitionedDataSetFilters.cxx
Normal file
@ -0,0 +1,126 @@
|
||||
//============================================================================
|
||||
// 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/CellShape.h>
|
||||
#include <vtkm/VectorAnalysis.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/CellSetStructured.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/DataSetFieldAdd.h>
|
||||
|
||||
#include <vtkm/cont/PartitionedDataSet.h>
|
||||
#include <vtkm/cont/serial/DeviceAdapterSerial.h>
|
||||
#include <vtkm/exec/ConnectivityStructured.h>
|
||||
|
||||
#include <vtkm/cont/testing/MakeTestDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
#include <vtkm/filter/CellAverage.h>
|
||||
|
||||
|
||||
template <typename T>
|
||||
vtkm::cont::PartitionedDataSet PartitionedDataSetBuilder(std::size_t partitionNum,
|
||||
std::string fieldName)
|
||||
{
|
||||
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
|
||||
vtkm::cont::DataSet dataSet;
|
||||
vtkm::cont::DataSetFieldAdd dsf;
|
||||
|
||||
vtkm::Vec<T, 2> origin(0);
|
||||
vtkm::Vec<T, 2> spacing(1);
|
||||
vtkm::cont::PartitionedDataSet partitions;
|
||||
for (vtkm::Id partId = 0; partId < static_cast<vtkm::Id>(partitionNum); partId++)
|
||||
{
|
||||
vtkm::Id2 dimensions((partId + 2) * (partId + 2), (partId + 2) * (partId + 2));
|
||||
|
||||
if (fieldName == "cellvar")
|
||||
{
|
||||
vtkm::Id numCells = (dimensions[0] - 1) * (dimensions[1] - 1);
|
||||
|
||||
std::vector<T> varC2D(static_cast<std::size_t>(numCells));
|
||||
for (vtkm::Id i = 0; i < numCells; i++)
|
||||
{
|
||||
varC2D[static_cast<std::size_t>(i)] = static_cast<T>(partId * i);
|
||||
}
|
||||
dataSet = dataSetBuilder.Create(vtkm::Id2(dimensions[0], dimensions[1]),
|
||||
vtkm::Vec<T, 2>(origin[0], origin[1]),
|
||||
vtkm::Vec<T, 2>(spacing[0], spacing[1]));
|
||||
dsf.AddCellField(dataSet, "cellvar", varC2D);
|
||||
}
|
||||
|
||||
if (fieldName == "pointvar")
|
||||
{
|
||||
vtkm::Id numPoints = dimensions[0] * dimensions[1];
|
||||
std::vector<T> varP2D(static_cast<std::size_t>(numPoints));
|
||||
for (vtkm::Id i = 0; i < numPoints; i++)
|
||||
{
|
||||
varP2D[static_cast<std::size_t>(i)] = static_cast<T>(partId);
|
||||
}
|
||||
dataSet = dataSetBuilder.Create(vtkm::Id2(dimensions[0], dimensions[1]),
|
||||
vtkm::Vec<T, 2>(origin[0], origin[1]),
|
||||
vtkm::Vec<T, 2>(spacing[0], spacing[1]));
|
||||
dsf.AddPointField(dataSet, "pointvar", varP2D);
|
||||
}
|
||||
|
||||
partitions.AppendPartition(dataSet);
|
||||
}
|
||||
return partitions;
|
||||
}
|
||||
template <typename D>
|
||||
void Result_Verify(const vtkm::cont::PartitionedDataSet& result,
|
||||
D& filter,
|
||||
const vtkm::cont::PartitionedDataSet& partitions,
|
||||
std::string fieldName)
|
||||
{
|
||||
VTKM_TEST_ASSERT(result.GetNumberOfPartitions() == partitions.GetNumberOfPartitions(),
|
||||
"result partition number incorrect");
|
||||
const std::string outputFieldName = filter.GetOutputFieldName();
|
||||
for (vtkm::Id j = 0; j < result.GetNumberOfPartitions(); j++)
|
||||
{
|
||||
filter.SetActiveField(fieldName);
|
||||
vtkm::cont::DataSet partitionResult = filter.Execute(partitions.GetPartition(j));
|
||||
|
||||
VTKM_TEST_ASSERT(result.GetPartition(j).GetField(outputFieldName).GetNumberOfValues() ==
|
||||
partitionResult.GetField(outputFieldName).GetNumberOfValues(),
|
||||
"result vectors' size incorrect");
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> partitionArray;
|
||||
result.GetPartition(j).GetField(outputFieldName).GetData().CopyTo(partitionArray);
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> sDataSetArray;
|
||||
partitionResult.GetField(outputFieldName).GetData().CopyTo(sDataSetArray);
|
||||
|
||||
const vtkm::Id numValues = result.GetPartition(j).GetField(outputFieldName).GetNumberOfValues();
|
||||
for (vtkm::Id i = 0; i < numValues; i++)
|
||||
{
|
||||
VTKM_TEST_ASSERT(partitionArray.GetPortalConstControl().Get(i) ==
|
||||
sDataSetArray.GetPortalConstControl().Get(i),
|
||||
"result values incorrect");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void TestPartitionedDataSetFilters()
|
||||
{
|
||||
std::size_t partitionNum = 7;
|
||||
vtkm::cont::PartitionedDataSet result;
|
||||
vtkm::cont::PartitionedDataSet partitions;
|
||||
|
||||
partitions = PartitionedDataSetBuilder<vtkm::Id>(partitionNum, "pointvar");
|
||||
vtkm::filter::CellAverage cellAverage;
|
||||
cellAverage.SetOutputFieldName("average");
|
||||
cellAverage.SetActiveField("pointvar");
|
||||
result = cellAverage.Execute(partitions);
|
||||
Result_Verify(result, cellAverage, partitions, std::string("pointvar"));
|
||||
}
|
||||
|
||||
int UnitTestPartitionedDataSetFilters(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestPartitionedDataSetFilters, argc, argv);
|
||||
}
|
@ -10,7 +10,7 @@
|
||||
#include <vtkm/filter/Histogram.h>
|
||||
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/MultiBlock.h>
|
||||
#include <vtkm/cont/PartitionedDataSet.h>
|
||||
#include <vtkm/cont/testing/Testing.h>
|
||||
|
||||
#include <algorithm>
|
||||
@ -79,32 +79,34 @@ void AddField(vtkm::cont::DataSet& dataset,
|
||||
}
|
||||
}
|
||||
|
||||
static void TestMultiBlockHistogram()
|
||||
static void TestPartitionedDataSetHistogram()
|
||||
{
|
||||
// init random seed.
|
||||
std::srand(100);
|
||||
|
||||
vtkm::cont::MultiBlock mb;
|
||||
vtkm::cont::PartitionedDataSet mb;
|
||||
|
||||
vtkm::cont::DataSet block0;
|
||||
AddField<double>(block0, 0.0, 100.0, 1024, "double");
|
||||
mb.AddBlock(block0);
|
||||
vtkm::cont::DataSet partition0;
|
||||
AddField<double>(partition0, 0.0, 100.0, 1024, "double");
|
||||
mb.AppendPartition(partition0);
|
||||
|
||||
vtkm::cont::DataSet block1;
|
||||
AddField<int>(block1, 100, 1000, 1024, "double");
|
||||
mb.AddBlock(block1);
|
||||
vtkm::cont::DataSet partition1;
|
||||
AddField<int>(partition1, 100, 1000, 1024, "double");
|
||||
mb.AppendPartition(partition1);
|
||||
|
||||
vtkm::cont::DataSet block2;
|
||||
AddField<double>(block2, 100.0, 500.0, 1024, "double");
|
||||
mb.AddBlock(block2);
|
||||
vtkm::cont::DataSet partition2;
|
||||
AddField<double>(partition2, 100.0, 500.0, 1024, "double");
|
||||
mb.AppendPartition(partition2);
|
||||
|
||||
vtkm::filter::Histogram histogram;
|
||||
histogram.SetActiveField("double");
|
||||
auto result = histogram.Execute(mb);
|
||||
VTKM_TEST_ASSERT(result.GetNumberOfBlocks() == 1, "Expecting 1 block.");
|
||||
VTKM_TEST_ASSERT(result.GetNumberOfPartitions() == 1, "Expecting 1 partition.");
|
||||
|
||||
auto bins =
|
||||
result.GetBlock(0).GetField("histogram").GetData().Cast<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
auto bins = result.GetPartition(0)
|
||||
.GetField("histogram")
|
||||
.GetData()
|
||||
.Cast<vtkm::cont::ArrayHandle<vtkm::Id>>();
|
||||
VTKM_TEST_ASSERT(bins.GetNumberOfValues() == 10, "Expecting 10 bins.");
|
||||
auto count = std::accumulate(vtkm::cont::ArrayPortalToIteratorBegin(bins.GetPortalConstControl()),
|
||||
vtkm::cont::ArrayPortalToIteratorEnd(bins.GetPortalConstControl()),
|
||||
@ -120,7 +122,7 @@ static void TestMultiBlockHistogram()
|
||||
std::cout << std::endl;
|
||||
};
|
||||
|
||||
int UnitTestMultiBlockHistogramFilter(int argc, char* argv[])
|
||||
int UnitTestPartitionedDataSetHistogramFilter(int argc, char* argv[])
|
||||
{
|
||||
return vtkm::cont::testing::Testing::Run(TestMultiBlockHistogram, argc, argv);
|
||||
return vtkm::cont::testing::Testing::Run(TestPartitionedDataSetHistogram, argc, argv);
|
||||
}
|
Loading…
Reference in New Issue
Block a user