/*========================================================================= Program: Visualization Toolkit Module: TestXMLCompositeDataReaderDistribution.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 "vtkXMLCompositeDataReader.h" #include "vtkCompositeDataIterator.h" #include "vtkCompositeDataPipeline.h" #include "vtkCompositeDataSet.h" #include "vtkInformation.h" #include "vtkPolyData.h" #include "vtkXMLMultiBlockDataReader.h" #include "vtkNew.h" #include #include #include #define TEST_ASSERT(cond, message) \ do \ { \ if (!(cond)) \ { \ std::cerr << "Failure at line " << __LINE__ << ":\n" \ << "\tCondition: " << #cond << "\n" \ << "\tError: " << message << "\n"; \ return EXIT_FAILURE; \ } \ } while (0) /* do-while swallows semicolons */ namespace { // Returns a multiset containing the number of points in each leaf dataset. std::multiset PointCounts(vtkCompositeDataSet* cds) { std::multiset result; using SmartIterator = vtkSmartPointer; auto it = SmartIterator::Take(cds->NewIterator()); it->SkipEmptyNodesOn(); for (it->InitTraversal(); !it->IsDoneWithTraversal(); it->GoToNextItem()) { vtkPolyData* pd = vtkPolyData::SafeDownCast(it->GetCurrentDataObject()); if (pd) { result.insert(pd->GetNumberOfPoints()); } } return result; } bool VerifyCounts(vtkCompositeDataSet* cds, const std::multiset& expected) { return PointCounts(cds) == expected; } std::string DumpCounts(vtkCompositeDataSet* cds) { const std::multiset ids = PointCounts(cds); std::ostringstream out; out << "{ "; for (auto id : ids) { out << id << " "; } out << "}"; return out.str(); } } int TestXMLCompositeDataReaderDistribution(int argc, char* argv[]) { if (argc < 2) { std::cerr << "Missing argument.\n"; return EXIT_FAILURE; } vtkNew in; in->SetFileName(argv[1]); // Verify that the dataset is what we expect: 10 leaves, each with a unique // number of points spanning 1-10 inclusive. { in->Update(); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); } // Simulate a request for a partitioning across 3 processors: vtkNew req; req->Set(vtkCompositeDataPipeline::UPDATE_NUMBER_OF_PIECES(), 3); // Verify that block loading works as expected. { in->SetPieceDistribution(vtkXMLMultiBlockDataReader::Block); // First processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 0); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 1, 2, 3, 4 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); // Second processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 1); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 5, 6, 7 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); // Third processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 2); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 8, 9, 10 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); } // Verify that interleaved loading works as expected. { in->SetPieceDistribution(vtkXMLMultiBlockDataReader::Interleave); // First processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 0); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 1, 4, 7, 10 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); // Second processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 1); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 2, 5, 8 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); // Third processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 2); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 3, 6, 9 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); } // Add an update restriction to test that loading is balanced when datasets 2 // and 7 (point counts, not ids) are ignored. req->Append(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), 0); req->Append(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), 2); req->Append(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), 3); req->Append(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), 4); req->Append(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), 5); req->Append(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), 7); req->Append(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), 8); req->Append(vtkCompositeDataPipeline::UPDATE_COMPOSITE_INDICES(), 9); // Verify that block loading works as expected. { in->SetPieceDistribution(vtkXMLMultiBlockDataReader::Block); // First processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 0); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 1, 3, 4 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); // Second processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 1); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 5, 6, 8 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); // Third processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 2); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 9, 10 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); } // Verify that interleaved loading works as expected. { in->SetPieceDistribution(vtkXMLMultiBlockDataReader::Interleave); // First processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 0); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 1, 5, 9 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); // Second processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 1); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 3, 6, 10 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); // Third processor: req->Set(vtkCompositeDataPipeline::UPDATE_PIECE_NUMBER(), 2); in->Update(req); TEST_ASSERT(VerifyCounts(in->GetOutput(), { 4, 8 }), "Incorrect partitioning: " << DumpCounts(in->GetOutput())); } return EXIT_SUCCESS; }