From 8cf02d3632471280d7b98b581bb51598081607c5 Mon Sep 17 00:00:00 2001 From: Li-Ta Lo Date: Fri, 3 Dec 2021 13:44:51 -0700 Subject: [PATCH] New Filter Interface Design --- vtkm/filter/CMakeLists.txt | 18 +- vtkm/filter/FieldTransform/CMakeLists.txt | 33 ++ .../{ => FieldTransform}/GenerateIds.cxx | 9 +- .../filter/{ => FieldTransform}/GenerateIds.h | 19 +- .../FieldTransform/testing/CMakeLists.txt | 22 ++ .../testing/UnitTestGenerateIds.cxx | 8 +- vtkm/filter/NewFilter.cxx | 132 +++++++ vtkm/filter/NewFilter.h | 365 ++++++++++++++++++ vtkm/filter/testing/CMakeLists.txt | 1 - vtkm/filter/testing/UnitTestContourFilter.cxx | 2 +- vtkm/worklet/testing/UnitTestContour.cxx | 2 +- 11 files changed, 580 insertions(+), 31 deletions(-) create mode 100644 vtkm/filter/FieldTransform/CMakeLists.txt rename vtkm/filter/{ => FieldTransform}/GenerateIds.cxx (89%) rename vtkm/filter/{ => FieldTransform}/GenerateIds.h (85%) create mode 100644 vtkm/filter/FieldTransform/testing/CMakeLists.txt rename vtkm/filter/{ => FieldTransform}/testing/UnitTestGenerateIds.cxx (98%) create mode 100644 vtkm/filter/NewFilter.cxx create mode 100644 vtkm/filter/NewFilter.h diff --git a/vtkm/filter/CMakeLists.txt b/vtkm/filter/CMakeLists.txt index fc9829d56..3c8154ec6 100644 --- a/vtkm/filter/CMakeLists.txt +++ b/vtkm/filter/CMakeLists.txt @@ -89,7 +89,6 @@ set(extra_headers ExternalFaces.h FieldSelection.h FieldToColors.h - GenerateIds.h GhostCellClassify.h GhostCellRemove.h Histogram.h @@ -191,7 +190,6 @@ set(extra_sources_device ${ClipWithFieldInstantiations} ${ClipWithImplicitFunctionInstantiations} ExternalFaces.cxx - GenerateIds.cxx VectorMagnitude.cxx particleadvection/Messenger.cxx particleadvection/ParticleMessenger.cxx @@ -234,6 +232,18 @@ set(gradient_sources_device vtkm_pyexpander_generated_file(ClipWithFieldExternInstantiations.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) vtkm_library( @@ -270,6 +280,7 @@ vtkm_library( set_target_properties( vtkm_filter_common + vtkm_filter_core vtkm_filter_extra vtkm_filter_contour vtkm_filter_gradient @@ -279,6 +290,7 @@ set_target_properties( ) 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_contour PUBLIC vtkm_filter_common) target_link_libraries(vtkm_filter_gradient PUBLIC vtkm_filter_common) @@ -293,6 +305,7 @@ target_link_libraries(vtkm_filter PUBLIC INTERFACE vtkm_filter_contour vtkm_filter_gradient vtkm_filter_common + vtkm_filter_core ) install(TARGETS vtkm_filter EXPORT ${VTKm_EXPORT_NAME}) @@ -300,6 +313,7 @@ install(TARGETS vtkm_filter EXPORT ${VTKm_EXPORT_NAME}) add_subdirectory(internal) add_subdirectory(particleadvection) +add_subdirectory(FieldTransform) #-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - if (VTKm_ENABLE_TESTING) diff --git a/vtkm/filter/FieldTransform/CMakeLists.txt b/vtkm/filter/FieldTransform/CMakeLists.txt new file mode 100644 index 000000000..c6ddf467c --- /dev/null +++ b/vtkm/filter/FieldTransform/CMakeLists.txt @@ -0,0 +1,33 @@ +##============================================================================ +## 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(fieldtransform_headers + GenerateIds.h) +set(fieldtransform_sources_device + GenerateIds.cxx) + +vtkm_library( + NAME vtkm_filter_fieldtransform + HEADERS ${fieldtransform_headers} + DEVICE_SOURCES ${fieldtransform_sources_device} + USE_VTKM_JOB_POOL +) + +set_property(TARGET + vtkm_filter_fieldtransform + PROPERTY UNITY_BUILD_MODE GROUP + ) + +target_link_libraries(vtkm_filter_fieldtransform PUBLIC vtkm_worklet vtkm_filter_core) +target_link_libraries(vtkm_filter PUBLIC INTERFACE vtkm_filter_fieldtransform) + +#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - +if (VTKm_ENABLE_TESTING) + add_subdirectory(testing) +endif () diff --git a/vtkm/filter/GenerateIds.cxx b/vtkm/filter/FieldTransform/GenerateIds.cxx similarity index 89% rename from vtkm/filter/GenerateIds.cxx rename to vtkm/filter/FieldTransform/GenerateIds.cxx index b058d826a..b9fe9b0e3 100644 --- a/vtkm/filter/GenerateIds.cxx +++ b/vtkm/filter/FieldTransform/GenerateIds.cxx @@ -7,12 +7,9 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ - -#include - #include -#include #include +#include namespace { @@ -42,7 +39,7 @@ namespace vtkm namespace filter { -vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input) const +vtkm::cont::DataSet GenerateIds::Execute(const vtkm::cont::DataSet& input) { vtkm::cont::DataSet output = input; @@ -57,6 +54,8 @@ vtkm::cont::DataSet GenerateIds::DoExecute(const vtkm::cont::DataSet& input) con output.AddCellField(this->GetCellFieldName(), GenerateArray(*this, input.GetNumberOfCells())); } + MapFieldsOntoOutput(input, output); + return output; } diff --git a/vtkm/filter/GenerateIds.h b/vtkm/filter/FieldTransform/GenerateIds.h similarity index 85% rename from vtkm/filter/GenerateIds.h rename to vtkm/filter/FieldTransform/GenerateIds.h index 0cc5e4013..8b03b49c1 100644 --- a/vtkm/filter/GenerateIds.h +++ b/vtkm/filter/FieldTransform/GenerateIds.h @@ -10,9 +10,8 @@ #ifndef vtk_m_filter_GenerateIds_h #define vtk_m_filter_GenerateIds_h -#include - -#include +#include +#include namespace vtkm { @@ -28,7 +27,7 @@ namespace filter /// convenient for adding indices to operations designed for fields and generally /// creating test data. /// -class VTKM_FILTER_EXTRA_EXPORT GenerateIds : public vtkm::filter::Filter +class VTKM_FILTER_FIELDTRANSFORM_EXPORT GenerateIds : public vtkm::filter::NewFilter { std::string PointFieldName = "pointids"; std::string CellFieldName = "cellids"; @@ -37,9 +36,6 @@ class VTKM_FILTER_EXTRA_EXPORT GenerateIds : public vtkm::filter::FilterUseFloat; } void SetUseFloat(bool flag) { this->UseFloat = flag; } - vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) const; - - template - vtkm::cont::DataSet PrepareForExecution(const vtkm::cont::DataSet& input, - vtkm::filter::PolicyBase) const - { - return this->DoExecute(input); - } + vtkm::cont::DataSet Execute(const vtkm::cont::DataSet& input) override; }; } // namespace vtkm::filter diff --git a/vtkm/filter/FieldTransform/testing/CMakeLists.txt b/vtkm/filter/FieldTransform/testing/CMakeLists.txt new file mode 100644 index 000000000..fd25171c6 --- /dev/null +++ b/vtkm/filter/FieldTransform/testing/CMakeLists.txt @@ -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_fieldtransform + vtkm_source) + +vtkm_unit_tests( + SOURCES ${unit_tests} + LIBRARIES ${libraries} + USE_VTKM_JOB_POOL +) diff --git a/vtkm/filter/testing/UnitTestGenerateIds.cxx b/vtkm/filter/FieldTransform/testing/UnitTestGenerateIds.cxx similarity index 98% rename from vtkm/filter/testing/UnitTestGenerateIds.cxx rename to vtkm/filter/FieldTransform/testing/UnitTestGenerateIds.cxx index b3b410746..91f05fe07 100644 --- a/vtkm/filter/testing/UnitTestGenerateIds.cxx +++ b/vtkm/filter/FieldTransform/testing/UnitTestGenerateIds.cxx @@ -7,14 +7,10 @@ // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // PURPOSE. See the above copyright notice for more information. //============================================================================ - -#include - -#include - #include - #include +#include +#include namespace { diff --git a/vtkm/filter/NewFilter.cxx b/vtkm/filter/NewFilter.cxx new file mode 100644 index 000000000..c4d2c428c --- /dev/null +++ b/vtkm/filter/NewFilter.cxx @@ -0,0 +1,132 @@ +//============================================================================ +// 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 +#include +#include + +#include +#include +#include + +#include + +namespace vtkm +{ +namespace filter +{ +namespace +{ +void RunFilter(NewFilter* self, + vtkm::filter::DataSetQueue& input, + vtkm::filter::DataSetQueue& output) +{ + std::pair 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 + +//---------------------------------------------------------------------------- +vtkm::cont::PartitionedDataSet NewFilter::DoExecute(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> futures(static_cast(numThreads)); + for (std::size_t i = 0; i < static_cast(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::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().c_str()); + + // Call `void Derived::PreExecute(input, policy)`, if defined. + this->PreExecute(input); + + // Call `PrepareForExecution` (which should probably be renamed at some point) + vtkm::cont::PartitionedDataSet output = this->DoExecute(input); + + // Call `Derived::PostExecute(input, output, policy)` if defined. + this->PostExecute(input, output); + + 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(numDS, availThreads); + return numThreads; +} + +} // namespace filter +} // namespace vtkm diff --git a/vtkm/filter/NewFilter.h b/vtkm/filter/NewFilter.h new file mode 100644 index 000000000..fe52fd9bc --- /dev/null +++ b/vtkm/filter/NewFilter.h @@ -0,0 +1,365 @@ +//============================================================================ +// 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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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, +/// FilterDataSet, FilterDataSetWithField, 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. MarchingCubes). +/// vtkm::filter::MarchingCubes marchingCubes; +/// +/// // select fieds to map to the output, if different from default which is to +/// // map all input fields. +/// marchingCubes.SetFieldToPass({"var1", "var2"}); +/// +/// // execute the filter on vtkm::cont::DataSet. +/// vtkm::cont::DataSet dsInput = ... +/// auto outputDS = filter.Execute(dsInput); +/// +/// // 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 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 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 +/// +/// Typically, one subclasses one of the immediate subclasses of this class such as +/// FilterField, FilterDataSet, FilterDataSetWithField, 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::Filter. +/// +/// \subsection FilterPreExecutePostExecute PreExecute and PostExecute +/// +/// Subclasses may provide implementations for either or both of the following +/// methods. +/// +/// \code{cpp} +/// +/// template +/// void PreExecute(const vtkm::cont::PartitionedDataSet& input, +/// const vtkm::filter::PolicyBase& policy); +/// +/// template +/// void PostExecute(const vtkm::cont::PartitionedDataSet& input, vtkm::cont::PartitionedDataSet& output +/// const vtkm::filter::PolicyBase& 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 +/// 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 partitions, then +/// these methods provide convenient hooks for the same. +/// +/// \subsection FilterPrepareForExecution PrepareForExecution +/// +/// A concrete subclass of Filter must provide `PrepareForExecution` +/// 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} +/// +/// template +/// vtkm::cont::DataSet PrepareForExecution( +/// const vtkm::cont::DataSet& input, +/// const vtkm::filter::PolicyBase& policy); +/// +/// \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 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 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 PartitionedDataSets cannot be modelled as a reduction of the +/// results, one can implement the following signature. +/// +/// \code{cpp} +/// template +/// vtkm::cont::PartitionedDataSet PrepareForExecution( +/// const vtkm::cont::PartitionedDataSet& input, +/// const vtkm::filter::PolicyBase& policy); +/// \endcode +/// +/// The responsibility of this method is the same, except now the subclass is +/// given full control over the execution, including any mapping of fields to +/// output (described in next sub-section). +/// +/// \subsection FilterMapFieldOntoOutput DoMapField +/// +/// Subclasses may provide `DoMapField` method with the following +/// signature: +/// +/// \code{cpp} +/// +/// template +/// VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result, +/// const vtkm::cont::Field& field, +/// const vtkm::filter::PolicyBase& policy); +/// +/// \endcode +/// +/// 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. +/// +class VTKM_FILTER_CORE_EXPORT NewFilter +{ +public: + VTKM_CONT + virtual ~NewFilter() = default; + + VTKM_CONT + virtual bool CanThread() const { return true; } + + 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 additional field storage to support. + /// + /// When a filter gets a field value from a DataSet, it has to determine what type + /// of storage the array has. Typically this is taken from the default storage + /// types defined in DefaultTypes.h. In some cases it is useful to support additional + /// types. For example, the filter might make sense to support ArrayHandleIndex or + /// ArrayHandleConstant. If so, the storage of those additional types should be + /// listed here. + using AdditionalFieldStorage = vtkm::ListEmpty; + + /// \brief Specify which structured cell sets to support. + /// + /// When a filter gets a cell set from a DataSet, it has to determine what type + /// of concrete cell set it is. This provides a list of supported structured + /// cell sets. + using SupportedStructuredCellSets = VTKM_DEFAULT_CELL_SET_LIST_STRUCTURED; + + /// \brief Specify which unstructured cell sets to support. + /// + /// When a filter gets a cell set from a DataSet, it has to determine what type + /// of concrete cell set it is. This provides a list of supported unstructured + /// cell sets. + using SupportedUnstructuredCellSets = VTKM_DEFAULT_CELL_SET_LIST_UNSTRUCTURED; + + /// \brief Specify which unstructured cell sets to support. + /// + /// When a filter gets a cell set from a DataSet, it has to determine what type + /// of concrete cell set it is. This provides a list of supported cell sets. + using SupportedCellSets = VTKM_DEFAULT_CELL_SET_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 virtual vtkm::cont::DataSet Execute(const vtkm::cont::DataSet& input) = 0; + //@} + + //@{ + /// 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 virtual 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; } + + // TODO: de-virtual, move to protected. + VTKM_CONT + virtual vtkm::Id DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input); + +protected: + vtkm::cont::Invoker Invoke; + vtkm::Id CoordinateSystemIndex = 0; + + //@{ + /// 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. + VTKM_CONT virtual void PreExecute(const vtkm::cont::PartitionedDataSet&) {} + + VTKM_CONT virtual void PostExecute(const vtkm::cont::PartitionedDataSet&, + vtkm::cont::PartitionedDataSet&) + { + } + //@} + + VTKM_CONT virtual vtkm::cont::PartitionedDataSet DoExecute( + const vtkm::cont::PartitionedDataSet& inData); + + static void defaultMapper(vtkm::cont::DataSet& output, const vtkm::cont::Field& field) + { + output.AddField(field); + }; + + template + VTKM_CONT void MapFieldsOntoOutput(const vtkm::cont::DataSet& input, + vtkm::cont::DataSet& output, + Mapper&& mapper) + { + // TODO: in the future of C++20, we can make it a "filtered_view". + 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::filter::FieldSelection FieldsToPass = vtkm::filter::FieldSelection::MODE_ALL; + bool RunFilterWithMultipleThreads = false; +}; +} +} // namespace vtkm::filter + +#endif diff --git a/vtkm/filter/testing/CMakeLists.txt b/vtkm/filter/testing/CMakeLists.txt index 415b15570..3195fd64d 100644 --- a/vtkm/filter/testing/CMakeLists.txt +++ b/vtkm/filter/testing/CMakeLists.txt @@ -37,7 +37,6 @@ set(unit_tests UnitTestFieldToColors.cxx UnitTestGradientExplicit.cxx UnitTestGradientUniform.cxx - UnitTestGenerateIds.cxx UnitTestGhostCellClassify.cxx UnitTestGhostCellRemove.cxx UnitTestHistogramFilter.cxx diff --git a/vtkm/filter/testing/UnitTestContourFilter.cxx b/vtkm/filter/testing/UnitTestContourFilter.cxx index 335264ea2..7356dfbe3 100644 --- a/vtkm/filter/testing/UnitTestContourFilter.cxx +++ b/vtkm/filter/testing/UnitTestContourFilter.cxx @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include diff --git a/vtkm/worklet/testing/UnitTestContour.cxx b/vtkm/worklet/testing/UnitTestContour.cxx index e97405cdc..087d2adf2 100644 --- a/vtkm/worklet/testing/UnitTestContour.cxx +++ b/vtkm/worklet/testing/UnitTestContour.cxx @@ -16,7 +16,7 @@ #include #include -#include +#include #include #include