From 0c13917c1e81b1042ffbf72409a19074bb83d99f Mon Sep 17 00:00:00 2001 From: Kenneth Moreland Date: Thu, 2 Feb 2023 16:08:02 -0500 Subject: [PATCH] Change CellAverage to work on fields of any type The previous version of the `CellAverage` filter used a float fallback to handle most array types. The problem with this approach other than converting field types perhaps unexpectantly is that it does not work with every `Vec` size. This change uses the extract by component feature of `UnknownArrayHandle` to handle every array type. To implement this change the `CellAverage` worklet had to be changed to handle recombined vecs. This change resulted in a feature degridation where it can no longer be compiled for inputs of incompatible `Vec` sizes. This feature dates back to when worklets like this were exposed in the interface. This worklet class is now hidden away from the exposed interface, so this degredation should not affect end users. There are some unit tests that use this worklet to test other features, and these had to be updated. --- docs/changelog/interp-any-field.md | 1 + .../testing/UnitTestDataSetPermutation.cxx | 15 ++++-- vtkm/filter/field_conversion/CellAverage.cxx | 12 ++--- .../field_conversion/worklet/CellAverage.h | 46 ++++++------------- .../UnitTestWorkletMapTopologyExplicit.cxx | 14 ++++-- .../UnitTestWorkletMapTopologyUniform.cxx | 6 ++- 6 files changed, 46 insertions(+), 48 deletions(-) diff --git a/docs/changelog/interp-any-field.md b/docs/changelog/interp-any-field.md index bc25c488c..7531d14ce 100644 --- a/docs/changelog/interp-any-field.md +++ b/docs/changelog/interp-any-field.md @@ -13,6 +13,7 @@ to get data from any type of array. The following filters have been updated. * `CleanGrid` + * `CellAverage` * `ClipWithField` * `ClipWithImplicitFunction` * `Contour` diff --git a/vtkm/cont/testing/UnitTestDataSetPermutation.cxx b/vtkm/cont/testing/UnitTestDataSetPermutation.cxx index abe960e9c..a8e6b74a2 100644 --- a/vtkm/cont/testing/UnitTestDataSetPermutation.cxx +++ b/vtkm/cont/testing/UnitTestDataSetPermutation.cxx @@ -105,7 +105,10 @@ void TestDataSet_Explicit() //run a basic for-each topology algorithm on this vtkm::cont::ArrayHandle result; vtkm::worklet::DispatcherMapTopology dispatcher; - dispatcher.Invoke(subset, dataSet.GetField("pointvar"), result); + dispatcher.Invoke( + subset, + dataSet.GetField("pointvar").GetData().AsArrayHandle>(), + result); //iterate same cell 4 times vtkm::Float32 expected[4] = { 30.1667f, 30.1667f, 30.1667f, 30.1667f }; @@ -139,7 +142,10 @@ void TestDataSet_Structured2D() //run a basic for-each topology algorithm on this vtkm::cont::ArrayHandle result; vtkm::worklet::DispatcherMapTopology dispatcher; - dispatcher.Invoke(subset, dataSet.GetField("pointvar"), result); + dispatcher.Invoke( + subset, + dataSet.GetField("pointvar").GetData().AsArrayHandle>(), + result); vtkm::Float32 expected[4] = { 40.1f, 40.1f, 40.1f, 40.1f }; auto resultPortal = result.ReadPortal(); @@ -172,7 +178,10 @@ void TestDataSet_Structured3D() //run a basic for-each topology algorithm on this vtkm::cont::ArrayHandle result; vtkm::worklet::DispatcherMapTopology dispatcher; - dispatcher.Invoke(subset, dataSet.GetField("pointvar"), result); + dispatcher.Invoke( + subset, + dataSet.GetField("pointvar").GetData().AsArrayHandle>(), + result); vtkm::Float32 expected[4] = { 70.2125f, 70.2125f, 70.2125f, 70.2125f }; auto resultPortal = result.ReadPortal(); diff --git a/vtkm/filter/field_conversion/CellAverage.cxx b/vtkm/filter/field_conversion/CellAverage.cxx index 9459ed15d..9e3ef3159 100644 --- a/vtkm/filter/field_conversion/CellAverage.cxx +++ b/vtkm/filter/field_conversion/CellAverage.cxx @@ -28,17 +28,15 @@ vtkm::cont::DataSet CellAverage::DoExecute(const vtkm::cont::DataSet& input) } vtkm::cont::UnknownCellSet inputCellSet = input.GetCellSet(); - vtkm::cont::UnknownArrayHandle outArray; + vtkm::cont::UnknownArrayHandle inArray = field.GetData(); + vtkm::cont::UnknownArrayHandle outArray = inArray.NewInstanceBasic(); auto resolveType = [&](const auto& concrete) { - using T = typename std::decay_t::ValueType; - vtkm::cont::ArrayHandle result; + using T = typename std::decay_t::ValueType::ComponentType; + auto result = outArray.ExtractArrayFromComponents(); this->Invoke(vtkm::worklet::CellAverage{}, inputCellSet, concrete, result); - outArray = result; }; - field.GetData() - .CastAndCallForTypesWithFloatFallback( - resolveType); + inArray.CastAndCallWithExtractedArray(resolveType); std::string outputName = this->GetOutputFieldName(); if (outputName.empty()) diff --git a/vtkm/filter/field_conversion/worklet/CellAverage.h b/vtkm/filter/field_conversion/worklet/CellAverage.h index fe7a632bb..5aca4a941 100644 --- a/vtkm/filter/field_conversion/worklet/CellAverage.h +++ b/vtkm/filter/field_conversion/worklet/CellAverage.h @@ -35,43 +35,25 @@ public: { using PointValueType = typename PointValueVecType::ComponentType; - using InVecSize = - std::integral_constant::NUM_COMPONENTS>; - using OutVecSize = - std::integral_constant::NUM_COMPONENTS>; - using SameLengthVectors = typename std::is_same::type; + VTKM_ASSERT(vtkm::VecTraits::GetNumberOfComponents(pointValues[0]) == + vtkm::VecTraits::GetNumberOfComponents(average)); - this->DoAverage(numPoints, pointValues, average, SameLengthVectors()); - } - -private: - template - VTKM_EXEC void DoAverage(const vtkm::IdComponent& numPoints, - const PointValueVecType& pointValues, - OutType& average, - std::true_type) const - { - using OutComponentType = typename vtkm::VecTraits::ComponentType; - OutType sum = OutType(pointValues[0]); + average = pointValues[0]; for (vtkm::IdComponent pointIndex = 1; pointIndex < numPoints; ++pointIndex) { - // OutType constructor is for when OutType is a Vec. - // static_cast is for when OutType is a small int that gets promoted to int32. - sum = static_cast(sum + OutType(pointValues[pointIndex])); + average += pointValues[pointIndex]; } - // OutType constructor is for when OutType is a Vec. - // static_cast is for when OutType is a small int that gets promoted to int32. - average = static_cast(sum / OutType(static_cast(numPoints))); - } - - template - VTKM_EXEC void DoAverage(const vtkm::IdComponent& vtkmNotUsed(numPoints), - const PointValueVecType& vtkmNotUsed(pointValues), - OutType& vtkmNotUsed(average), - std::false_type) const - { - this->RaiseError("CellAverage called with mismatched Vec sizes for CellAverage."); + using VTraits = vtkm::VecTraits; + using OutComponentType = typename VTraits::ComponentType; + const vtkm::IdComponent numComponents = VTraits::GetNumberOfComponents(average); + for (vtkm::IdComponent cIndex = 0; cIndex < numComponents; ++cIndex) + { + VTraits::SetComponent( + average, + cIndex, + static_cast(VTraits::GetComponent(average, cIndex) / numPoints)); + } } }; } diff --git a/vtkm/worklet/testing/UnitTestWorkletMapTopologyExplicit.cxx b/vtkm/worklet/testing/UnitTestWorkletMapTopologyExplicit.cxx index 8b67487a6..cbd6a53b6 100644 --- a/vtkm/worklet/testing/UnitTestWorkletMapTopologyExplicit.cxx +++ b/vtkm/worklet/testing/UnitTestWorkletMapTopologyExplicit.cxx @@ -114,7 +114,10 @@ static void TestAvgPointToCell() vtkm::cont::ArrayHandle result; vtkm::worklet::DispatcherMapTopology dispatcher; - dispatcher.Invoke(&cellset, dataSet.GetField("pointvar"), &result); + dispatcher.Invoke( + &cellset, + dataSet.GetField("pointvar").GetData().AsArrayHandle>(), + &result); std::cout << "Make sure we got the right answer." << std::endl; VTKM_TEST_ASSERT(test_equal(result.ReadPortal().Get(0), 20.1333f), @@ -126,9 +129,12 @@ static void TestAvgPointToCell() bool exceptionThrown = false; try { - dispatcher.Invoke(dataSet.GetCellSet(), - dataSet.GetField("cellvar"), // should be pointvar - result); + dispatcher.Invoke( + dataSet.GetCellSet(), + dataSet.GetField("cellvar") + .GetData() + .AsArrayHandle>(), // should be pointvar + result); } catch (vtkm::cont::ErrorBadValue& error) { diff --git a/vtkm/worklet/testing/UnitTestWorkletMapTopologyUniform.cxx b/vtkm/worklet/testing/UnitTestWorkletMapTopologyUniform.cxx index 0ed1aea64..4fe9053b5 100644 --- a/vtkm/worklet/testing/UnitTestWorkletMapTopologyUniform.cxx +++ b/vtkm/worklet/testing/UnitTestWorkletMapTopologyUniform.cxx @@ -147,7 +147,7 @@ static void TestAvgPointToCell() // of the way we get cell indices. We need to make that // part more flexible. &cellset, - dataSet.GetField("pointvar"), + dataSet.GetField("pointvar").GetData().AsArrayHandle>(), result); std::cout << "Make sure we got the right answer." << std::endl; @@ -165,7 +165,9 @@ static void TestAvgPointToCell() // of the way we get cell indices. We need to make that // part more flexible. dataSet.GetCellSet().ResetCellSetList(vtkm::cont::CellSetListStructured2D()), - dataSet.GetField("cellvar"), // should be pointvar + dataSet.GetField("cellvar") + .GetData() + .AsArrayHandle>(), // should be pointvar result); } catch (vtkm::cont::ErrorBadValue& error)