From ed8d31b614155b926d67942ddfd2261689d65cdf Mon Sep 17 00:00:00 2001 From: Spiros Tsalikis Date: Tue, 17 Mar 2026 16:12:49 -0400 Subject: [PATCH 1/3] vtkAggregateDataSetFilter: Cleanup code --- .../Parallel/vtkAggregateDataSetFilter.cxx | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/Filters/Parallel/vtkAggregateDataSetFilter.cxx b/Filters/Parallel/vtkAggregateDataSetFilter.cxx index ca11b4a30c0..9f7a40284b2 100644 --- a/Filters/Parallel/vtkAggregateDataSetFilter.cxx +++ b/Filters/Parallel/vtkAggregateDataSetFilter.cxx @@ -32,8 +32,9 @@ void vtkAggregateDataSetFilter::SetNumberOfTargetProcesses(int tp) { if (tp != this->NumberOfTargetProcesses) { - int numProcs = vtkMultiProcessController::GetGlobalController()->GetNumberOfProcesses(); - if (tp > 0 && tp <= numProcs) + const int numberOfProcesses = + vtkMultiProcessController::GetGlobalController()->GetNumberOfProcesses(); + if (tp > 0 && tp <= numberOfProcesses) { this->NumberOfTargetProcesses = tp; this->Modified(); @@ -43,9 +44,9 @@ void vtkAggregateDataSetFilter::SetNumberOfTargetProcesses(int tp) this->NumberOfTargetProcesses = 1; this->Modified(); } - else if (tp > numProcs && this->NumberOfTargetProcesses != numProcs) + else if (tp > numberOfProcesses && this->NumberOfTargetProcesses != numberOfProcesses) { - this->NumberOfTargetProcesses = numProcs; + this->NumberOfTargetProcesses = numberOfProcesses; this->Modified(); } } @@ -71,16 +72,16 @@ int vtkAggregateDataSetFilter::RequestData( { input = vtkDataSet::GetData(inputVector[0], 0); } + if (!input) + { + return 1; + } vtkMultiProcessController* controller = vtkMultiProcessController::GetGlobalController(); - - int numberOfProcesses = controller->GetNumberOfProcesses(); + const int numberOfProcesses = controller->GetNumberOfProcesses(); if (numberOfProcesses == this->NumberOfTargetProcesses) { - if (input) - { - output->ShallowCopy(input); - } + output->ShallowCopy(input); return 1; } @@ -102,13 +103,14 @@ int vtkAggregateDataSetFilter::RequestData( } else { - int localProcessId = controller->GetLocalProcessId(); - int numberOfProcessesPerGroup = numberOfProcesses / this->NumberOfTargetProcesses; + // group processes in round robin-fashion + const int localProcessId = controller->GetLocalProcessId(); + const auto divResult = std::div(numberOfProcesses, this->NumberOfTargetProcesses); + const int numberOfProcessesPerGroup = divResult.quot; int localColor = localProcessId / numberOfProcessesPerGroup; - if (numberOfProcesses % this->NumberOfTargetProcesses) + if (divResult.rem) { - double d = 1. * numberOfProcesses / this->NumberOfTargetProcesses; - localColor = int(localProcessId / d); + localColor = static_cast(localProcessId / (1.0 * numberOfProcessesPerGroup)); } subController.TakeReference(controller->PartitionController(localColor, 0)); } @@ -121,7 +123,7 @@ int vtkAggregateDataSetFilter::RequestData( subController->AllGather(&numPoints, pointCount.data(), 1); // The first process in the subcontroller to have points is the one that data will - // be aggregated to. All of the other processes send their data set to that process. + // be aggregated to. All the other processes send their data set to that process. int receiveProc = 0; vtkIdType maxVal = 0; for (int i = 0; i < subNumProcs; i++) @@ -162,10 +164,9 @@ int vtkAggregateDataSetFilter::RequestData( else if (input->IsA("vtkPolyData")) { vtkNew appendFilter; - for (std::vector>::iterator it = recvBuffer.begin(); - it != recvBuffer.end(); ++it) + for (const vtkSmartPointer& dObj : recvBuffer) { - appendFilter->AddInputData(vtkPolyData::SafeDownCast(*it)); + appendFilter->AddInputData(vtkPolyData::SafeDownCast(dObj)); } appendFilter->Update(); output->ShallowCopy(appendFilter->GetOutput()); @@ -174,10 +175,9 @@ int vtkAggregateDataSetFilter::RequestData( { vtkNew appendFilter; appendFilter->SetMergePoints(this->MergePoints); - for (std::vector>::iterator it = recvBuffer.begin(); - it != recvBuffer.end(); ++it) + for (const vtkSmartPointer& dObj : recvBuffer) { - appendFilter->AddInputData(*it); + appendFilter->AddInputData(dObj); } appendFilter->Update(); output->ShallowCopy(appendFilter->GetOutput()); -- GitLab From fdb9dae621c007089c4ba38411d26f4f50c896b1 Mon Sep 17 00:00:00 2001 From: Spiros Tsalikis Date: Tue, 17 Mar 2026 16:36:11 -0400 Subject: [PATCH 2/3] vtkAggregateDataSetFilter: Add TargetProcess --- .../Parallel/vtkAggregateDataSetFilter.cxx | 18 +++++++----- Filters/Parallel/vtkAggregateDataSetFilter.h | 29 +++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Filters/Parallel/vtkAggregateDataSetFilter.cxx b/Filters/Parallel/vtkAggregateDataSetFilter.cxx index 9f7a40284b2..a73e739267e 100644 --- a/Filters/Parallel/vtkAggregateDataSetFilter.cxx +++ b/Filters/Parallel/vtkAggregateDataSetFilter.cxx @@ -22,6 +22,7 @@ vtkObjectFactoryNewMacro(vtkAggregateDataSetFilter); vtkAggregateDataSetFilter::vtkAggregateDataSetFilter() { this->NumberOfTargetProcesses = 1; + this->TargetProcess = vtkAggregateDataSetFilter::PROCESS_WITH_MOST_POINTS; } //------------------------------------------------------------------------------ @@ -122,16 +123,19 @@ int vtkAggregateDataSetFilter::RequestData( vtkIdType numPoints = input->GetNumberOfPoints(); subController->AllGather(&numPoints, pointCount.data(), 1); - // The first process in the subcontroller to have points is the one that data will - // be aggregated to. All the other processes send their data set to that process. int receiveProc = 0; - vtkIdType maxVal = 0; - for (int i = 0; i < subNumProcs; i++) + if (this->TargetProcess == vtkAggregateDataSetFilter::PROCESS_WITH_MOST_POINTS) { - if (pointCount[i] > maxVal) + // The first process in the subcontroller to have points is the one that data will + // be aggregated to. All the other processes send their data set to that process. + vtkIdType maxVal = 0; + for (int i = 0; i < subNumProcs; i++) { - maxVal = pointCount[i]; - receiveProc = i; + if (pointCount[i] > maxVal) + { + maxVal = pointCount[i]; + receiveProc = i; + } } } diff --git a/Filters/Parallel/vtkAggregateDataSetFilter.h b/Filters/Parallel/vtkAggregateDataSetFilter.h index 12294bdfb7e..e3b8caa850c 100644 --- a/Filters/Parallel/vtkAggregateDataSetFilter.h +++ b/Filters/Parallel/vtkAggregateDataSetFilter.h @@ -41,6 +41,33 @@ public: vtkGetMacro(NumberOfTargetProcesses, int); ///@} + enum TargetProcessType + { + ROOT_PROCESS = 0, + PROCESS_WITH_MOST_POINTS = 1 + }; + ///@{ + /** + * Get/Set the target process for the aggregate operation. + * + * - `ROOT_PROCESS`: data from all processes is aggregated to the root process + * of the (sub)controller. This ensures consistent aggregation across timesteps + * even when point counts change over time. + * + * - `PROCESS_WITH_MOST_POINTS` (default): data from all processes is aggregated + * to the process that currently has the most points, minimizing the amount of + * data sent over the network. Note that if the process with the most points + * changes over time, the aggregation target may vary across timesteps. + */ + vtkSetClampMacro(TargetProcess, int, ROOT_PROCESS, PROCESS_WITH_MOST_POINTS); + vtkGetMacro(TargetProcess, int); + void SetTargetProcessToRootProcess() { this->SetTargetProcess(ROOT_PROCESS); } + void SetTargetProcessToProcessWithMostPoints() + { + this->SetTargetProcess(PROCESS_WITH_MOST_POINTS); + } + ///@} + ///@{ /** * Get/Set if the filter should merge coincidental points @@ -68,6 +95,8 @@ protected: private: vtkAggregateDataSetFilter(const vtkAggregateDataSetFilter&) = delete; void operator=(const vtkAggregateDataSetFilter&) = delete; + + int TargetProcess; }; VTK_ABI_NAMESPACE_END -- GitLab From e8d55cb1b63734a92b8c988a38f0927c4089b97b Mon Sep 17 00:00:00 2001 From: Spiros Tsalikis Date: Tue, 17 Mar 2026 16:36:18 -0400 Subject: [PATCH 3/3] Add changelog --- .../add-vtkAggregateDataSetFilter-target-process.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 Documentation/release/dev/add-vtkAggregateDataSetFilter-target-process.md diff --git a/Documentation/release/dev/add-vtkAggregateDataSetFilter-target-process.md b/Documentation/release/dev/add-vtkAggregateDataSetFilter-target-process.md new file mode 100644 index 00000000000..775dfac1349 --- /dev/null +++ b/Documentation/release/dev/add-vtkAggregateDataSetFilter-target-process.md @@ -0,0 +1,11 @@ +## vtkAggregateDataSetFilter: Add Target Process + +The `vtkAggregateDataSetFilter` has a new `TargetProcess` property, which has the following options: + +1. `vtkAggregateDataSetFilter::TargetProcessType::ROOT_PROCESS`: the data from all processes are aggregated to the + root process of a (sub)controller. This is useful to ensure consistent aggregation across data that their number of + points change over time. +2. `vtkAggregateDataSetFilter::TargetProcessType::PROCESS_WITH_MOST_POINTS` (default): the data from all processes are + aggregated to the process that has the most points. This is useful to minimize the amount of data that needs to be + sent across the network, but it can lead to inconsistent aggregation across time if the process with the most points + changes over time. -- GitLab