migrate tutorials to New Filter interface

This commit is contained in:
Li-Ta Lo 2022-05-26 12:52:08 -06:00
parent 10c1682a1a
commit 6ec329bd03
5 changed files with 100 additions and 154 deletions

@ -36,11 +36,16 @@ target_link_libraries(two_filters vtkm_filter vtkm_io)
add_executable(mag_grad mag_grad.cxx)
target_link_libraries(mag_grad vtkm_filter vtkm_io)
# Because mag_grad.cxx creates a worklet with code that
# runs on a GPU, it needs additional information.
vtkm_add_target_information(mag_grad
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES mag_grad.cxx)
if (VTKm_ENABLE_RENDERING)
add_executable(rendering rendering.cxx)
target_link_libraries(rendering vtkm_filter vtkm_io vtkm_rendering)
endif()
endif ()
add_executable(error_handling error_handling.cxx)
target_link_libraries(error_handling vtkm_filter vtkm_io)
@ -50,46 +55,15 @@ target_link_libraries(logging vtkm_filter vtkm_io)
add_executable(point_to_cell point_to_cell.cxx)
target_link_libraries(point_to_cell vtkm_cont vtkm_filter vtkm_io)
vtkm_add_target_information(point_to_cell
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES point_to_cell.cxx)
add_executable(extract_edges extract_edges.cxx)
target_link_libraries(extract_edges vtkm_cont vtkm_filter vtkm_io)
set(tutorial_targets
io
contour
contour_two_fields
two_filters
mag_grad
error_handling
logging
point_to_cell
extract_edges
)
set(tutorial_sources
io.cxx
contour.cxx
contour_two_fields.cxx
two_filters.cxx
mag_grad.cxx
error_handling.cxx
logging.cxx
point_to_cell.cxx
extract_edges.cxx
)
if (VTKm_ENABLE_RENDERING)
list(APPEND tutorial_sources rendering.cxx)
list(APPEND tutorial_targets rendering)
endif()
vtkm_add_target_information(${tutorial_targets}
DROP_UNUSED_SYMBOLS
MODIFY_CUDA_FLAGS
DEVICE_SOURCES
${tutorial_sources})
vtkm_add_target_information(extract_edges
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
DEVICE_SOURCES extract_edges.cxx)
# Copy the data file to be adjacent to the binaries
file(GENERATE OUTPUT "$<TARGET_FILE_DIR:mag_grad>/data/kitchen.vtk" INPUT "${CMAKE_CURRENT_SOURCE_DIR}/data/kitchen.vtk")

@ -21,6 +21,8 @@
#include <vtkm/io/VTKDataSetWriter.h>
#include <vtkm/filter/FilterDataSet.h>
#include <vtkm/filter/MapFieldMergeAverage.h>
#include <vtkm/filter/MapFieldPermutation.h>
#include <vtkm/filter/contour/Contour.h>
#include <vtkm/worklet/WorkletMapTopology.h>
@ -117,95 +119,23 @@ struct EdgeIndicesWorklet : vtkm::worklet::WorkletReduceByKey
namespace
{
class ExtractEdges : public vtkm::filter::FilterDataSet<ExtractEdges>
{
public:
template <typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData,
vtkm::filter::PolicyBase<Policy> policy);
template <typename T, typename StorageType, typename Policy>
VTKM_CONT bool DoMapField(vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& input,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<Policy>& policy);
private:
vtkm::worklet::ScatterCounting::OutputToInputMapType OutputToInputCellMap;
vtkm::worklet::Keys<vtkm::Id2> CellToEdgeKeys;
};
template <typename Policy>
inline VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute(
const vtkm::cont::DataSet& inData,
vtkm::filter::PolicyBase<Policy> policy)
{
auto inCellSet = vtkm::filter::ApplyPolicyCellSet(inData.GetCellSet(), policy, *this);
// First, count the edges in each cell.
vtkm::cont::ArrayHandle<vtkm::IdComponent> edgeCounts;
this->Invoke(CountEdgesWorklet{}, inCellSet, edgeCounts);
// Second, using these counts build a scatter that repeats a cell's visit
// for each edge in the cell.
vtkm::worklet::ScatterCounting scatter(edgeCounts);
this->OutputToInputCellMap = scatter.GetOutputToInputMap(inCellSet.GetNumberOfCells());
vtkm::worklet::ScatterCounting::VisitArrayType outputToInputEdgeMap =
scatter.GetVisitArray(inCellSet.GetNumberOfCells());
// Third, for each edge, extract a canonical id.
vtkm::cont::ArrayHandle<vtkm::Id2> canonicalIds;
this->Invoke(EdgeIdsWorklet{}, scatter, inCellSet, canonicalIds);
// Fourth, construct a Keys object to combine all like edge ids.
this->CellToEdgeKeys = vtkm::worklet::Keys<vtkm::Id2>(canonicalIds);
// Fifth, use a reduce-by-key to extract indices for each unique edge.
vtkm::cont::ArrayHandle<vtkm::Id> connectivityArray;
this->Invoke(EdgeIndicesWorklet{},
this->CellToEdgeKeys,
inCellSet,
this->OutputToInputCellMap,
outputToInputEdgeMap,
vtkm::cont::make_ArrayHandleGroupVec<2>(connectivityArray));
// Sixth, use the created connectivity array to build a cell set.
vtkm::cont::CellSetSingleType<> outCellSet;
outCellSet.Fill(inCellSet.GetNumberOfPoints(), vtkm::CELL_SHAPE_LINE, 2, connectivityArray);
vtkm::cont::DataSet outData;
outData.SetCellSet(outCellSet);
for (vtkm::IdComponent coordSystemIndex = 0;
coordSystemIndex < inData.GetNumberOfCoordinateSystems();
++coordSystemIndex)
{
outData.AddCoordinateSystem(inData.GetCoordinateSystem(coordSystemIndex));
}
return outData;
}
template <typename T, typename StorageType, typename Policy>
inline VTKM_CONT bool ExtractEdges::DoMapField(
VTKM_CONT bool DoMapField(
vtkm::cont::DataSet& result,
const vtkm::cont::ArrayHandle<T, StorageType>& inputArray,
const vtkm::filter::FieldMetadata& fieldMeta,
const vtkm::filter::PolicyBase<Policy>&)
const vtkm::cont::Field& inputField,
const vtkm::worklet::ScatterCounting::OutputToInputMapType& OutputToInputCellMap,
const vtkm::worklet::Keys<vtkm::Id2>& CellToEdgeKeys)
{
vtkm::cont::Field outputField;
if (fieldMeta.IsPointField())
if (inputField.IsFieldPoint())
{
outputField = fieldMeta.AsField(inputArray); // pass through
outputField = inputField; // pass through
}
else if (fieldMeta.IsCellField())
else if (inputField.IsFieldCell())
{
auto outputCellArray = vtkm::worklet::AverageByKey::Run(
this->CellToEdgeKeys,
vtkm::cont::make_ArrayHandlePermutation(this->OutputToInputCellMap, inputArray));
outputField = fieldMeta.AsField(outputCellArray);
vtkm::cont::Field permuted;
vtkm::filter::MapFieldPermutation(inputField, OutputToInputCellMap, permuted);
vtkm::filter::MapFieldMergeAverage(permuted, CellToEdgeKeys, outputField);
}
else
{
@ -217,6 +147,55 @@ inline VTKM_CONT bool ExtractEdges::DoMapField(
return true;
}
class ExtractEdges : public vtkm::filter::NewFilter
{
public:
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inData) override;
};
VTKM_CONT vtkm::cont::DataSet ExtractEdges::DoExecute(const vtkm::cont::DataSet& inData)
{
auto inCellSet = inData.GetCellSet();
// First, count the edges in each cell.
vtkm::cont::ArrayHandle<vtkm::IdComponent> edgeCounts;
this->Invoke(CountEdgesWorklet{}, inCellSet, edgeCounts);
// Second, using these counts build a scatter that repeats a cell's visit
// for each edge in the cell.
vtkm::worklet::ScatterCounting scatter(edgeCounts);
vtkm::worklet::ScatterCounting::OutputToInputMapType OutputToInputCellMap;
OutputToInputCellMap = scatter.GetOutputToInputMap(inCellSet.GetNumberOfCells());
vtkm::worklet::ScatterCounting::VisitArrayType outputToInputEdgeMap =
scatter.GetVisitArray(inCellSet.GetNumberOfCells());
// Third, for each edge, extract a canonical id.
vtkm::cont::ArrayHandle<vtkm::Id2> canonicalIds;
this->Invoke(EdgeIdsWorklet{}, scatter, inCellSet, canonicalIds);
// Fourth, construct a Keys object to combine all like edge ids.
vtkm::worklet::Keys<vtkm::Id2> CellToEdgeKeys;
CellToEdgeKeys = vtkm::worklet::Keys<vtkm::Id2>(canonicalIds);
// Fifth, use a reduce-by-key to extract indices for each unique edge.
vtkm::cont::ArrayHandle<vtkm::Id> connectivityArray;
this->Invoke(EdgeIndicesWorklet{},
CellToEdgeKeys,
inCellSet,
OutputToInputCellMap,
outputToInputEdgeMap,
vtkm::cont::make_ArrayHandleGroupVec<2>(connectivityArray));
// Sixth, use the created connectivity array to build a cell set.
vtkm::cont::CellSetSingleType<> outCellSet;
outCellSet.Fill(inCellSet.GetNumberOfPoints(), vtkm::CELL_SHAPE_LINE, 2, connectivityArray);
auto mapper = [&](auto& outDataSet, const auto& f) {
DoMapField(outDataSet, f, OutputToInputCellMap, CellToEdgeKeys);
};
return this->CreateResult(inData, outCellSet, inData.GetCoordinateSystems(), mapper);
}
}
int main(int argc, char** argv)

