Commit a36f1e76 authored by Andrew Bauer's avatar Andrew Bauer
Browse files

Changes to allow aggregation of topologically regular grids

Addresses paraview/paraview#18303.
parent 242ba041
Pipeline #114128 failed with stage
......@@ -27,7 +27,7 @@
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkUnstructuredGrid.h"
vtkStandardNewMacro(vtkAggregateDataSetFilter);
vtkObjectFactoryNewMacro(vtkAggregateDataSetFilter);
//-----------------------------------------------------------------------------
vtkAggregateDataSetFilter::vtkAggregateDataSetFilter()
......@@ -179,5 +179,4 @@ void vtkAggregateDataSetFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "NumberOfTargetProcesses: " << this->NumberOfTargetProcesses << endl;
os << endl;
}
......@@ -17,7 +17,8 @@
* @brief Aggregates data sets to a reduced number of processes.
*
* This class allows polydata and unstructured grids to be aggregated
* over a smaller set of processes.
* over a smaller set of processes. The derived vtkDIYAggregateDataSetFilter
* will operate on image data, rectilinear grids and structured grids.
*/
#ifndef vtkAggregateDataSetFilter_h
......
......@@ -3,12 +3,14 @@ if (NOT WIN32)
include(vtkObjectFactory)
set(Module_SRCS
vtkDIYAggregateDataSetFilter.cxx
vtkPResampleToImage.cxx
vtkPResampleWithDataSet.cxx
)
vtk_add_override(vtkResampleToImage vtkPResampleToImage)
vtk_add_override(vtkResampleWithDataSet vtkPResampleWithDataSet)
vtk_add_override(vtkAggregateDataSetFilter vtkDIYAggregateDataSetFilter)
vtk_object_factory_configure("${vtk_module_overrides}")
list(APPEND Module_SRCS
......
......@@ -9,4 +9,21 @@ vtk_add_test_mpi(vtkFiltersParallelDIY2CxxTests-MPI tests
TestPResampleWithDataSet2.cxx
)
vtk_test_mpi_executable(vtkFiltersParallelDIY2CxxTests-MPI tests)
# We want 4 processes to test the vtkAggregateDataSetFilter
# properly
set (vtkFiltersParallelDIY2CxxTests-MPI_NUMPROCS 4)
vtk_add_test_mpi(vtkFiltersParallelDIY2CxxTests-MPI no_data_tests_4_procs
DIYAggregateDataSet.cxx
)
set(all_tests
${tests}
${no_data_tests_4_procs}
)
vtk_test_mpi_executable(vtkFiltersParallelDIY2CxxTests-MPI all_tests)
# keep getting dashboard errors for vtkFiltersParallelDIY2Cxx-MPI-DIYAggregateDataSet
# that I can't reproduce manually so I'm hoping that if I run the test by itself that
# the test will pass. in the future we may be able to figure out why these test is
# failing in parallel.
set_tests_properties(vtkFiltersParallelDIY2Cxx-MPI-DIYAggregateDataSet PROPERTIES RUN_SERIAL ON)
/*=========================================================================
Program: Visualization Toolkit
Module: DIYAggregateDataSet.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.
=========================================================================*/
// Tests vtkDIYAggregateDataSetFilter.
/*
** This test only builds if MPI is in use. It uses 4 MPI processes to
** test that the data is aggregated down to two processes. It uses a simple
** point count to verify results.
*/
#include "vtkDIYAggregateDataSetFilter.h"
#include "vtkDataSet.h"
#include "vtkIdentityTransform.h"
#include "vtkMPICommunicator.h"
#include "vtkMPIController.h"
#include "vtkNew.h"
#include "vtkPointSet.h"
#include "vtkRTAnalyticSource.h"
#include "vtkTransformFilter.h"
#include <mpi.h>
int DIYAggregateDataSet(int argc, char* argv[])
{
// This is here to avoid false leak messages from vtkDebugLeaks when
// using mpich. It appears that the root process which spawns all the
// main processes waits in MPI_Init() and calls exit() when
// the others are done, causing apparent memory leaks for any objects
// created before MPI_Init().
MPI_Init(&argc, &argv);
// Note that this will create a vtkMPIController if MPI
// is configured, vtkThreadedController otherwise.
vtkMPIController* contr = vtkMPIController::New();
contr->Initialize(&argc, &argv, 1);
int retVal = EXIT_SUCCESS;
vtkMultiProcessController::SetGlobalController(contr);
int me = contr->GetLocalProcessId();
if (!contr->IsA("vtkMPIController"))
{
if (me == 0)
{
cout << "DIYAggregateDataSet test requires MPI" << endl;
}
contr->Delete();
return EXIT_FAILURE;
}
int numProcs = contr->GetNumberOfProcesses();
// Create and execute pipeline
vtkRTAnalyticSource* wavelet = vtkRTAnalyticSource::New();
wavelet->UpdatePiece(me, numProcs, 0);
vtkDIYAggregateDataSetFilter* aggregate = vtkDIYAggregateDataSetFilter::New();
aggregate->SetInputConnection(wavelet->GetOutputPort());
aggregate->SetNumberOfTargetProcesses(2);
aggregate->UpdatePiece(me, numProcs, 0);
if (me % 2 == 1 && vtkDataSet::SafeDownCast(aggregate->GetOutput())->GetNumberOfPoints() != 4851)
{
vtkGenericWarningMacro("Wrong number of imagedata points on process "
<< me << ". Should be 4851 but is "
<< vtkDataSet::SafeDownCast(aggregate->GetOutput())->GetNumberOfPoints());
retVal = EXIT_FAILURE;
}
else if (me % 2 != 1 &&
vtkDataSet::SafeDownCast(aggregate->GetOutput())->GetNumberOfPoints() != 0)
{
vtkGenericWarningMacro("Wrong number of imagedata points on process "
<< me << ". Should be 0 but is "
<< vtkDataSet::SafeDownCast(aggregate->GetOutput())->GetNumberOfPoints());
retVal = EXIT_FAILURE;
}
aggregate->Delete();
wavelet->Delete();
// Now do the same thing for a structured grid (the transform filter converts the wavelet
// from an image data to a structured grid). Also, do it for a 2D grid to make sure it
// works for that as well.
vtkRTAnalyticSource* wavelet2 = vtkRTAnalyticSource::New();
wavelet2->SetWholeExtent(-10, 10, -10, 10, 0, 0);
vtkTransformFilter* transform = vtkTransformFilter::New();
transform->SetInputConnection(wavelet2->GetOutputPort());
vtkNew<vtkIdentityTransform> identityTransform;
transform->SetTransform(identityTransform);
transform->UpdatePiece(me, numProcs, 0);
vtkDIYAggregateDataSetFilter* aggregate2 = vtkDIYAggregateDataSetFilter::New();
aggregate2->SetInputConnection(transform->GetOutputPort());
aggregate2->SetNumberOfTargetProcesses(2);
aggregate2->UpdatePiece(me, numProcs, 0);
if (me % 2 == 1 && vtkDataSet::SafeDownCast(aggregate2->GetOutput())->GetNumberOfPoints() != 231)
{
vtkGenericWarningMacro("Wrong number of structured grid points on process "
<< me << ". Should be 4851 but is "
<< vtkDataSet::SafeDownCast(aggregate2->GetOutput())->GetNumberOfPoints());
retVal = EXIT_FAILURE;
}
else if (me % 2 != 1 &&
vtkDataSet::SafeDownCast(aggregate2->GetOutput())->GetNumberOfPoints() != 0)
{
vtkGenericWarningMacro("Wrong number of structured grid points on process "
<< me << ". Should be 0 but is "
<< vtkDataSet::SafeDownCast(aggregate2->GetOutput())->GetNumberOfPoints());
retVal = EXIT_FAILURE;
}
aggregate2->Delete();
transform->Delete();
wavelet2->Delete();
contr->Finalize();
contr->Delete();
return retVal;
}
......@@ -2,6 +2,7 @@ if (NOT WIN32)
vtk_module(vtkFiltersParallelDIY2
IMPLEMENTS
vtkFiltersCore
vtkFiltersParallel
GROUPS
MPI
TEST_DEPENDS
......@@ -15,11 +16,13 @@ if (NOT WIN32)
vtkParallel
DEPENDS
vtkFiltersCore
vtkFiltersParallel
vtkdiy2
PRIVATE_DEPENDS
vtkCommonCore
vtkCommonDataModel
vtkCommonExecutionModel
vtkIOXML
vtkParallelMPI
)
endif()
This diff is collapsed.
/*=========================================================================
Program: Visualization Toolkit
Module: vtkDIYAggregateDataSetFilter.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 vtkDIYAggregateDataSetFilter
* @brief Aggregates data sets to a reduced number of processes.
*
* This class allows vtkDataSets to be aggregated over a smaller set of processes.
*/
#ifndef vtkDIYAggregateDataSetFilter_h
#define vtkDIYAggregateDataSetFilter_h
#include "vtkFiltersParallelDIY2Module.h" // For export macro
#include "vtkAggregateDataSetFilter.h"
#include <map> // For passing computed data between methods
#include <string> // For passing computed data between methods
#include <vector> // For passing computed data between methods
class vtkDataObject;
class vtkIdList;
class VTKFILTERSPARALLELDIY2_EXPORT vtkDIYAggregateDataSetFilter : public vtkAggregateDataSetFilter
{
vtkTypeMacro(vtkDIYAggregateDataSetFilter, vtkAggregateDataSetFilter);
public:
static vtkDIYAggregateDataSetFilter* New();
void PrintSelf(ostream& os, vtkIndent indent) override;
protected:
vtkDIYAggregateDataSetFilter();
~vtkDIYAggregateDataSetFilter() override;
int RequestData(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
int FillInputPortInformation(int port, vtkInformation* info) override;
int RequestInformation(vtkInformation*,
vtkInformationVector**,
vtkInformationVector*) override;
int RequestUpdateExtent(vtkInformation*,
vtkInformationVector**,
vtkInformationVector*) override;
/**
* Given a source process id and number of processes, return a target process id for the aggregate
* operation. The target process id ranges from 0 to NumberOfTargetProcesses-1.
* For source process ids that don't have a target process id, a -1 will be
* returned.
*/
int GetTargetProcessId(int sourceProcessId, int numberOfProcesses);
/**
* Given two extents and dimensions (marking whether or not we have cells
* in that dimension with a value of 0 for no), return whether or not the
* extents overlap by at least a single cell. We ignore if they share a
* point as this is not needed to share information. If the extents do
* overlap then the overlapping extent is returned in overlappingExtent
* if it is non-null.
*/
bool DoExtentsOverlap(int extent1[6], int extent2[6], int dimensions[3],
int* overlappingExtent);
/**
* Get the extent of the topologically regular dataset.
*/
void GetExtent(vtkDataSet* dataSet, int extent[6]);
/**
* Extract information from source dataset into target dataset.
*/
void ExtractDataSetInformation(vtkDataSet* source, vtkDataSet* target);
/**
* Move data with DIY. Having issues with the serialized XML string.
* so saving for later use.
*/
int MoveDataWithDIY(int inputExtent[6], int wholeExtent[6], int outputExtent[6],
std::map<int, std::string>& serializedDataSets,
std::vector<std::string>& receivedDataSets);
/**
* Move data directly with vtkMPIController.
*/
int MoveData(int inputExtent[6], int wholeExtent[6], int outputExtent[6],
std::map<int, std::string>& serializedDataSets,
std::vector<std::string>& receivedDataSets);
/**
* Determine which processes I receive data and put those process ranks (in order)
* into *processesIReceiveFrom*.
*/
void ComputeProcessesIReceiveFrom(
int inputExent[6], int wholeExtent[6], int outputExtent[6], vtkIdList* processesIReceiveFrom);
/**
* Put appropriate values from *sourceCoordinates* into *targetCoordinates*
* based on the extents overlap.
*/
void ExtractRectilinearGridCoordinates(int* sourceExtent, int* targetExtent,
vtkDataArray* sourceCoordinates, vtkDataArray* targetCoordinates);
private:
vtkDIYAggregateDataSetFilter(const vtkDIYAggregateDataSetFilter&) = delete;
void operator=(const vtkDIYAggregateDataSetFilter&) = delete;
/**
* Used to keep track of whether or not we've initialized the output
* dataset
*/
bool OutputInitialized;
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment