From e6ae090e0bf5c4374a1d35669a37c0c767ca4a31 Mon Sep 17 00:00:00 2001 From: Scott Wittenburg <scott.wittenburg@kitware.com> Date: Tue, 11 Feb 2020 10:48:57 -0700 Subject: [PATCH] Move vtkMergeArrays into VTK proper, to be used from within other filters. Also separate out the parallel functionality and move it into a subclass, vtkPMergeArrays. --- Filters/General/CMakeLists.txt | 1 + Filters/General/vtkMergeArrays.cxx | 191 +++++++++++++++++++++++++++ Filters/General/vtkMergeArrays.h | 89 +++++++++++++ Filters/Parallel/CMakeLists.txt | 1 + Filters/Parallel/vtkPMergeArrays.cxx | 65 +++++++++ Filters/Parallel/vtkPMergeArrays.h | 51 +++++++ 6 files changed, 398 insertions(+) create mode 100644 Filters/General/vtkMergeArrays.cxx create mode 100644 Filters/General/vtkMergeArrays.h create mode 100644 Filters/Parallel/vtkPMergeArrays.cxx create mode 100644 Filters/Parallel/vtkPMergeArrays.h diff --git a/Filters/General/CMakeLists.txt b/Filters/General/CMakeLists.txt index 11d19119e0a..e20d462b779 100644 --- a/Filters/General/CMakeLists.txt +++ b/Filters/General/CMakeLists.txt @@ -59,6 +59,7 @@ set(classes vtkLoopBooleanPolyDataFilter vtkMarchingContourFilter vtkMatricizeArray + vtkMergeArrays vtkMergeCells vtkMultiBlockDataGroupFilter vtkMultiBlockFromTimeSeriesFilter diff --git a/Filters/General/vtkMergeArrays.cxx b/Filters/General/vtkMergeArrays.cxx new file mode 100644 index 00000000000..c6e6abe748e --- /dev/null +++ b/Filters/General/vtkMergeArrays.cxx @@ -0,0 +1,191 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkMergeArrays.cxx + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkMergeArrays.h" + +#include "vtkCellData.h" +#include "vtkCompositeDataIterator.h" +#include "vtkCompositeDataSet.h" +#include "vtkDataArray.h" +#include "vtkDataSet.h" +#include "vtkFieldData.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkSmartPointer.h" + +vtkStandardNewMacro(vtkMergeArrays); + +//---------------------------------------------------------------------------- +vtkMergeArrays::vtkMergeArrays() {} + +//---------------------------------------------------------------------------- +vtkMergeArrays::~vtkMergeArrays() {} + +//---------------------------------------------------------------------------- +bool vtkMergeArrays::GetOutputArrayName( + vtkFieldData* arrays, const char* arrayName, int inputIndex, std::string& outputArrayName) +{ + if (arrays->GetAbstractArray(arrayName) == nullptr) + { + return false; + } + outputArrayName = std::string(arrayName) + "_input_" + std::to_string(inputIndex); + return true; +} + +//---------------------------------------------------------------------------- +void vtkMergeArrays::MergeArrays(int inputIndex, vtkFieldData* inputFD, vtkFieldData* outputFD) +{ + if (inputFD == nullptr || outputFD == nullptr) + { + return; + } + + std::string outputArrayName; + int numArrays = inputFD->GetNumberOfArrays(); + for (int arrayIdx = 0; arrayIdx < numArrays; ++arrayIdx) + { + vtkAbstractArray* array = inputFD->GetAbstractArray(arrayIdx); + if (this->GetOutputArrayName(outputFD, array->GetName(), inputIndex, outputArrayName)) + { + vtkAbstractArray* newArray = array->NewInstance(); + if (vtkDataArray* newDataArray = vtkDataArray::SafeDownCast(newArray)) + { + newDataArray->ShallowCopy(vtkDataArray::SafeDownCast(array)); + } + else + { + newArray->DeepCopy(array); + } + newArray->SetName(outputArrayName.c_str()); + outputFD->AddArray(newArray); + newArray->FastDelete(); + } + else + { + outputFD->AddArray(array); + } + } +} + +//---------------------------------------------------------------------------- +int vtkMergeArrays::MergeDataObjectFields(vtkDataObject* input, int idx, vtkDataObject* output) +{ + int checks[vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES]; + for (int attr = 0; attr < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; attr++) + { + checks[attr] = output->GetNumberOfElements(attr) == input->GetNumberOfElements(attr) ? 0 : 1; + } + int globalChecks[vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES]; + + for (int i = 0; i < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; ++i) + { + globalChecks[i] = checks[i]; + } + + for (int attr = 0; attr < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; attr++) + { + if (globalChecks[attr] == 0) + { + // only merge arrays when the number of elements in the input and output are the same + this->MergeArrays( + idx, input->GetAttributesAsFieldData(attr), output->GetAttributesAsFieldData(attr)); + } + } + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkMergeArrays::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_IS_REPEATABLE(), 1); + return 1; +} + +//---------------------------------------------------------------------------- +int vtkMergeArrays::RequestData(vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, vtkInformationVector* outputVector) +{ + int num = inputVector[0]->GetNumberOfInformationObjects(); + if (num < 1) + { + return 0; + } + // get the output info object + vtkInformation* outInfo = outputVector->GetInformationObject(0); + vtkDataObject* output = outInfo->Get(vtkDataObject::DATA_OBJECT()); + + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkDataObject* input = inInfo->Get(vtkDataObject::DATA_OBJECT()); + + vtkCompositeDataSet* cOutput = vtkCompositeDataSet::SafeDownCast(output); + if (cOutput) + { + vtkCompositeDataSet* cInput = vtkCompositeDataSet::SafeDownCast(input); + cOutput->CopyStructure(cInput); + vtkSmartPointer<vtkCompositeDataIterator> iter; + iter.TakeReference(cInput->NewIterator()); + iter->InitTraversal(); + for (; !iter->IsDoneWithTraversal(); iter->GoToNextItem()) + { + if (vtkDataSet* tmpIn = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject())) + { + vtkDataSet* tmpOut = tmpIn->NewInstance(); + tmpOut->ShallowCopy(tmpIn); + cOutput->SetDataSet(iter, tmpOut); + tmpOut->Delete(); + } + } + } + else + { + output->ShallowCopy(input); + } + + for (int idx = 1; idx < num; ++idx) + { + inInfo = inputVector[0]->GetInformationObject(idx); + input = inInfo->Get(vtkDataObject::DATA_OBJECT()); + if (!this->MergeDataObjectFields(input, idx, output)) + { + return 0; + } + vtkCompositeDataSet* cInput = vtkCompositeDataSet::SafeDownCast(input); + if (cOutput && cInput) + { + vtkSmartPointer<vtkCompositeDataIterator> iter; + iter.TakeReference(cInput->NewIterator()); + iter->InitTraversal(); + for (; !iter->IsDoneWithTraversal(); iter->GoToNextItem()) + { + vtkDataObject* tmpIn = iter->GetCurrentDataObject(); + vtkDataObject* tmpOut = cOutput->GetDataSet(iter); + if (!this->MergeDataObjectFields(tmpIn, idx, tmpOut)) + { + return 0; + } + } + } + } + return 1; +} + +//---------------------------------------------------------------------------- +void vtkMergeArrays::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} diff --git a/Filters/General/vtkMergeArrays.h b/Filters/General/vtkMergeArrays.h new file mode 100644 index 00000000000..fe972f47e41 --- /dev/null +++ b/Filters/General/vtkMergeArrays.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkMergeArrays.h + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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. + +=========================================================================*/ +/** + * @class vtkMergeArrays + * @brief Multiple inputs with one output. + * + * vtkMergeArrays tries to put all arrays from all inputs into one output. + * The output data object is the same as the first data input. + * The filter checks for a consistent number of points and cells with + * respect to the first input, but does not check any more. Any inputs + * which do not have the correct number of points or cells are ignored + * for that type of data set attribute. When adding new arrays, if there + * is an existing array of the same name and attribute type, the new array + * will have the name mangled to be the original array name plus + * `_input_<inputid>` where `<inputid>` is the id/index of the input filter + * that is providing that array. + */ + +#ifndef vtkMergeArrays_h +#define vtkMergeArrays_h + +#include "vtkFiltersGeneralModule.h" // For export macro +#include "vtkPassInputTypeAlgorithm.h" + +#include <string> // Needed for protected method argument + +class vtkDataSet; +class vtkFieldData; + +class VTKFILTERSGENERAL_EXPORT vtkMergeArrays : public vtkPassInputTypeAlgorithm +{ +public: + static vtkMergeArrays* New(); + + vtkTypeMacro(vtkMergeArrays, vtkPassInputTypeAlgorithm); + void PrintSelf(ostream& os, vtkIndent indent) override; + +protected: + vtkMergeArrays(); + ~vtkMergeArrays() override; + + //@{ + /** + * Given an existing set of output arrays and an array name and input data set + * index, return an appropriate name to use for the output array. Returns true + * if the name is a new name and false if not. + */ + virtual bool GetOutputArrayName( + vtkFieldData* arrays, const char* inArrayName, int inputIndex, std::string& outArrayName); + //@} + + //@{ + /** + * Add input field arrays to output, mangling output array names as needed + * based on inputIndex. + */ + void MergeArrays(int inputIndex, vtkFieldData* inputFD, vtkFieldData* outputFD); + + //@{ + /** + * For a given input and index, add data arrays to the output. Returns 1 for + * success and 0 for failure. + */ + virtual int MergeDataObjectFields(vtkDataObject* input, int inputIndex, vtkDataObject* output); + //@} + + // see algorithm for more info + int FillInputPortInformation(int port, vtkInformation* info) override; + + int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override; + +private: + vtkMergeArrays(const vtkMergeArrays&) = delete; + void operator=(const vtkMergeArrays&) = delete; +}; + +#endif diff --git a/Filters/Parallel/CMakeLists.txt b/Filters/Parallel/CMakeLists.txt index 4014a68b46f..613c430a154 100644 --- a/Filters/Parallel/CMakeLists.txt +++ b/Filters/Parallel/CMakeLists.txt @@ -21,6 +21,7 @@ set(classes vtkPKdTree vtkPLinearExtrusionFilter vtkPMaskPoints + vtkPMergeArrays vtkPOutlineCornerFilter vtkPOutlineFilter vtkPOutlineFilterInternals diff --git a/Filters/Parallel/vtkPMergeArrays.cxx b/Filters/Parallel/vtkPMergeArrays.cxx new file mode 100644 index 00000000000..c2649e1ab41 --- /dev/null +++ b/Filters/Parallel/vtkPMergeArrays.cxx @@ -0,0 +1,65 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkPMergeArrays.cxx + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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 "vtkPMergeArrays.h" +#include "vtkDataObject.h" +#include "vtkMultiProcessController.h" +#include "vtkObjectFactory.h" + +vtkStandardNewMacro(vtkPMergeArrays); + +//---------------------------------------------------------------------------- +vtkPMergeArrays::vtkPMergeArrays() {} + +//---------------------------------------------------------------------------- +void vtkPMergeArrays::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +int vtkPMergeArrays::MergeDataObjectFields(vtkDataObject* input, int idx, vtkDataObject* output) +{ + int checks[vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES]; + for (int attr = 0; attr < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; attr++) + { + checks[attr] = output->GetNumberOfElements(attr) == input->GetNumberOfElements(attr) ? 0 : 1; + } + int globalChecks[vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES]; + auto controller = vtkMultiProcessController::GetGlobalController(); + if (controller == nullptr) + { + for (int i = 0; i < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; ++i) + { + globalChecks[i] = checks[i]; + } + } + else + { + controller->AllReduce( + checks, globalChecks, vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES, vtkCommunicator::MAX_OP); + } + + for (int attr = 0; attr < vtkDataObject::NUMBER_OF_ATTRIBUTE_TYPES; attr++) + { + if (globalChecks[attr] == 0) + { + // only merge arrays when the number of elements in the input and output are the same + this->MergeArrays( + idx, input->GetAttributesAsFieldData(attr), output->GetAttributesAsFieldData(attr)); + } + } + + return 1; +} diff --git a/Filters/Parallel/vtkPMergeArrays.h b/Filters/Parallel/vtkPMergeArrays.h new file mode 100644 index 00000000000..4614fff3f8b --- /dev/null +++ b/Filters/Parallel/vtkPMergeArrays.h @@ -0,0 +1,51 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkPMergeArrays.h + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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. + +=========================================================================*/ +/** + * @class vtkPMergeArrays + * @brief Multiple inputs with one output, parallel version + * + * Like it's super class, this filter tries to combine all arrays from + * inputs into one output. + * + * @sa + * vtkMergeArrays + */ + +#ifndef vtkPMergeArrays_h +#define vtkPMergeArrays_h + +#include "vtkFiltersParallelModule.h" // For export macro +#include "vtkMergeArrays.h" + +class VTKFILTERSPARALLEL_EXPORT vtkPMergeArrays : public vtkMergeArrays +{ +public: + vtkTypeMacro(vtkPMergeArrays, vtkMergeArrays); + void PrintSelf(ostream& os, vtkIndent indent) override; + + static vtkPMergeArrays* New(); + +protected: + vtkPMergeArrays(); + ~vtkPMergeArrays() override {} + + int MergeDataObjectFields(vtkDataObject* input, int idx, vtkDataObject* output) override; + +private: + vtkPMergeArrays(const vtkPMergeArrays&) = delete; + void operator=(const vtkPMergeArrays&) = delete; +}; + +#endif -- GitLab