diff --git a/IO/ParallelXML/Testing/Python/testParallelMultiBlockWriter.py b/IO/ParallelXML/Testing/Python/testParallelMultiBlockWriter.py index 11b49c5c44c798c724b06b717d58c3a749152c9b..8ab8620a9dd5ccf6cd5df20253bd61cbe88d1638 100644 --- a/IO/ParallelXML/Testing/Python/testParallelMultiBlockWriter.py +++ b/IO/ParallelXML/Testing/Python/testParallelMultiBlockWriter.py @@ -43,6 +43,13 @@ else: # | |-- [0,1,..nranks](0,1,...nranks) # | |-- [0,1,..nranks](0,1,...nranks) # | ... (up to total number of ranks) +# | +# |-- <MP> # level where a multipiece dataset is present on all ranks +# | | +# | |-- [0,1,..nranks](0,1,...nranks) +# | |-- [0,1,..nranks](0,1,...nranks) +# | |-- [0,1,..nranks](0,1,...nranks) +# | ... (up to total number of ranks) def createDataSet(empty): @@ -62,12 +69,20 @@ def createData(non_null_ranks, non_empty_ranks, num_ranks): mb.SetBlock(i, createDataSet(i not in non_empty_ranks)) return mb +def createMP(num_pieces): + mp = vtk.vtkMultiPieceDataSet() + mp.SetNumberOfPieces(num_pieces) + for i in range(num_pieces): + mp.SetPiece(i, createDataSet(False)) + return mp + def createMB(piece, num_pieces): output = vtk.vtkMultiBlockDataSet() - output.SetNumberOfBlocks(3) + output.SetNumberOfBlocks(4) output.SetBlock(0, createData([piece], [piece], num_pieces)) output.SetBlock(1, createData(range(num_pieces), [piece], num_pieces)) output.SetBlock(2, createData(range(num_pieces), range(num_pieces), num_pieces)) + output.SetBlock(3, createMP(num_pieces)) return output writer = vtk.vtkXMLPMultiBlockDataWriter() @@ -104,6 +119,6 @@ if rank == 0: # set of files, let's just look at the files we wrote out. files = os.listdir(prefix) - expected_file_count = nranks + nranks + (nranks*nranks) + expected_file_count = nranks + nranks + 2*(nranks*nranks) print ("Expecting %d files for the leaf nodes" % expected_file_count) assert (len(files) == expected_file_count) diff --git a/IO/XML/vtkXMLMultiBlockDataReader.cxx b/IO/XML/vtkXMLMultiBlockDataReader.cxx index 33945dbf34dad23173b4b2ac078852ee932b3382..358c4f0375525b12dc61698314142d9ff2a4a7e4 100644 --- a/IO/XML/vtkXMLMultiBlockDataReader.cxx +++ b/IO/XML/vtkXMLMultiBlockDataReader.cxx @@ -172,7 +172,20 @@ void vtkXMLMultiBlockDataReader::ReadComposite(vtkXMLDataElement* element, // Child is a multipiece dataset. Create it. else if (mblock != nullptr && strcmp(tagName, "Piece") == 0) { - vtkMultiPieceDataSet* childDS = vtkMultiPieceDataSet::New(); + // Look ahead to see if there is a nested Piece structure, which can happen when + // the dataset pieces in a vtkMultiPieceDataSet are themselves split into + // vtkMultiPieceDataSets when saved in parallel. + vtkCompositeDataSet* childDS; + if (childXML->FindNestedElementWithName("Piece")) + { + // Create a multiblock to handle a multipiece child + childDS = vtkMultiBlockDataSet::New(); + } + else + { + // Child is not multipiece, so it is safe to create a vtkMultiPieceDataSet + childDS = vtkMultiPieceDataSet::New(); + } this->ReadComposite(childXML, childDS, filePath, dataSetIndex); const char* name = childXML->GetAttribute("name"); mblock->SetBlock(index, childDS); @@ -284,7 +297,21 @@ int vtkXMLMultiBlockDataReader::FillMetaData(vtkCompositeDataSet* metadata, // Child is a multipiece dataset. Create it. else if (mblock != nullptr && strcmp(tagName, "Piece") == 0) { - vtkMultiPieceDataSet* childDS = vtkMultiPieceDataSet::New(); + // Look ahead to see if there is a nested Piece structure, which can happen when + // the dataset pieces in a vtkMultiPieceDataSet are themselves split into + // vtkMultiPieceDataSets when saved in parallel. + vtkCompositeDataSet* childDS; + if (childXML->FindNestedElementWithName("Piece")) + { + // Create a multiblock to handle a multipiece child + childDS = vtkMultiBlockDataSet::New(); + } + else + { + // Child is not multipiece, so it is safe to create a vtkMultiPieceDataSet + childDS = vtkMultiPieceDataSet::New(); + } + this->FillMetaData(childDS, childXML, filePath, dataSetIndex); mblock->SetBlock(index, childDS); childDS->Delete();