@ -28,29 +28,30 @@ struct ComputeMagnitude : vtkm::worklet::WorkletMapField
}
};
#include <vtkm/filter/FilterField.h>
#include <vtkm/filter/NewFilterField.h>
class FieldMagnitude : public vtkm::filter::FilterField<FieldMagnitude>
class FieldMagnitude : public vtkm::filter::NewFilterField
{
public:
using SupportedTypes = vtkm::List<vtkm::Vec3f>;
template <typename ArrayHandleType, typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet,
const ArrayHandleType& inField,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<Policy>)
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet) override
{
const auto& inField = this->GetFieldFromDataSet(inDataSet);
vtkm::cont::ArrayHandle<vtkm::FloatDefault> outField;
this->Invoke(ComputeMagnitude{}, inField, outField);
auto resolveType = [&](const auto& concrete) {
this->Invoke(ComputeMagnitude{}, concrete, outField);
};
this->CastAndCallVecField<3>(inField, resolveType);
std::string outFieldName = this->GetOutputFieldName();
if (outFieldName == "")
{
outFieldName = fieldMetadata.GetName() + "_magnitude";
outFieldName = inField.GetName() + "_magnitude";
}
return vtkm::filter::CreateResult(inDataSet, outField, outFieldName, fieldMetadata);
return this->CreateResultFieldCell(inDataSet, outFieldName, outField);
}
};

@ -46,46 +46,39 @@ struct ConvertPointFieldToCells : vtkm::worklet::WorkletVisitCellsWithPoints
} // namespace worklet
} // namespace vtkm
#include <vtkm/filter/FilterField.h>
#include <vtkm/filter/NewFilterField.h>
namespace vtkm
{
namespace filter
{
struct ConvertPointFieldToCells : vtkm::filter::FilterField<ConvertPointFieldToCells>
struct ConvertPointFieldToCells : vtkm::filter::NewFilterField
{
template <typename ArrayHandleType, typename Policy>
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet,
const ArrayHandleType& inField,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<Policy>);
VTKM_CONT vtkm::cont::DataSet DoExecute(const vtkm::cont::DataSet& inDataSet) override;
};
template <typename ArrayHandleType, typename Policy>
VTKM_CONT cont::DataSet ConvertPointFieldToCells::DoExecute(
const vtkm::cont::DataSet& inDataSet,
const ArrayHandleType& inField,
const vtkm::filter::FieldMetadata& fieldMetadata,
vtkm::filter::PolicyBase<Policy> policy)
VTKM_CONT cont::DataSet ConvertPointFieldToCells::DoExecute(const vtkm::cont::DataSet& inDataSet)
{
VTKM_IS_ARRAY_HANDLE(ArrayHandleType);
const auto& inField = this->GetFieldFromDataSet(inDataSet);
using ValueType = typename ArrayHandleType::ValueType;
vtkm::cont::UnknownArrayHandle outArray;
auto resolveType = [&](const auto& concrete) {
using ValueType = typename std::decay_t<decltype(concrete)>::ValueType;
vtkm::cont::ArrayHandle<ValueType> outField;
this->Invoke(vtkm::worklet::ConvertPointFieldToCells{},
vtkm::filter::ApplyPolicyCellSet(inDataSet.GetCellSet(), policy, *this),
inField,
outField);
vtkm::cont::ArrayHandle<ValueType> outField;
this->Invoke(
vtkm::worklet::ConvertPointFieldToCells{}, inDataSet.GetCellSet(), concrete, outField);
outArray = outField;
};
this->CastAndCallScalarField(inField, resolveType);
std::string outFieldName = this->GetOutputFieldName();
if (outFieldName == "")
{
outFieldName = fieldMetadata.GetName();
outFieldName = inField.GetName();
}
return vtkm::filter::CreateResultFieldCell(inDataSet, outField, outFieldName);
return this->CreateResultFieldCell(inDataSet, outFieldName, outArray);
}
} // namespace filter

@ -12,7 +12,6 @@
#include <vtkm/cont/Initialize.h>
#include <vtkm/io/VTKDataSetReader.h>
#include <vtkm/io/VTKDataSetWriter.h>
#include <vtkm/rendering/Actor.h>
#include <vtkm/rendering/CanvasRayTracer.h>
#include <vtkm/rendering/MapperRayTracer.h>