// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen // SPDX-License-Identifier: BSD-3-Clause #include "vtkRectilinearGridPartitioner.h" // VTK includes #include "vtkDoubleArray.h" #include "vtkExtentRCBPartitioner.h" #include "vtkIndent.h" #include "vtkInformation.h" #include "vtkInformationVector.h" #include "vtkMultiBlockDataSet.h" #include "vtkObjectFactory.h" #include "vtkRectilinearGrid.h" #include "vtkStreamingDemandDrivenPipeline.h" #include "vtkStructuredData.h" #include "vtkStructuredExtent.h" #include VTK_ABI_NAMESPACE_BEGIN vtkStandardNewMacro(vtkRectilinearGridPartitioner); //------------------------------------------------------------------------------ vtkRectilinearGridPartitioner::vtkRectilinearGridPartitioner() { this->NumberOfPartitions = 2; this->NumberOfGhostLayers = 0; this->DuplicateNodes = 1; this->SetNumberOfInputPorts(1); this->SetNumberOfOutputPorts(1); } //------------------------------------------------------------------------------ vtkRectilinearGridPartitioner::~vtkRectilinearGridPartitioner() = default; //------------------------------------------------------------------------------ void vtkRectilinearGridPartitioner::PrintSelf(std::ostream& oss, vtkIndent indent) { this->Superclass::PrintSelf(oss, indent); oss << "NumberOfPartitions: " << this->NumberOfPartitions << std::endl; oss << "NumberOfGhostLayers: " << this->NumberOfGhostLayers << std::endl; } //------------------------------------------------------------------------------ int vtkRectilinearGridPartitioner::FillInputPortInformation( int vtkNotUsed(port), vtkInformation* info) { info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkRectilinearGrid"); return 1; } //------------------------------------------------------------------------------ int vtkRectilinearGridPartitioner::FillOutputPortInformation( int vtkNotUsed(port), vtkInformation* info) { info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkMultiBlockDataSet"); return 1; } //------------------------------------------------------------------------------ void vtkRectilinearGridPartitioner::ExtractGridCoordinates(vtkRectilinearGrid* grd, int subext[6], vtkDoubleArray* xcoords, vtkDoubleArray* ycoords, vtkDoubleArray* zcoords) { assert("pre: nullptr rectilinear grid" && (grd != nullptr)); assert("pre: nullptr xcoords" && (xcoords != nullptr)); assert("pre: nullptr ycoords" && (ycoords != nullptr)); assert("pre: nullptr zcoords" && (zcoords != nullptr)); int dataDescription = vtkStructuredData::GetDataDescriptionFromExtent(subext); int ndims[3]; vtkStructuredData::GetDimensionsFromExtent(subext, ndims, dataDescription); vtkDoubleArray* coords[3]; coords[0] = xcoords; coords[1] = ycoords; coords[2] = zcoords; vtkDataArray* src_coords[3]; src_coords[0] = grd->GetXCoordinates(); src_coords[1] = grd->GetYCoordinates(); src_coords[2] = grd->GetZCoordinates(); for (int dim = 0; dim < 3; ++dim) { coords[dim]->SetNumberOfComponents(1); coords[dim]->SetNumberOfTuples(ndims[dim]); for (int idx = subext[dim * 2]; idx <= subext[dim * 2 + 1]; ++idx) { vtkIdType lidx = idx - subext[dim * 2]; coords[dim]->SetTuple1(lidx, src_coords[dim]->GetTuple1(idx)); } // END for all ids } // END for all dimensions } //------------------------------------------------------------------------------ int vtkRectilinearGridPartitioner::RequestData(vtkInformation* vtkNotUsed(request), vtkInformationVector** inputVector, vtkInformationVector* outputVector) { // STEP 0: Get input object vtkInformation* input = inputVector[0]->GetInformationObject(0); assert("pre: input information object is nullptr" && (input != nullptr)); vtkRectilinearGrid* grd = vtkRectilinearGrid::SafeDownCast(input->Get(vtkDataObject::DATA_OBJECT())); // STEP 1: Get output object vtkInformation* output = outputVector->GetInformationObject(0); assert("pre: output information object is nullptr" && (output != nullptr)); vtkMultiBlockDataSet* multiblock = vtkMultiBlockDataSet::SafeDownCast(output->Get(vtkDataObject::DATA_OBJECT())); assert("pre: multi-block grid is nullptr" && (multiblock != nullptr)); // STEP 2: Get the global extent int extent[6]; grd->GetExtent(extent); // STEP 3: Setup extent partitioner vtkExtentRCBPartitioner* extentPartitioner = vtkExtentRCBPartitioner::New(); assert("pre: extent partitioner is nullptr" && (extentPartitioner != nullptr)); extentPartitioner->SetGlobalExtent(extent); extentPartitioner->SetNumberOfPartitions(this->NumberOfPartitions); extentPartitioner->SetNumberOfGhostLayers(this->NumberOfGhostLayers); if (this->DuplicateNodes == 1) { extentPartitioner->DuplicateNodesOn(); } else { extentPartitioner->DuplicateNodesOff(); } // STEP 4: Partition extentPartitioner->Partition(); // STEP 5: Extract partition in a multi-block multiblock->SetNumberOfBlocks(extentPartitioner->GetNumExtents()); // Set the whole extent of the grid multiblock->GetInformation()->Set(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent, 6); int subext[6]; unsigned int blockIdx = 0; for (; blockIdx < multiblock->GetNumberOfBlocks(); ++blockIdx) { if (this->CheckAbort()) { break; } extentPartitioner->GetPartitionExtent(blockIdx, subext); vtkRectilinearGrid* subgrid = vtkRectilinearGrid::New(); subgrid->SetExtent(subext); vtkDoubleArray* xcoords = vtkDoubleArray::New(); vtkDoubleArray* ycoords = vtkDoubleArray::New(); vtkDoubleArray* zcoords = vtkDoubleArray::New(); this->ExtractGridCoordinates(grd, subext, xcoords, ycoords, zcoords); subgrid->SetXCoordinates(xcoords); subgrid->SetYCoordinates(ycoords); subgrid->SetZCoordinates(zcoords); xcoords->Delete(); ycoords->Delete(); zcoords->Delete(); vtkInformation* metadata = multiblock->GetMetaData(blockIdx); assert("pre: metadata is nullptr" && (metadata != nullptr)); metadata->Set(vtkDataObject::PIECE_EXTENT(), subext, 6); multiblock->SetBlock(blockIdx, subgrid); subgrid->Delete(); } // END for all blocks extentPartitioner->Delete(); return 1; } VTK_ABI_NAMESPACE_END