restore deprecated filter::GenerateIds

update comments

privatize DoExecute

remove Pre|PostExecute

more Eecute -> DoExecute changes

fixed a typo so GeneratedIds.h gets installed
This commit is contained in:
Li-Ta Lo 2021-12-09 17:28:44 -07:00
parent 130d0d9dfe
commit 0e3cc80767
7 changed files with 118 additions and 140 deletions

@ -89,6 +89,7 @@ set(extra_headers
ExternalFaces.h ExternalFaces.h
FieldSelection.h FieldSelection.h
FieldToColors.h FieldToColors.h
GenerateIds.h
GhostCellClassify.h GhostCellClassify.h
GhostCellRemove.h GhostCellRemove.h
Histogram.h Histogram.h

40
vtkm/filter/GenerateIds.h Normal file

@ -0,0 +1,40 @@
//============================================================================
// 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_GenerateIds_h
#define vtk_m_filter_GenerateIds_h
#include <vtkm/Deprecated.h>
#include <vtkm/filter/field_transform/GenerateIds.h>
namespace vtkm
{
namespace filter
{
VTKM_DEPRECATED(
1.8,
"Use vtkm/filter/field_transform/GenerateIds.h instead of vtkm/filter/GenerateIds.h.")
inline void GenerateIds_deprecated() {}
inline void GenerateIds_deprecated_warning()
{
GenerateIds_deprecated();
}
class VTKM_DEPRECATED(1.8, "Use vtkm::filter::field_transform::GenerateIds.") GenerateIds
: public vtkm::filter::field_transform::GenerateIds
{
using field_transform::GenerateIds::GenerateIds;
};
}
} // namespace vtkm::filter
#endif //vtk_m_filter_GenerateIds_h

@ -82,6 +82,7 @@ vtkm::cont::PartitionedDataSet NewFilter::DoExecute(const vtkm::cont::Partitione
return output; return output;
} }
vtkm::cont::DataSet NewFilter::Execute(const vtkm::cont::DataSet& input) vtkm::cont::DataSet NewFilter::Execute(const vtkm::cont::DataSet& input)
{ {
return this->DoExecute(input); return this->DoExecute(input);
@ -94,12 +95,7 @@ vtkm::cont::PartitionedDataSet NewFilter::Execute(const vtkm::cont::PartitionedD
(int)input.GetNumberOfPartitions(), (int)input.GetNumberOfPartitions(),
vtkm::cont::TypeToString<decltype(*this)>().c_str()); vtkm::cont::TypeToString<decltype(*this)>().c_str());
this->PreExecute(input);
vtkm::cont::PartitionedDataSet output = this->DoExecute(input); vtkm::cont::PartitionedDataSet output = this->DoExecute(input);
this->PostExecute(input, output);
return output; return output;
} }

