vtkmAverageToPoints and vtkmAverageToCells fail when points of the wrong association exist.
The vtkmAverageToPoints
and vtkmAverateToCells
filters are fragile in that they break anytime there is a field of the wrong association. The problem is that each filter tries to convert all fields regardless of their association, and if the association is wrong the filter fails. The problem is easy to see when you run the TestVTKGradientAndCorticity
test, which internally runs vtkmAverageToPoints
.
1818/2648 Test: VTK::AcceleratorsVTKmFiltersCxx-TestVTKMGradientAndVorticity
Command: "/Users/4d5/builds/VTK/Debug/bin/vtkAcceleratorsVTKmFiltersCxxTests" "TestVTKMGradientAndVorticity" "-D" "/Users/4d5/builds/VTK/Debug/ExternalData/Testing" "-T" "/Users/4d5/builds/VTK/Debug/Testing/Temporary"
Directory: /Users/4d5/builds/VTK/Debug/Accelerators/Vtkm/Filters/Testing/Cxx
"VTK::AcceleratorsVTKmFiltersCxx-TestVTKMGradientAndVorticity" start time: Mar 20 09:16 MDT
Output:
----------------------------------------------------------
( 0.239s) [main thread ]vtkmAverageToPoints.cxx:171 WARN| vtkmAverageToPoints (0x600001278380): VTK-m failed with message: No field with requested name: coords
Falling back to the default VTK implementation.
<end of output>
Test time = 1.90 sec
----------------------------------------------------------
Test Passed.
"VTK::AcceleratorsVTKmFiltersCxx-TestVTKMGradientAndVorticity" end time: Mar 20 09:16 MDT
"VTK::AcceleratorsVTKmFiltersCxx-TestVTKMGradientAndVorticity" time elapsed: 00:00:01
----------------------------------------------------------
The test passes, but notice the warning. The VTK-m filter failed to the VTK fallback. It shouldn't.
The problem comes from how vtkmAverageToPoints.cxx
iterates over all of the fields (https://gitlab.kitware.com/vtk/vtk/-/blob/master/Accelerators/Vtkm/Filters/vtkmAverageToPoints.cxx#L147). The relevant code is
for (int i = 0; i < in.GetNumberOfFields(); ++i)
{
const auto& name = in.GetField(i).GetName();
filter.SetActiveField(name, vtkm::cont::Field::Association::Cells);
auto result = filter.Execute(in);
The problem is that all the input fields are converted. But if you have a point field, it attempts to convert it from a cell field. That cell field (probably) does not exist, so the filter fails and the exception kicks back to code that throws away any other computations and runs the VTK algorithm. This is particularly bad for vtkmAverageToPoints
because the coordinates are always added as a point field, which means you will always run into this problem. The same problem exists for vtkmAverageToCells
, but it might pass if there are no cell fields.
The fix is simple, skip any fields that are not associated with cells (or points).
for (int i = 0; i < in.GetNumberOfFields(); ++i)
{
const auto& field = in.GetField(i);
if (!field.IsCellField())
{
continue;
}
filter.SetActiveField(field.GetName(), vtkm::cont::Field::Association::Cells);
auto result = filter.Execute(in);