mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-19 10:35:42 +00:00
Merge topic 'NewFilter'
ba2a710e7 Update NewFitlerInterface.md 1469d34b4 rename DoExecutePartitions 74905a05c use new header file 161391656 Add ChangeLog 0e3cc8076 restore deprecated filter::GenerateIds 130d0d9df Updated Doxygen comments 8cf02d363 New Filter Interface Design Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !2641
This commit is contained in:
commit
06428e2bc7
20
docs/changelog/NewFitlerInterface.md
Normal file
20
docs/changelog/NewFitlerInterface.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
## New Filter Interface Design ##
|
||||||
|
|
||||||
|
An overhaul of the Filter interface is undergoing. This refactoring effort will
|
||||||
|
address many problems we faced in the old design. The most important one is to
|
||||||
|
remove the requirement to compile every single Filter users with a Device Compiler.
|
||||||
|
This is addressed by removing C++ template (and CRTP) from Filter and is subclasses.
|
||||||
|
A new non-templated NewFilter class is added with many old templated public interface
|
||||||
|
removed.
|
||||||
|
|
||||||
|
This new design also made Filter implementations thread-safe by default. Filter
|
||||||
|
implementations are encouraged to take advantage of the new design and removing
|
||||||
|
shared metatable states from their `DoExecute`, see Doxygen documentation in
|
||||||
|
NewFilter.h
|
||||||
|
|
||||||
|
Filter implementations are also re-organized into submodules, with each submodule
|
||||||
|
in its own `vtkm/filter` subdirectory. User should update their code to include
|
||||||
|
the new header files, for example, `vtkm/filter/field_transform/GenerateIds.h`and
|
||||||
|
link to submodule library file, for example, `libvtkm_filter_field_transform.so`.
|
||||||
|
To maintain backward compatability, old `vtkm/filter/FooFilter.h` header files
|
||||||
|
can still be used but will be deprecated in release 2.0.
|
@ -191,7 +191,6 @@ set(extra_sources_device
|
|||||||
${ClipWithFieldInstantiations}
|
${ClipWithFieldInstantiations}
|
||||||
${ClipWithImplicitFunctionInstantiations}
|
${ClipWithImplicitFunctionInstantiations}
|
||||||
ExternalFaces.cxx
|
ExternalFaces.cxx
|
||||||
GenerateIds.cxx
|
|
||||||
VectorMagnitude.cxx
|
VectorMagnitude.cxx
|
||||||
particleadvection/Messenger.cxx
|
particleadvection/Messenger.cxx
|
||||||
particleadvection/ParticleMessenger.cxx
|
particleadvection/ParticleMessenger.cxx
|
||||||
@ -234,6 +233,18 @@ set(gradient_sources_device
|
|||||||
vtkm_pyexpander_generated_file(ClipWithFieldExternInstantiations.h)
|
vtkm_pyexpander_generated_file(ClipWithFieldExternInstantiations.h)
|
||||||
vtkm_pyexpander_generated_file(ClipWithImplicitFunctionExternInstantiations.h)
|
vtkm_pyexpander_generated_file(ClipWithImplicitFunctionExternInstantiations.h)
|
||||||
|
|
||||||
|
set(core_headers
|
||||||
|
NewFilter.h)
|
||||||
|
set(core_sources_device
|
||||||
|
NewFilter.cxx)
|
||||||
|
|
||||||
|
vtkm_library(
|
||||||
|
NAME vtkm_filter_core
|
||||||
|
HEADERS ${core_headers}
|
||||||
|
DEVICE_SOURCES ${core_sources_device}
|
||||||
|
USE_VTKM_JOB_POOL
|
||||||
|
)
|
||||||
|
|
||||||
add_library(vtkm_filter INTERFACE)
|
add_library(vtkm_filter INTERFACE)
|
||||||
|
|
||||||
vtkm_library(
|
vtkm_library(
|
||||||
@ -270,6 +281,7 @@ vtkm_library(
|
|||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
vtkm_filter_common
|
vtkm_filter_common
|
||||||
|
vtkm_filter_core
|
||||||
vtkm_filter_extra
|
vtkm_filter_extra
|
||||||
vtkm_filter_contour
|
vtkm_filter_contour
|
||||||
vtkm_filter_gradient
|
vtkm_filter_gradient
|
||||||
@ -279,6 +291,7 @@ set_target_properties(
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(vtkm_filter_common PUBLIC vtkm_worklet)
|
target_link_libraries(vtkm_filter_common PUBLIC vtkm_worklet)
|
||||||
|
target_link_libraries(vtkm_filter_core PUBLIC vtkm_cont)
|
||||||
target_link_libraries(vtkm_filter_extra PUBLIC vtkm_filter_common)
|
target_link_libraries(vtkm_filter_extra PUBLIC vtkm_filter_common)
|
||||||
target_link_libraries(vtkm_filter_contour PUBLIC vtkm_filter_common)
|
target_link_libraries(vtkm_filter_contour PUBLIC vtkm_filter_common)
|
||||||
target_link_libraries(vtkm_filter_gradient PUBLIC vtkm_filter_common)
|
target_link_libraries(vtkm_filter_gradient PUBLIC vtkm_filter_common)
|
||||||
@ -293,6 +306,7 @@ target_link_libraries(vtkm_filter PUBLIC INTERFACE
|
|||||||
vtkm_filter_contour
|
vtkm_filter_contour
|
||||||
vtkm_filter_gradient
|
vtkm_filter_gradient
|
||||||
vtkm_filter_common
|
vtkm_filter_common
|
||||||
|
vtkm_filter_core
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS vtkm_filter EXPORT ${VTKm_EXPORT_NAME})
|
install(TARGETS vtkm_filter EXPORT ${VTKm_EXPORT_NAME})
|
||||||
@ -300,6 +314,7 @@ install(TARGETS vtkm_filter EXPORT ${VTKm_EXPORT_NAME})
|
|||||||
|
|
||||||
add_subdirectory(internal)
|
add_subdirectory(internal)
|
||||||
add_subdirectory(particleadvection)
|
add_subdirectory(particleadvection)
|
||||||
|
add_subdirectory(field_transform)
|
||||||
|
|
||||||
#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
|
#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
|
||||||
if (VTKm_ENABLE_TESTING)
|
if (VTKm_ENABLE_TESTING)
|
||||||
|
@ -10,95 +10,31 @@
|
|||||||
#ifndef vtk_m_filter_GenerateIds_h
|
#ifndef vtk_m_filter_GenerateIds_h
|
||||||
#define vtk_m_filter_GenerateIds_h
|
#define vtk_m_filter_GenerateIds_h
|
||||||
|
|
||||||
#include <vtkm/filter/Filter.h>
|
#include <vtkm/Deprecated.h>
|
||||||
|
#include <vtkm/filter/field_transform/GenerateIds.h>
|
||||||
#include <vtkm/filter/vtkm_filter_extra_export.h>
|
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
namespace filter
|
namespace filter
|
||||||
{
|
{
|
||||||
|
|
||||||
/// \brief Adds fields to a `DataSet` that give the ids for the points and cells.
|
VTKM_DEPRECATED(
|
||||||
///
|
1.8,
|
||||||
/// This filter will add (by default) a point field named `pointids` that gives the
|
"Use vtkm/filter/field_transform/GenerateIds.h instead of vtkm/filter/GenerateIds.h.")
|
||||||
/// index of the associated point and likewise a cell field named `cellids` for the
|
inline void GenerateIds_deprecated() {}
|
||||||
/// associated cell indices. These fields are useful for tracking the provenance of
|
|
||||||
/// the elements of a `DataSet` as it gets manipulated by filters. It is also
|
inline void GenerateIds_deprecated_warning()
|
||||||
/// convenient for adding indices to operations designed for fields and generally
|
|
||||||
/// creating test data.
|
|
||||||
///
|
|
||||||
class VTKM_FILTER_EXTRA_EXPORT GenerateIds : public vtkm::filter::Filter<GenerateIds>
|
|
||||||
{
|
{
|
||||||
std::string PointFieldName = "pointids";
|
GenerateIds_deprecated();
|
||||||
std::string CellFieldName = "cellids";
|
}
|
||||||
bool GeneratePointIds = true;
|
|
||||||
bool GenerateCellIds = true;
|
|
||||||
bool UseFloat = false;
|
|
||||||
|
|
||||||
public:
|
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::field_transform::GenerateIds.") GenerateIds
|
||||||
GenerateIds() = default;
|
: public vtkm::filter::field_transform::GenerateIds
|
||||||
~GenerateIds() = default;
|
{
|
||||||
|
using field_transform::GenerateIds::GenerateIds;
|
||||||
/// \{
|
|
||||||
/// \brief The name given to the generated point field.
|
|
||||||
///
|
|
||||||
/// By default, the name is `pointids`.
|
|
||||||
///
|
|
||||||
const std::string& GetPointFieldName() const { return this->PointFieldName; }
|
|
||||||
void SetPointFieldName(const std::string& name) { this->PointFieldName = name; }
|
|
||||||
/// \}
|
|
||||||
|
|
||||||
/// \{
|
|
||||||
/// \brief The name given to the generated cell field.
|
|
||||||
///
|
|
||||||
/// By default, the name is `cellids`.
|
|
||||||
///
|
|
||||||
const std::string& GetCellFieldName() const { return this->CellFieldName; }
|
|
||||||
void SetCellFieldName(const std::string& name) { this->CellFieldName = name; }
|
|
||||||
/// \}
|
|
||||||
|
|
||||||
/// \{
|
|
||||||
/// \brief Specify whether the point id field is generated.
|
|
||||||
///
|
|
||||||
/// When `GeneratePointIds` is `true` (the default), a field echoing the point
|
|
||||||
/// indices is generated. When set to `false`, this output is not created.
|
|
||||||
///
|
|
||||||
bool GetGeneratePointIds() const { return this->GeneratePointIds; }
|
|
||||||
void SetGeneratePointIds(bool flag) { this->GeneratePointIds = flag; }
|
|
||||||
/// \}
|
|
||||||
|
|
||||||
/// \{
|
|
||||||
/// \brief Specify whether the cell id field is generated.
|
|
||||||
///
|
|
||||||
/// When `GenerateCellIds` is `true` (the default), a field echoing the cell
|
|
||||||
/// indices is generated. When set to `false`, this output is not created.
|
|
||||||
///
|
|
||||||
bool GetGenerateCellIds() const { return this->GenerateCellIds; }
|
|
||||||
void SetGenerateCellIds(bool flag) { this->GenerateCellIds = flag; }
|
|
||||||
/// \}
|
|
||||||
|
|
||||||
/// \{
|
|
||||||
/// \brief Specify whether the generated fields should be integer or float.
|
|
||||||
///
|
|
||||||
/// When `UseFloat` is `false` (the default), then the fields generated will have
|
|
||||||
/// type `vtkm::Id`. If it is set to `true`, then the fields will be generated
|
|
||||||
/// with type `vtkm::FloatDefault`.
|
|
||||||
///
|
|
||||||
bool GetUseFloat() const { return this->UseFloat; }
|
|
||||||
void SetUseFloat(bool flag) { this->UseFloat = flag; }
|
|
||||||
|
|
||||||
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) const;
|
|
||||||
|
|
||||||
template <typename DerivedPolicy>
|
|
||||||
vtkm::cont::DataSet PrepareForExecution(const vtkm::cont::DataSet& input,
|
|
||||||
vtkm::filter::PolicyBase<DerivedPolicy>) const
|
|
||||||
{
|
|
||||||
return this->DoExecute(input);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}
|
||||||
} // namespace vtkm::filter
|
} // namespace vtkm::filter
|
||||||
} // namespace vtkm
|
|
||||||
|
|
||||||
#endif //vtk_m_filter_GenerateIds_h
|
#endif //vtk_m_filter_GenerateIds_h
|
||||||
|
136
vtkm/filter/NewFilter.cxx
Normal file
136
vtkm/filter/NewFilter.cxx
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
//============================================================================
|
||||||
|
// Copyright (c) Kitware, Inc.
|
||||||
|
// All rights reserved.
|
||||||
|
// See LICENSE.txt for details.
|
||||||
|
//
|
||||||
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
||||||
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
|
//============================================================================
|
||||||
|
#include <vtkm/cont/Algorithm.h>
|
||||||
|
#include <vtkm/cont/Logging.h>
|
||||||
|
#include <vtkm/cont/RuntimeDeviceTracker.h>
|
||||||
|
|
||||||
|
#include <vtkm/filter/NewFilter.h>
|
||||||
|
#include <vtkm/filter/TaskQueue.h>
|
||||||
|
|
||||||
|
#include <future>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void RunFilter(NewFilter* self,
|
||||||
|
vtkm::filter::DataSetQueue& input,
|
||||||
|
vtkm::filter::DataSetQueue& output)
|
||||||
|
{
|
||||||
|
std::pair<vtkm::Id, vtkm::cont::DataSet> task;
|
||||||
|
while (input.GetTask(task))
|
||||||
|
{
|
||||||
|
auto outDS = self->Execute(task.second);
|
||||||
|
output.Push(std::make_pair(task.first, std::move(outDS)));
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::cont::Algorithm::Synchronize();
|
||||||
|
}
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
NewFilter::~NewFilter() = default;
|
||||||
|
|
||||||
|
bool NewFilter::CanThread() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
vtkm::cont::PartitionedDataSet NewFilter::DoExecutePartitions(
|
||||||
|
const vtkm::cont::PartitionedDataSet& input)
|
||||||
|
{
|
||||||
|
vtkm::cont::PartitionedDataSet output;
|
||||||
|
|
||||||
|
if (this->GetRunMultiThreadedFilter())
|
||||||
|
{
|
||||||
|
vtkm::filter::DataSetQueue inputQueue(input);
|
||||||
|
vtkm::filter::DataSetQueue outputQueue;
|
||||||
|
|
||||||
|
vtkm::Id numThreads = this->DetermineNumberOfThreads(input);
|
||||||
|
|
||||||
|
//Run 'numThreads' filters.
|
||||||
|
std::vector<std::future<void>> futures(static_cast<std::size_t>(numThreads));
|
||||||
|
for (std::size_t i = 0; i < static_cast<std::size_t>(numThreads); i++)
|
||||||
|
{
|
||||||
|
auto f = std::async(
|
||||||
|
std::launch::async, RunFilter, this, std::ref(inputQueue), std::ref(outputQueue));
|
||||||
|
futures[i] = std::move(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& f : futures)
|
||||||
|
f.get();
|
||||||
|
|
||||||
|
//Get results from the outputQueue.
|
||||||
|
output = outputQueue.Get();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (const auto& inBlock : input)
|
||||||
|
{
|
||||||
|
vtkm::cont::DataSet outBlock = this->Execute(inBlock);
|
||||||
|
output.AppendPartition(outBlock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::cont::DataSet NewFilter::Execute(const vtkm::cont::DataSet& input)
|
||||||
|
{
|
||||||
|
return this->DoExecute(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::cont::PartitionedDataSet NewFilter::Execute(const vtkm::cont::PartitionedDataSet& input)
|
||||||
|
{
|
||||||
|
VTKM_LOG_SCOPE(vtkm::cont::LogLevel::Perf,
|
||||||
|
"NewFilter (%d partitions): '%s'",
|
||||||
|
(int)input.GetNumberOfPartitions(),
|
||||||
|
vtkm::cont::TypeToString<decltype(*this)>().c_str());
|
||||||
|
|
||||||
|
vtkm::cont::PartitionedDataSet output = this->DoExecutePartitions(input);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::Id NewFilter::DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input)
|
||||||
|
{
|
||||||
|
vtkm::Id numDS = input.GetNumberOfPartitions();
|
||||||
|
|
||||||
|
//Aribitrary constants.
|
||||||
|
const vtkm::Id threadsPerGPU = 8;
|
||||||
|
const vtkm::Id threadsPerCPU = 4;
|
||||||
|
|
||||||
|
vtkm::Id availThreads = 1;
|
||||||
|
|
||||||
|
auto& tracker = vtkm::cont::GetRuntimeDeviceTracker();
|
||||||
|
|
||||||
|
if (tracker.CanRunOn(vtkm::cont::DeviceAdapterTagCuda{}))
|
||||||
|
availThreads = threadsPerGPU;
|
||||||
|
else if (tracker.CanRunOn(vtkm::cont::DeviceAdapterTagKokkos{}))
|
||||||
|
{
|
||||||
|
//Kokkos doesn't support threading on the CPU.
|
||||||
|
#ifdef VTKM_KOKKOS_CUDA
|
||||||
|
availThreads = threadsPerGPU;
|
||||||
|
#else
|
||||||
|
availThreads = 1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (tracker.CanRunOn(vtkm::cont::DeviceAdapterTagSerial{}))
|
||||||
|
availThreads = 1;
|
||||||
|
else
|
||||||
|
availThreads = threadsPerCPU;
|
||||||
|
|
||||||
|
vtkm::Id numThreads = std::min<vtkm::Id>(numDS, availThreads);
|
||||||
|
return numThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace filter
|
||||||
|
} // namespace vtkm
|
362
vtkm/filter/NewFilter.h
Normal file
362
vtkm/filter/NewFilter.h
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_NewFilter_h
|
||||||
|
#define vtk_m_filter_NewFilter_h
|
||||||
|
|
||||||
|
#include <vtkm/cont/DataSet.h>
|
||||||
|
#include <vtkm/cont/Field.h>
|
||||||
|
#include <vtkm/cont/Invoker.h>
|
||||||
|
#include <vtkm/cont/Logging.h>
|
||||||
|
#include <vtkm/cont/PartitionedDataSet.h>
|
||||||
|
|
||||||
|
#include <vtkm/filter/FieldSelection.h>
|
||||||
|
#include <vtkm/filter/vtkm_filter_core_export.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
/// \brief base class for all filters.
|
||||||
|
///
|
||||||
|
/// This is the base class for all filters. To add a new filter, one can subclass this (or any of
|
||||||
|
/// the existing subclasses e.g. FilterField, FilterParticleAdvection, etc.) and implement relevant
|
||||||
|
/// methods.
|
||||||
|
///
|
||||||
|
/// \section FilterUsage Usage
|
||||||
|
///
|
||||||
|
/// To execute a filter, one typically calls the `auto result = filter.Execute(input)`. Typical
|
||||||
|
/// usage is as follows:
|
||||||
|
///
|
||||||
|
/// \code{cpp}
|
||||||
|
///
|
||||||
|
/// // create the concrete subclass (e.g. Contour).
|
||||||
|
/// vtkm::filter::contour::Contour contour;
|
||||||
|
///
|
||||||
|
/// // select fields to map to the output, if different from default which is to map all input
|
||||||
|
/// // fields.
|
||||||
|
/// contour.SetFieldToPass({"var1", "var2"});
|
||||||
|
///
|
||||||
|
/// // execute the filter on vtkm::cont::DataSet.
|
||||||
|
/// vtkm::cont::DataSet dsInput = ...
|
||||||
|
/// auto outputDS = contour.Execute(dsInput);
|
||||||
|
///
|
||||||
|
/// // or, execute on a vtkm::cont::PartitionedDataSet
|
||||||
|
/// vtkm::cont::PartitionedDataSet mbInput = ...
|
||||||
|
/// auto outputMB = contour.Execute(mbInput);
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// `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.
|
||||||
|
///
|
||||||
|
/// `Execute` simply calls the pure virtual function `DoExecute(DataSet&)` which is the main
|
||||||
|
/// extension point of the Filter interface. Filter developer needs to override
|
||||||
|
/// `DoExecute(DataSet)` to implement the business logic of filtering operations on a single
|
||||||
|
/// DataSet.
|
||||||
|
///
|
||||||
|
/// The default implementation of `Execute(PartitionedDataSet&)` is merely provided for
|
||||||
|
/// convenience. Internally, it calls `DoExecutePartitions(PartitionedDataSet)` to iterate DataSets
|
||||||
|
/// of a PartitionedDataSet and pass each individual DataSets to `DoExecute(DataSet&)`,
|
||||||
|
/// possibly in a multi-threaded setting. Developer of `DoExecute(DataSet&)` needs to indicate
|
||||||
|
/// the thread-safeness of `DoExecute(DataSet&)` by overriding the `CanThread()` virtual method
|
||||||
|
/// which by default returns `true`.
|
||||||
|
///
|
||||||
|
/// In the case that filtering on a PartitionedDataSet can not be simply implemented as a
|
||||||
|
/// for-each loop on the component DataSets, filter implementor needs to override the
|
||||||
|
/// `DoExecutePartitions(PartitionedDataSet&)`. See the implementation of
|
||||||
|
/// `FilterParticleAdvection::Execute(PartitionedDataSet&)` for an example.
|
||||||
|
///
|
||||||
|
/// \section FilterSubclassing Subclassing
|
||||||
|
///
|
||||||
|
/// In many uses cases, one subclasses one of the immediate subclasses of this class such as
|
||||||
|
/// FilterField, FilterParticleAdvection, etc. Those may impose additional constraints on the
|
||||||
|
/// methods to implement in the subclasses. Here, we describes the things to consider when directly
|
||||||
|
/// subclassing vtkm::filter::NewFilter.
|
||||||
|
///
|
||||||
|
/// \subsection FilterExecution Execute
|
||||||
|
///
|
||||||
|
/// A concrete subclass of Filter must provide `DoExecute` implementation that provides the meat
|
||||||
|
/// for the filter i.e. the implementation for the filter's data processing logic. There are two
|
||||||
|
/// signatures 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
|
||||||
|
/// 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}
|
||||||
|
///
|
||||||
|
/// vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input);
|
||||||
|
///
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// The role of this method is to execute on the input dataset and generate the result and return
|
||||||
|
/// it. If there are any errors, the subclass must throw an exception
|
||||||
|
/// (e.g. `vtkm::cont::ErrorFilterExecution`).
|
||||||
|
///
|
||||||
|
/// In this simple case, the NewFilter superclass handles iterating over multiple partitions in the
|
||||||
|
/// input PartitionedDataSet and calling `DoExecute(DataSet&)` iteratively.
|
||||||
|
///
|
||||||
|
/// The aforementioned approach is also suitable for filters that need special handling for
|
||||||
|
/// PartitionedDataSets that requires certain cross DataSet operations (usually scatter/gather
|
||||||
|
/// and reduction on DataSets) before and/or after the per DataSet operation. This can be done by
|
||||||
|
/// overriding `DoExecutePartitions(PartitionedDataSet&)` while calling to the base class
|
||||||
|
/// `DoExecutePartitions(PartitionedDataSet&) as helper function for iteration on DataSets.
|
||||||
|
///
|
||||||
|
/// \code{cpp}
|
||||||
|
/// vtkm::cont::PartitionedDataSet FooFilter::DoExecutePartitions(
|
||||||
|
/// const vtkm::cont::PartitionedDataSet& input)
|
||||||
|
/// {
|
||||||
|
/// // Do pre execute stuff, e.g. scattering to each DataSet
|
||||||
|
/// auto output = this->NewFilter::DoExecutePartitions(input);
|
||||||
|
/// // Do post execute stuff, e.g gather/reduce from DataSets
|
||||||
|
/// return output;
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// For more complex filters, like streamlines, particle tracking, where the processing of
|
||||||
|
/// PartitionedDataSets cannot be modelled as mapping and reduction operation on DataSet, one
|
||||||
|
/// needs fully implement `DoExecutePartitions(PartitionedDataSet&)`. Now the subclass is given
|
||||||
|
/// full control over the execution, including any mapping of fields to output (described in next
|
||||||
|
/// sub-section).
|
||||||
|
///
|
||||||
|
/// \subsection FilterMappingFields MapFieldsOntoOutput
|
||||||
|
///
|
||||||
|
/// For subclasses that map input fields into output fields, the implementation of its
|
||||||
|
/// `DoExecute(DataSet&)` should call `NewFilter::MapFieldsOntoOutput` with a properly defined
|
||||||
|
/// `Mapper`, before returning the output DataSet. For example:
|
||||||
|
///
|
||||||
|
/// \code{cpp}
|
||||||
|
/// VTKM_CONT DataSet SomeFilter::DoExecute(const vtkm::cont::DataSet& input)
|
||||||
|
/// {
|
||||||
|
/// vtkm::cont::DataSet output;
|
||||||
|
/// output = ... // Generation of the new DataSet
|
||||||
|
///
|
||||||
|
/// // Mapper is a callable object (function object, lambda, etc.) that takes an input Field
|
||||||
|
/// // and maps it to an output Field and then add the output Field to the output DataSet
|
||||||
|
/// auto mapper = [](auto& outputDs, const auto& inputField) {
|
||||||
|
/// auto outputField = ... // Business logic for mapping input field to output field
|
||||||
|
/// output.AddField(outputField);
|
||||||
|
/// };
|
||||||
|
/// MapFieldsOntoOutput(input, output, mapper);
|
||||||
|
///
|
||||||
|
/// return output;
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// `MapFieldsOntoOutput` iterates through each `FieldToPass` in the input DataSet and calls the
|
||||||
|
/// Mapper to map the input Field to output Field. For simple filters that just pass on input
|
||||||
|
/// fields to the output DataSet without any computation, an overload of
|
||||||
|
/// `MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output)` is also
|
||||||
|
/// provided as a convenience that uses the default mapper which trivially adds input Field to
|
||||||
|
/// output DaaSet (via a shallow copy).
|
||||||
|
///
|
||||||
|
/// \subsection FilterThreadSafety CanThread
|
||||||
|
///
|
||||||
|
/// By default, the implementation of `DoExecute(DataSet&)` should model a *pure function*, i.e. it
|
||||||
|
/// does not have any mutable shared state. This makes it thread-safe by default and allows
|
||||||
|
/// the default implementation of `DoExecutePartitions(PartitionedDataSet&)` to be simply a parallel
|
||||||
|
/// for-each, thus facilitates multi-threaded execution without any lock.
|
||||||
|
///
|
||||||
|
/// Many legacy (VTKm 1.x) filter implementations needed to store states between the mesh generation
|
||||||
|
/// phase and field mapping phase of filter execution, for example, parameters for field
|
||||||
|
/// interpolation. The shared mutable states were mostly stored as mutable data members of the
|
||||||
|
/// filter class (either in terms of ArrayHandle or some kind of Worket). The new filter interface,
|
||||||
|
/// by combining the two phases into a single call to `DoExecute(DataSet&)`, we have eliminated most
|
||||||
|
/// of the cases that require such shared mutable states. New implementations of filters that
|
||||||
|
/// require passing information between these two phases can now use local variables within the
|
||||||
|
/// `DoExecute(DataSet&)`. For example:
|
||||||
|
///
|
||||||
|
/// \code{cpp}
|
||||||
|
/// struct SharedState; // shared states between mesh generation and field mapping.
|
||||||
|
/// VTKM_CONT DataSet ThreadSafeFilter::DoExecute(const vtkm::cont::DataSet& input)
|
||||||
|
/// {
|
||||||
|
/// // Mutable states that was a data member of the filter is now a local variable.
|
||||||
|
/// // Each invocation of Execute(DataSet) in the multi-threaded execution of
|
||||||
|
/// // Execute(PartitionedDataSet&) will have a copy of `states` on each thread's stack
|
||||||
|
/// // thus making it thread-safe.
|
||||||
|
/// SharedStates states;
|
||||||
|
///
|
||||||
|
/// vtkm::cont::DataSet output;
|
||||||
|
/// output = ... // Generation of the new DataSet and store interpolation parameters in `states`
|
||||||
|
///
|
||||||
|
/// // Lambda capture of `states`, effectively passing the shared states to the Mapper.
|
||||||
|
/// auto mapper = [&states](auto& outputDs, const auto& inputField) {
|
||||||
|
/// auto outputField = ... // Use `states` for mapping input field to output field
|
||||||
|
/// output.AddField(outputField);
|
||||||
|
/// };
|
||||||
|
/// MapFieldsOntoOutput(input, output, mapper);
|
||||||
|
///
|
||||||
|
/// return output;
|
||||||
|
/// }
|
||||||
|
/// \endcode
|
||||||
|
///
|
||||||
|
/// In the rare cases that filter implementation can not be made thread-safe, the implementation
|
||||||
|
/// needs to override the `CanThread()` virtual method to return `false`. The default
|
||||||
|
/// `Execute(PartitionedDataSet&)` implementation will fallback to a serial for loop execution.
|
||||||
|
///
|
||||||
|
/// \subsection FilterThreadScheduling DoExecute
|
||||||
|
/// The default multi-threaded execution of `Execute(PartitionedDataSet&)` uses a simple FIFO queue
|
||||||
|
/// of DataSet and pool of *worker* threads. Implementation of Filter subclass can override the
|
||||||
|
/// `DoExecutePartitions(PartitionedDataSet)` virtual method to provide implementation specific
|
||||||
|
/// scheduling policy. The default number of *worker* threads in the pool are determined by the
|
||||||
|
/// `DetermineNumberOfThreads()` virtual method using several backend dependent heuristic.
|
||||||
|
/// Implementations of Filter subclass can also override
|
||||||
|
/// `DetermineNumberOfThreads()` to provide implementation specific heuristic.
|
||||||
|
///
|
||||||
|
class VTKM_FILTER_CORE_EXPORT NewFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VTKM_CONT
|
||||||
|
virtual ~NewFilter();
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
virtual bool CanThread() const;
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
bool GetRunMultiThreadedFilter() const
|
||||||
|
{
|
||||||
|
return this->CanThread() && this->RunFilterWithMultipleThreads;
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void SetRunMultiThreadedFilter(bool val)
|
||||||
|
{
|
||||||
|
if (this->CanThread())
|
||||||
|
this->RunFilterWithMultipleThreads = val;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::string msg =
|
||||||
|
"Multi threaded filter not supported for " + std::string(typeid(*this).name());
|
||||||
|
VTKM_LOG_S(vtkm::cont::LogLevel::Info, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Specify which subset of types a filter supports.
|
||||||
|
///
|
||||||
|
/// A filter is able to state what subset of types it supports.
|
||||||
|
using SupportedTypes = VTKM_DEFAULT_TYPE_LIST;
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// \brief Specify which fields get passed from input to output.
|
||||||
|
///
|
||||||
|
/// After a filter successfully executes and returns a new data set, fields are mapped from
|
||||||
|
/// input to output. Depending on what operation the filter does, this could be a simple shallow
|
||||||
|
/// copy of an array, or it could be a computed operation. You can control which fields are
|
||||||
|
/// passed (and equivalently which are not) with this parameter.
|
||||||
|
///
|
||||||
|
/// By default, all fields are passed during execution.
|
||||||
|
///
|
||||||
|
VTKM_CONT
|
||||||
|
void SetFieldsToPass(const vtkm::filter::FieldSelection& fieldsToPass)
|
||||||
|
{
|
||||||
|
this->FieldsToPass = fieldsToPass;
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void SetFieldsToPass(const vtkm::filter::FieldSelection& fieldsToPass,
|
||||||
|
vtkm::filter::FieldSelection::ModeEnum mode)
|
||||||
|
{
|
||||||
|
this->FieldsToPass = fieldsToPass;
|
||||||
|
this->FieldsToPass.SetMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
void SetFieldsToPass(
|
||||||
|
const std::string& fieldname,
|
||||||
|
vtkm::cont::Field::Association association,
|
||||||
|
vtkm::filter::FieldSelection::ModeEnum mode = vtkm::filter::FieldSelection::MODE_SELECT)
|
||||||
|
{
|
||||||
|
this->SetFieldsToPass({ fieldname, association }, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
const vtkm::filter::FieldSelection& GetFieldsToPass() const { return this->FieldsToPass; }
|
||||||
|
VTKM_CONT
|
||||||
|
vtkm::filter::FieldSelection& GetFieldsToPass() { return this->FieldsToPass; }
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// Select the coordinate system index to make active to use when processing the input
|
||||||
|
/// DataSet. This is used primarily by the Filter to select the coordinate system
|
||||||
|
/// to use as a field when \c UseCoordinateSystemAsField is true.
|
||||||
|
VTKM_CONT
|
||||||
|
void SetActiveCoordinateSystem(vtkm::Id index) { this->CoordinateSystemIndex = index; }
|
||||||
|
|
||||||
|
VTKM_CONT
|
||||||
|
vtkm::Id GetActiveCoordinateSystemIndex() const { return this->CoordinateSystemIndex; }
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// Executes the filter on the input and produces a result dataset.
|
||||||
|
///
|
||||||
|
/// On success, this the dataset produced. On error, vtkm::cont::ErrorExecution will be thrown.
|
||||||
|
VTKM_CONT vtkm::cont::DataSet Execute(const vtkm::cont::DataSet& input);
|
||||||
|
//@}
|
||||||
|
|
||||||
|
//@{
|
||||||
|
/// 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::PartitionedDataSet Execute(const vtkm::cont::PartitionedDataSet& input);
|
||||||
|
//@}
|
||||||
|
|
||||||
|
// FIXME: Is this actually materialize? Are there different kinds of Invoker?
|
||||||
|
/// Specify the vtkm::cont::Invoker to be used to execute worklets by
|
||||||
|
/// this filter instance. Overriding the default allows callers to control
|
||||||
|
/// which device adapters a filter uses.
|
||||||
|
void SetInvoker(vtkm::cont::Invoker inv) { this->Invoke = inv; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
vtkm::cont::Invoker Invoke;
|
||||||
|
vtkm::Id CoordinateSystemIndex = 0;
|
||||||
|
|
||||||
|
template <typename Mapper>
|
||||||
|
VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input,
|
||||||
|
vtkm::cont::DataSet& output,
|
||||||
|
Mapper&& mapper)
|
||||||
|
{
|
||||||
|
for (vtkm::IdComponent cc = 0; cc < input.GetNumberOfFields(); ++cc)
|
||||||
|
{
|
||||||
|
auto field = input.GetField(cc);
|
||||||
|
if (this->GetFieldsToPass().IsFieldSelected(field))
|
||||||
|
{
|
||||||
|
mapper(output, field);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output)
|
||||||
|
{
|
||||||
|
MapFieldsOntoOutput(input, output, defaultMapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
VTKM_CONT
|
||||||
|
virtual vtkm::Id DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input);
|
||||||
|
|
||||||
|
// Note: In C++, subclasses can override private methods of superclass.
|
||||||
|
VTKM_CONT virtual vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) = 0;
|
||||||
|
VTKM_CONT virtual vtkm::cont::PartitionedDataSet DoExecutePartitions(
|
||||||
|
const vtkm::cont::PartitionedDataSet& inData);
|
||||||
|
|
||||||
|
static void defaultMapper(vtkm::cont::DataSet& output, const vtkm::cont::Field& field)
|
||||||
|
{
|
||||||
|
output.AddField(field);
|
||||||
|
};
|
||||||
|
|
||||||
|
vtkm::filter::FieldSelection FieldsToPass = vtkm::filter::FieldSelection::MODE_ALL;
|
||||||
|
bool RunFilterWithMultipleThreads = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} // namespace vtkm::filter
|
||||||
|
|
||||||
|
#endif
|
28
vtkm/filter/field_transform/CMakeLists.txt
Normal file
28
vtkm/filter/field_transform/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
##============================================================================
|
||||||
|
## 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.
|
||||||
|
##============================================================================
|
||||||
|
set(field_transform_headers
|
||||||
|
GenerateIds.h)
|
||||||
|
set(field_transform_sources_device
|
||||||
|
GenerateIds.cxx)
|
||||||
|
|
||||||
|
vtkm_library(
|
||||||
|
NAME vtkm_filter_field_transform
|
||||||
|
HEADERS ${field_transform_headers}
|
||||||
|
DEVICE_SOURCES ${field_transform_sources_device}
|
||||||
|
USE_VTKM_JOB_POOL
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(vtkm_filter_field_transform PUBLIC vtkm_worklet vtkm_filter_core)
|
||||||
|
target_link_libraries(vtkm_filter PUBLIC INTERFACE vtkm_filter_field_transform)
|
||||||
|
|
||||||
|
#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
|
||||||
|
if (VTKm_ENABLE_TESTING)
|
||||||
|
add_subdirectory(testing)
|
||||||
|
endif ()
|
@ -7,17 +7,15 @@
|
|||||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
// PURPOSE. See the above copyright notice for more information.
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <vtkm/filter/GenerateIds.h>
|
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayCopy.h>
|
#include <vtkm/cont/ArrayCopy.h>
|
||||||
#include <vtkm/cont/ArrayHandleCast.h>
|
|
||||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||||
|
#include <vtkm/filter/field_transform/GenerateIds.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
vtkm::cont::UnknownArrayHandle GenerateArray(const vtkm::filter::GenerateIds& self, vtkm::Id size)
|
vtkm::cont::UnknownArrayHandle GenerateArray(const vtkm::filter::field_transform::GenerateIds& self,
|
||||||
|
vtkm::Id size)
|
||||||
{
|
{
|
||||||
vtkm::cont::ArrayHandleIndex indexArray(size);
|
vtkm::cont::ArrayHandleIndex indexArray(size);
|
||||||
|
|
||||||
@ -41,8 +39,9 @@ namespace vtkm
|
|||||||
{
|
{
|
||||||
namespace filter
|
namespace filter
|
||||||
{
|
{
|
||||||
|
namespace field_transform
|
||||||
vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input) const
|
{
|
||||||
|
vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input)
|
||||||
{
|
{
|
||||||
vtkm::cont::DataSet output = input;
|
vtkm::cont::DataSet output = input;
|
||||||
|
|
||||||
@ -57,8 +56,10 @@ vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input) con
|
|||||||
output.AddCellField(this->GetCellFieldName(), GenerateArray(*this, input.GetNumberOfCells()));
|
output.AddCellField(this->GetCellFieldName(), GenerateArray(*this, input.GetNumberOfCells()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapFieldsOntoOutput(input, output);
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
} // namespace field_transform
|
||||||
} // namespace vtkm::filter
|
} // namespace vtkm::filter
|
||||||
} // namespace vtkm
|
} // namespace vtkm
|
95
vtkm/filter/field_transform/GenerateIds.h
Normal file
95
vtkm/filter/field_transform/GenerateIds.h
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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_filter_field_transform_GenerateIds_h
|
||||||
|
#define vtk_m_filter_field_transform_GenerateIds_h
|
||||||
|
|
||||||
|
#include <vtkm/filter/NewFilter.h>
|
||||||
|
#include <vtkm/filter/field_transform/vtkm_filter_field_transform_export.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace filter
|
||||||
|
{
|
||||||
|
namespace field_transform
|
||||||
|
{
|
||||||
|
/// \brief Adds fields to a `DataSet` that give the ids for the points and cells.
|
||||||
|
///
|
||||||
|
/// This filter will add (by default) a point field named `pointids` that gives the
|
||||||
|
/// index of the associated point and likewise a cell field named `cellids` for the
|
||||||
|
/// associated cell indices. These fields are useful for tracking the provenance of
|
||||||
|
/// the elements of a `DataSet` as it gets manipulated by filters. It is also
|
||||||
|
/// convenient for adding indices to operations designed for fields and generally
|
||||||
|
/// creating test data.
|
||||||
|
///
|
||||||
|
class VTKM_FILTER_FIELD_TRANSFORM_EXPORT GenerateIds : public vtkm::filter::NewFilter
|
||||||
|
{
|
||||||
|
std::string PointFieldName = "pointids";
|
||||||
|
std::string CellFieldName = "cellids";
|
||||||
|
bool GeneratePointIds = true;
|
||||||
|
bool GenerateCellIds = true;
|
||||||
|
bool UseFloat = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// \{
|
||||||
|
/// \brief The name given to the generated point field.
|
||||||
|
///
|
||||||
|
/// By default, the name is `pointids`.
|
||||||
|
///
|
||||||
|
const std::string& GetPointFieldName() const { return this->PointFieldName; }
|
||||||
|
void SetPointFieldName(const std::string& name) { this->PointFieldName = name; }
|
||||||
|
/// \}
|
||||||
|
|
||||||
|
/// \{
|
||||||
|
/// \brief The name given to the generated cell field.
|
||||||
|
///
|
||||||
|
/// By default, the name is `cellids`.
|
||||||
|
///
|
||||||
|
const std::string& GetCellFieldName() const { return this->CellFieldName; }
|
||||||
|
void SetCellFieldName(const std::string& name) { this->CellFieldName = name; }
|
||||||
|
/// \}
|
||||||
|
|
||||||
|
/// \{
|
||||||
|
/// \brief Specify whether the point id field is generated.
|
||||||
|
///
|
||||||
|
/// When `GeneratePointIds` is `true` (the default), a field echoing the point
|
||||||
|
/// indices is generated. When set to `false`, this output is not created.
|
||||||
|
///
|
||||||
|
bool GetGeneratePointIds() const { return this->GeneratePointIds; }
|
||||||
|
void SetGeneratePointIds(bool flag) { this->GeneratePointIds = flag; }
|
||||||
|
/// \}
|
||||||
|
|
||||||
|
/// \{
|
||||||
|
/// \brief Specify whether the cell id field is generated.
|
||||||
|
///
|
||||||
|
/// When `GenerateCellIds` is `true` (the default), a field echoing the cell
|
||||||
|
/// indices is generated. When set to `false`, this output is not created.
|
||||||
|
///
|
||||||
|
bool GetGenerateCellIds() const { return this->GenerateCellIds; }
|
||||||
|
void SetGenerateCellIds(bool flag) { this->GenerateCellIds = flag; }
|
||||||
|
/// \}
|
||||||
|
|
||||||
|
/// \{
|
||||||
|
/// \brief Specify whether the generated fields should be integer or float.
|
||||||
|
///
|
||||||
|
/// When `UseFloat` is `false` (the default), then the fields generated will have
|
||||||
|
/// type `vtkm::Id`. If it is set to `true`, then the fields will be generated
|
||||||
|
/// with type `vtkm::FloatDefault`.
|
||||||
|
///
|
||||||
|
bool GetUseFloat() const { return this->UseFloat; }
|
||||||
|
void SetUseFloat(bool flag) { this->UseFloat = flag; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
|
||||||
|
};
|
||||||
|
} // namespace field_transform
|
||||||
|
} // namespace vtkm::filter
|
||||||
|
} // namespace vtkm
|
||||||
|
|
||||||
|
#endif //vtk_m_filter_field_transform_GenerateIds_h
|
22
vtkm/filter/field_transform/testing/CMakeLists.txt
Normal file
22
vtkm/filter/field_transform/testing/CMakeLists.txt
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
##============================================================================
|
||||||
|
## 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.
|
||||||
|
##============================================================================
|
||||||
|
|
||||||
|
set(unit_tests
|
||||||
|
UnitTestGenerateIds.cxx)
|
||||||
|
|
||||||
|
set(libraries
|
||||||
|
vtkm_filter_field_transform
|
||||||
|
vtkm_source)
|
||||||
|
|
||||||
|
vtkm_unit_tests(
|
||||||
|
SOURCES ${unit_tests}
|
||||||
|
LIBRARIES ${libraries}
|
||||||
|
USE_VTKM_JOB_POOL
|
||||||
|
)
|
@ -7,14 +7,10 @@
|
|||||||
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||||
// PURPOSE. See the above copyright notice for more information.
|
// PURPOSE. See the above copyright notice for more information.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include <vtkm/filter/GenerateIds.h>
|
|
||||||
|
|
||||||
#include <vtkm/source/Tangle.h>
|
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayHandleIndex.h>
|
#include <vtkm/cont/ArrayHandleIndex.h>
|
||||||
|
|
||||||
#include <vtkm/cont/testing/Testing.h>
|
#include <vtkm/cont/testing/Testing.h>
|
||||||
|
#include <vtkm/filter/field_transform/GenerateIds.h>
|
||||||
|
#include <vtkm/source/Tangle.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -38,7 +34,8 @@ void CheckField(const vtkm::cont::UnknownArrayHandle& array, vtkm::Id expectedSi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TryGenerateIds(vtkm::filter::GenerateIds& filter, // Why is Filter::Execute not const?
|
void TryGenerateIds(
|
||||||
|
vtkm::filter::field_transform::GenerateIds& filter, // Why is Filter::Execute not const?
|
||||||
const vtkm::cont::DataSet& input)
|
const vtkm::cont::DataSet& input)
|
||||||
{
|
{
|
||||||
vtkm::cont::DataSet output = filter.Execute(input);
|
vtkm::cont::DataSet output = filter.Execute(input);
|
||||||
@ -81,7 +78,7 @@ void TryGenerateIds(vtkm::filter::GenerateIds& filter, // Why is Filter::Execute
|
|||||||
void TestGenerateIds()
|
void TestGenerateIds()
|
||||||
{
|
{
|
||||||
vtkm::cont::DataSet input = vtkm::source::Tangle{ vtkm::Id3(8) }.Execute();
|
vtkm::cont::DataSet input = vtkm::source::Tangle{ vtkm::Id3(8) }.Execute();
|
||||||
vtkm::filter::GenerateIds filter;
|
vtkm::filter::field_transform::GenerateIds filter;
|
||||||
|
|
||||||
TryGenerateIds(filter, input);
|
TryGenerateIds(filter, input);
|
||||||
|
|
@ -37,7 +37,6 @@ set(unit_tests
|
|||||||
UnitTestFieldToColors.cxx
|
UnitTestFieldToColors.cxx
|
||||||
UnitTestGradientExplicit.cxx
|
UnitTestGradientExplicit.cxx
|
||||||
UnitTestGradientUniform.cxx
|
UnitTestGradientUniform.cxx
|
||||||
UnitTestGenerateIds.cxx
|
|
||||||
UnitTestGhostCellClassify.cxx
|
UnitTestGhostCellClassify.cxx
|
||||||
UnitTestGhostCellRemove.cxx
|
UnitTestGhostCellRemove.cxx
|
||||||
UnitTestHistogramFilter.cxx
|
UnitTestHistogramFilter.cxx
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
#include <vtkm/filter/CleanGrid.h>
|
#include <vtkm/filter/CleanGrid.h>
|
||||||
#include <vtkm/filter/Contour.h>
|
#include <vtkm/filter/Contour.h>
|
||||||
#include <vtkm/filter/GenerateIds.h>
|
#include <vtkm/filter/field_transform/GenerateIds.h>
|
||||||
|
|
||||||
#include <vtkm/io/VTKDataSetReader.h>
|
#include <vtkm/io/VTKDataSetReader.h>
|
||||||
#include <vtkm/source/Tangle.h>
|
#include <vtkm/source/Tangle.h>
|
||||||
@ -32,7 +32,7 @@ public:
|
|||||||
|
|
||||||
vtkm::Id3 dims(4, 4, 4);
|
vtkm::Id3 dims(4, 4, 4);
|
||||||
vtkm::source::Tangle tangle(dims);
|
vtkm::source::Tangle tangle(dims);
|
||||||
vtkm::filter::GenerateIds genIds;
|
vtkm::filter::field_transform::GenerateIds genIds;
|
||||||
genIds.SetUseFloat(true);
|
genIds.SetUseFloat(true);
|
||||||
genIds.SetGeneratePointIds(false);
|
genIds.SetGeneratePointIds(false);
|
||||||
genIds.SetCellFieldName("cellvar");
|
genIds.SetCellFieldName("cellvar");
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#include <vtkm/cont/testing/Testing.h>
|
#include <vtkm/cont/testing/Testing.h>
|
||||||
|
|
||||||
#include <vtkm/filter/ClipWithImplicitFunction.h>
|
#include <vtkm/filter/ClipWithImplicitFunction.h>
|
||||||
#include <vtkm/filter/GenerateIds.h>
|
#include <vtkm/filter/field_transform/GenerateIds.h>
|
||||||
#include <vtkm/source/Tangle.h>
|
#include <vtkm/source/Tangle.h>
|
||||||
#include <vtkm/worklet/Contour.h>
|
#include <vtkm/worklet/Contour.h>
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ void TestContourUniformGrid()
|
|||||||
|
|
||||||
vtkm::Id3 dims(4, 4, 4);
|
vtkm::Id3 dims(4, 4, 4);
|
||||||
vtkm::source::Tangle tangle(dims);
|
vtkm::source::Tangle tangle(dims);
|
||||||
vtkm::filter::GenerateIds genIds;
|
vtkm::filter::field_transform::GenerateIds genIds;
|
||||||
genIds.SetUseFloat(true);
|
genIds.SetUseFloat(true);
|
||||||
genIds.SetGeneratePointIds(false);
|
genIds.SetGeneratePointIds(false);
|
||||||
genIds.SetCellFieldName("cellvar");
|
genIds.SetCellFieldName("cellvar");
|
||||||
@ -365,7 +365,7 @@ void TestContourClipped()
|
|||||||
|
|
||||||
vtkm::Id3 dims(4, 4, 4);
|
vtkm::Id3 dims(4, 4, 4);
|
||||||
vtkm::source::Tangle tangle(dims);
|
vtkm::source::Tangle tangle(dims);
|
||||||
vtkm::filter::GenerateIds genIds;
|
vtkm::filter::field_transform::GenerateIds genIds;
|
||||||
genIds.SetUseFloat(true);
|
genIds.SetUseFloat(true);
|
||||||
genIds.SetGeneratePointIds(false);
|
genIds.SetGeneratePointIds(false);
|
||||||
genIds.SetCellFieldName("cellvar");
|
genIds.SetCellFieldName("cellvar");
|
||||||
|
Loading…
Reference in New Issue
Block a user