@ -25,135 +25,116 @@ namespace filter
{ {
/// \brief base class for all filters. /// \brief base class for all filters.
/// ///
/// This is the base class for all filters. To add a new filter, one can /// This is the base class for all filters. To add a new filter, one can subclass this (or any of
/// subclass this (or any of the existing subclasses e.g. FilterField, /// the existing subclasses e.g. FilterField, FilterParticleAdvection, etc.) and implement relevant
/// FilterParticleAdvection, etc.) and implement relevant methods. /// methods.
/// ///
/// \section FilterUsage Usage /// \section FilterUsage Usage
/// ///
/// To execute a filter, one typically calls the `auto result = /// To execute a filter, one typically calls the `auto result = filter.Execute(input)`. Typical
/// filter.Execute(input)`. Typical usage is as follows: /// usage is as follows:
/// ///
/// \code{cpp} /// \code{cpp}
/// ///
/// // create the concrete subclass (e.g. MarchingCubes). /// // create the concrete subclass (e.g. Contour).
/// vtkm::filter::MarchingCubes marchingCubes; /// vtkm::filter::contour::Contour contour;
/// ///
/// // select fieds to map to the output, if different from default which is to /// // select fields to map to the output, if different from default which is to map all input
/// // map all input fields. /// // fields.
/// marchingCubes.SetFieldToPass({"var1", "var2"}); /// contour.SetFieldToPass({"var1", "var2"});
/// ///
/// // execute the filter on vtkm::cont::DataSet. /// // execute the filter on vtkm::cont::DataSet.
/// vtkm::cont::DataSet dsInput = ... /// vtkm::cont::DataSet dsInput = ...
/// auto outputDS = filter.Execute(dsInput); /// auto outputDS = contour.Execute(dsInput);
/// ///
/// // or, execute on a vtkm::cont::PartitionedDataSet /// // or, execute on a vtkm::cont::PartitionedDataSet
/// vtkm::cont::PartitionedDataSet mbInput = ... /// vtkm::cont::PartitionedDataSet mbInput = ...
/// auto outputMB = filter.Execute(mbInput); /// auto outputMB = contour.Execute(mbInput);
/// \endcode /// \endcode
/// ///
/// `Execute` methods take in the input DataSet or PartitionedDataSet to /// `Execute` methods take in the input DataSet or PartitionedDataSet to process and return the
/// process and return the result. The type of the result is same as the input /// result. The type of the result is same as the input type, thus `Execute(DataSet&)` returns
/// type, thus `Execute(DataSet&)` returns a DataSet while /// a DataSet while `Execute(PartitionedDataSet&)` returns a PartitionedDataSet.
/// `Execute(PartitionedDataSet&)` returns a PartitionedDataSet.
/// ///
/// The pure virtual function `Execute(DataSet&)` is the main extension point of the /// `Execute` simply calls the pure virtual function `DoExecute(DataSet&)` which is the main
/// Filter interface. Filter developer needs to override `Execute(DataSet)` to implement /// extension point of the Filter interface. Filter developer needs to override
/// the business logic of filtering operations on a single DataSet. /// `DoExecute(DataSet)` to implement the business logic of filtering operations on a single
/// DataSet.
/// ///
/// The default implementation of `Execute(PartitionedDataSet&)` is merely provided for /// The default implementation of `Execute(PartitionedDataSet&)` is merely provided for
/// convenience. Internally, it iterates DataSets of a PartitionedDataSet and pass /// convenience. Internally, it calls `DoExecute(PartitionedDataSet)` to iterate DataSets
/// each individual DataSets to `Execute(DataSet&)`, possibly in a multi-threaded setting. /// of a PartitionedDataSet and pass each individual DataSets to `DoExecute(DataSet&)`,
/// Developer of `Execute(DataSet&)` needs to indicate the thread-safeness of `Execute(DataSet&)` /// possibly in a multi-threaded setting. Developer of `DoExecute(DataSet&)` needs to indicate
/// by overriding the `CanThread()` virtual method which by default returns `true`. /// 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 /// 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 /// for-each loop on the component DataSets, filter implementor needs to override the
/// `Execute(PartitionedDataSet&)`. See the implementation of /// `DoExecute(PartitionedDataSet&)`. See the implementation of
/// `FilterParticleAdvection::Execute(PartitionedDataSet&)` for an example. /// `FilterParticleAdvection::Execute(PartitionedDataSet&)` for an example.
/// ///
/// \section FilterSubclassing Subclassing /// \section FilterSubclassing Subclassing
/// ///
/// Typically, one subclasses one of the immediate subclasses of this class such as /// In many uses cases, one subclasses one of the immediate subclasses of this class such as
/// FilterField, FilterParticleAdvection, etc. Those may impose /// FilterField, FilterParticleAdvection, etc. Those may impose additional constraints on the
/// additional constraints on the methods to implement in the subclasses. /// methods to implement in the subclasses. Here, we describes the things to consider when directly
/// Here, we describes the things to consider when directly subclassing /// subclassing vtkm::filter::NewFilter.
/// vtkm::filter::Filter.
///
/// \subsection FilterPreExecutePostExecute PreExecute and PostExecute
///
/// Subclasses may provide implementations for either or both of the following protected
/// methods.
///
/// \code{cpp}
///
/// void PreExecute(const vtkm::cont::PartitionedDataSet& input);
///
/// void PostExecute(const vtkm::cont::PartitionedDataSet& input,
/// vtkm::cont::PartitionedDataSet& output);
///
/// \endcode
///
/// As the name suggests, these are called and the before the beginning and after the end of
/// iterative `Filter::Execute(DataSet&)` calls. 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 to do 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 FilterExecution Execute /// \subsection FilterExecution Execute
/// ///
/// A concrete subclass of Filter must provide `Execute` implementation that provides the meat /// 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 /// for the filter i.e. the implementation for the filter's data processing logic. There are two
/// two signatures available; which one to implement depends on the nature of the filter. /// 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 /// Let's consider simple filters that do not need to do anything special to handle
/// handle PartitionedDataSet e.g. clip, contour, etc. These are the filters /// PartitionedDataSet e.g. clip, contour, etc. These are the filters where executing the filter
/// where executing the filter on a PartitionedDataSet simply means executing /// on a PartitionedDataSet simply means executing the filter on one partition at a time and
/// the filter on one partition at a time and packing the output for each /// packing the output for each iteration info the result PartitionedDataSet. For such filters,
/// iteration info the result PartitionedDataSet. For such filters, one must /// one must implement the following signature.
/// implement the following signature.
/// ///
/// \code{cpp} /// \code{cpp}
/// ///
/// vtkm::cont::DataSet Execution(const vtkm::cont::DataSet& input); /// vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input);
/// ///
/// \endcode /// \endcode
/// ///
/// The role of this method is to execute on the input dataset and generate the /// The role of this method is to execute on the input dataset and generate the result and return
/// result and return it. If there are any errors, the subclass must throw an /// it. If there are any errors, the subclass must throw an exception
/// exception (e.g. `vtkm::cont::ErrorFilterExecution`). /// (e.g. `vtkm::cont::ErrorFilterExecution`).
/// ///
/// In this simple case, the Filter superclass handles iterating over multiple /// In this simple case, the NewFilter superclass handles iterating over multiple partitions in the
/// partitions in the input PartitionedDataSet and calling /// input PartitionedDataSet and calling `DoExecute(DataSet&)` iteratively.
/// `Execute(DataSet&)` iteratively.
/// ///
/// The aforementioned approach is also suitable for filters that need special /// The aforementioned approach is also suitable for filters that need special handling for
/// handling for PartitionedDataSets which can be modelled as PreExecute and /// PartitionedDataSets that requires certain cross DataSet operations (usually scatter/gather
/// PostExecute steps (e.g. `vtkm::filter::Histogram`). /// and reduction on DataSets) before and/or after the per DataSet operation. This can be done by
/// /// overriding `DoExecute(PartitionedDataSet&)` while calling to the base class
/// For more complex filters, like streamlines, particle tracking, where the /// `DoExecute(PartitionedDataSet&) as helper function for iteration on DataSets.
/// processing of PartitionedDataSets cannot be modelled as a reduction of the
/// results, one can implement the following signature.
/// ///
/// \code{cpp} /// \code{cpp}
/// vtkm::cont::PartitionedDataSet Execute( /// vtkm::cont::PartitionedDataSet FooFilter::DoExecute(
/// const vtkm::cont::PartitionedDataSet& input); /// const vtkm::cont::PartitionedDataSet& input)
/// {
/// // Do pre execute stuff, e.g. scattering to each DataSet
/// auto output = this->NewFilter::DoExecute(input);
/// // Do post execute stuff, e.g gather/reduce from DataSets
/// return output;
/// }
/// \endcode /// \endcode
/// ///
/// The responsibility of this method is the same, except now the subclass is /// For more complex filters, like streamlines, particle tracking, where the processing of
/// given full control over the execution, including any mapping of fields to /// PartitionedDataSets cannot be modelled as mapping and reduction operation on DataSet, one
/// output (described in next sub-section). /// needs fully implement `DoExecute(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 /// \subsection FilterMappingFields MapFieldsOntoOutput
/// ///
/// For subclasses that map input fields into output fields, the implementation of its /// For subclasses that map input fields into output fields, the implementation of its
/// `Execute(DataSet&)` should call `Filter::MapFieldsOntoOutput` with a properly defined /// `DoExecute(DataSet&)` should call `NewFilter::MapFieldsOntoOutput` with a properly defined
/// `Mapper`, before returning the output DataSet. For example: /// `Mapper`, before returning the output DataSet. For example:
/// ///
/// \code{cpp} /// \code{cpp}
/// VTKM_CONT DataSet SomeFilter::Execute(const vtkm::cont::DataSet& input) /// VTKM_CONT DataSet SomeFilter::DoExecute(const vtkm::cont::DataSet& input)
/// { /// {
/// vtkm::cont::DataSet output; /// vtkm::cont::DataSet output;
/// output = ... // Generation of the new DataSet /// output = ... // Generation of the new DataSet
@ -174,28 +155,28 @@ namespace filter
/// Mapper to map the input Field to output Field. For simple filters that just pass on input /// 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 /// fields to the output DataSet without any computation, an overload of
/// `MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output)` is also /// `MapFieldsOntoOutput(const vtkm::cont::DataSet& input, vtkm::cont::DataSet& output)` is also
/// provided as a convenience that uses the default mapper which trivially add input Field to /// provided as a convenience that uses the default mapper which trivially adds input Field to
/// output DaaSet (via a shallow copy). /// output DaaSet (via a shallow copy).
/// ///
/// \subsection FilterThreadSafety CanThread /// \subsection FilterThreadSafety CanThread
/// ///
/// By default, the implementation of `Execute(DataSet&)` should model a *pure function*, i.e. it /// 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 /// does not have any mutable shared state. This makes it thread-safe by default and allows
/// the default implementation of `Execute(PartitionedDataSet&)` to be simply a parallel for-each, /// the default implementation of `DoExecute(PartitionedDataSet&)` to be simply a parallel for-each,
/// thus facilitates multi-threaded execution without any lock. /// thus facilitates multi-threaded execution without any lock.
/// ///
/// Many legacy (VTKm 1.x) filter implementations needed to store states between the mesh generation /// 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 /// 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 /// 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, /// 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 `Execute(DataSet&)`, we have eliminated most /// 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 /// 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 /// require passing information between these two phases can now use local variables within the
/// `Execute(DataSet&)`. For example: /// `DoExecute(DataSet&)`. For example:
/// ///
/// \code{cpp} /// \code{cpp}
/// struct SharedState; // shared states between mesh generation and field mapping. /// struct SharedState; // shared states between mesh generation and field mapping.
/// VTKM_CONT DataSet ThreadSafeFilter::Execute(const vtkm::cont::DataSet& input) /// 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. /// // 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 /// // Each invocation of Execute(DataSet) in the multi-threaded execution of
@ -230,36 +211,6 @@ namespace filter
/// Implementations of Filter subclass can also override /// Implementations of Filter subclass can also override
/// `DetermineNumberOfThreads()` to provide implementation specific heuristic. /// `DetermineNumberOfThreads()` to provide implementation specific heuristic.
/// ///
/// \subsection FilterNameLookup Overriding Overloaded Functions
/// Since we have two overloads of `Execute`, we need to work with C++'s rule for name lookup for
/// inherited, overloaded functions when overriding them. In most uses cases, we intend to only
/// override the `Execute(DataSet&)` overload in an implementation of a NewFilter subclass, such as
///
/// \code{cpp}
/// class FooFilter : public NewFilter
/// {
/// ...
/// vtkm::cont::DataSet Execute(const vtkm::cont::DataSet& input) override;
/// ...
/// }
/// \endcode
///
/// However, the compiler will stop the name lookup process once it sees the
/// `FooFilter::Execute(DataSet)`. When a user calls `FooFilter::Execute(PartitionedDataSet&)`,
/// the compiler will not find the overload from the base class `NewFilter`, resulting in failed
/// overload resolution. The solution to such a problem is to use a using-declaration in the
/// subclass definition to bring the `NewFilter::Execute(PartitionedDataSet&)` into scope for
/// name lookup. For example:
///
/// \code{cpp}
/// class FooFilter : public NewFilter
/// {
/// ...
/// using vtkm::filter::NewFilter::Execute; // bring overloads of Execute into name lookup
/// vtkm::cont::DataSet Execute(const vtkm::cont::DataSet& input) override;
/// ...
/// }
/// \endcode
class VTKM_FILTER_CORE_EXPORT NewFilter class VTKM_FILTER_CORE_EXPORT NewFilter
{ {
public: public:
@ -391,18 +342,7 @@ private:
VTKM_CONT VTKM_CONT
virtual vtkm::Id DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input); virtual vtkm::Id DetermineNumberOfThreads(const vtkm::cont::PartitionedDataSet& input);
//@{ // Note: In C++, subclasses can override private methods of superclass.
/// 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::DataSet DoExecute(const vtkm::cont::DataSet& inData) = 0; VTKM_CONT virtual vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) = 0;
VTKM_CONT virtual vtkm::cont::PartitionedDataSet DoExecute( VTKM_CONT virtual vtkm::cont::PartitionedDataSet DoExecute(
const vtkm::cont::PartitionedDataSet& inData); const vtkm::cont::PartitionedDataSet& inData);

@ -7,7 +7,7 @@
## 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.
##============================================================================ ##============================================================================
set(fieldt_ransform_headers set(field_transform_headers
GenerateIds.h) GenerateIds.h)
set(field_transform_sources_device set(field_transform_sources_device
GenerateIds.cxx) GenerateIds.cxx)

@ -7,8 +7,8 @@
// 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.
//============================================================================ //============================================================================
#ifndef vtk_m_filter_GenerateIds_h #ifndef vtk_m_filter_field_transform_GenerateIds_h
#define vtk_m_filter_GenerateIds_h #define vtk_m_filter_field_transform_GenerateIds_h
#include <vtkm/filter/NewFilter.h> #include <vtkm/filter/NewFilter.h>
#include <vtkm/filter/field_transform/vtkm_filter_field_transform_export.h> #include <vtkm/filter/field_transform/vtkm_filter_field_transform_export.h>
@ -85,10 +85,11 @@ public:
bool GetUseFloat() const { return this->UseFloat; } bool GetUseFloat() const { return this->UseFloat; }
void SetUseFloat(bool flag) { this->UseFloat = flag; } void SetUseFloat(bool flag) { this->UseFloat = flag; }
private:
vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override; vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& input) override;
}; };
} // namespace field_transform } // namespace field_transform
} // namespace vtkm::filter } // namespace vtkm::filter
} // namespace vtkm } // namespace vtkm
#endif //vtk_m_filter_GenerateIds_h #endif //vtk_m_filter_field_transform_GenerateIds_h

@ -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/field_transform/GenerateIds.h> #include <vtkm/filter/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::field_transform::GenerateIds genIds; vtkm::filter::GenerateIds genIds;
genIds.SetUseFloat(true); genIds.SetUseFloat(true);
genIds.SetGeneratePointIds(false); genIds.SetGeneratePointIds(false);
genIds.SetCellFieldName("cellvar"); genIds.SetCellFieldName("cellvar");