1 /*=========================================================================
2 
3  Program:   Visualization Toolkit
4  Module:    vtkRectilinearGridPartitioner.cxx
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE.  See the above copyright notice for more information.
13 
14  =========================================================================*/
15 #include "vtkRectilinearGridPartitioner.h"
16 
17 // VTK includes
18 #include "vtkDoubleArray.h"
19 #include "vtkExtentRCBPartitioner.h"
20 #include "vtkIndent.h"
21 #include "vtkInformation.h"
22 #include "vtkInformationVector.h"
23 #include "vtkMultiBlockDataSet.h"
24 #include "vtkObjectFactory.h"
25 #include "vtkRectilinearGrid.h"
26 #include "vtkStreamingDemandDrivenPipeline.h"
27 #include "vtkStructuredData.h"
28 #include "vtkStructuredExtent.h"
29 
30 #include <cassert>
31 
32 vtkStandardNewMacro( vtkRectilinearGridPartitioner );
33 
34 //------------------------------------------------------------------------------
vtkRectilinearGridPartitioner()35 vtkRectilinearGridPartitioner::vtkRectilinearGridPartitioner()
36 {
37   this->NumberOfPartitions  = 2;
38   this->NumberOfGhostLayers = 0;
39   this->DuplicateNodes = 1;
40   this->SetNumberOfInputPorts(1);
41   this->SetNumberOfOutputPorts(1);
42 }
43 
44 //------------------------------------------------------------------------------
45 vtkRectilinearGridPartitioner::~vtkRectilinearGridPartitioner() = default;
46 
47 //------------------------------------------------------------------------------
PrintSelf(std::ostream & oss,vtkIndent indent)48 void vtkRectilinearGridPartitioner::PrintSelf(
49     std::ostream &oss, vtkIndent indent )
50 {
51   this->Superclass::PrintSelf( oss, indent );
52   oss << "NumberOfPartitions: " << this->NumberOfPartitions << std::endl;
53   oss << "NumberOfGhostLayers: " << this->NumberOfGhostLayers << std::endl;
54 }
55 
56 //------------------------------------------------------------------------------
FillInputPortInformation(int vtkNotUsed (port),vtkInformation * info)57 int vtkRectilinearGridPartitioner::FillInputPortInformation(
58     int vtkNotUsed(port), vtkInformation *info )
59 {
60   info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(),"vtkRectilinearGrid");
61   return 1;
62 }
63 
64 //------------------------------------------------------------------------------
FillOutputPortInformation(int vtkNotUsed (port),vtkInformation * info)65 int vtkRectilinearGridPartitioner::FillOutputPortInformation(
66     int vtkNotUsed(port), vtkInformation *info )
67 {
68   info->Set(vtkDataObject::DATA_TYPE_NAME(),"vtkMultiBlockDataSet");
69   return 1;
70 }
71 
72 //------------------------------------------------------------------------------
ExtractGridCoordinates(vtkRectilinearGrid * grd,int subext[6],vtkDoubleArray * xcoords,vtkDoubleArray * ycoords,vtkDoubleArray * zcoords)73 void vtkRectilinearGridPartitioner::ExtractGridCoordinates(
74     vtkRectilinearGrid *grd, int subext[6],
75     vtkDoubleArray *xcoords, vtkDoubleArray *ycoords, vtkDoubleArray *zcoords )
76 {
77   assert("pre: nullptr rectilinear grid" && (grd != nullptr) );
78   assert("pre: nullptr xcoords" && (xcoords != nullptr) );
79   assert("pre: nullptr ycoords" && (ycoords != nullptr) );
80   assert("pre: nullptr zcoords" && (zcoords != nullptr) );
81 
82   int dataDescription = vtkStructuredData::GetDataDescriptionFromExtent(subext);
83 
84   int ndims[3];
85   vtkStructuredData::GetDimensionsFromExtent(subext,ndims,dataDescription );
86 
87   vtkDoubleArray* coords[3];
88   coords[0] = xcoords;
89   coords[1] = ycoords;
90   coords[2] = zcoords;
91 
92   vtkDataArray* src_coords[3];
93   src_coords[0] = grd->GetXCoordinates();
94   src_coords[1] = grd->GetYCoordinates();
95   src_coords[2] = grd->GetZCoordinates();
96 
97   for(int dim=0; dim < 3; ++dim)
98   {
99     coords[ dim ]->SetNumberOfComponents( 1 );
100     coords[ dim ]->SetNumberOfTuples( ndims[ dim ] );
101 
102     for(int idx=subext[dim*2]; idx <= subext[dim*2+1]; ++idx)
103     {
104       vtkIdType lidx = idx-subext[dim*2];
105       coords[ dim ]->SetTuple1(lidx,src_coords[dim]->GetTuple1(idx));
106     } // END for all ids
107 
108   } // END for all dimensions
109 }
110 
111 //------------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** inputVector,vtkInformationVector * outputVector)112 int vtkRectilinearGridPartitioner::RequestData(
113     vtkInformation* vtkNotUsed(request),
114     vtkInformationVector** inputVector,vtkInformationVector* outputVector )
115 {
116   // STEP 0: Get input object
117   vtkInformation *input = inputVector[0]->GetInformationObject( 0 );
118   assert("pre: input information object is nullptr" && (input != nullptr) );
119   vtkRectilinearGrid *grd =
120      vtkRectilinearGrid::SafeDownCast(input->Get(vtkDataObject::DATA_OBJECT()));
121 
122   // STEP 1: Get output object
123   vtkInformation *output = outputVector->GetInformationObject( 0 );
124   assert("pre: output information object is nullptr" && (output != nullptr) );
125   vtkMultiBlockDataSet *multiblock =
126       vtkMultiBlockDataSet::SafeDownCast(
127           output->Get(vtkDataObject::DATA_OBJECT()));
128   assert("pre: multi-block grid is nullptr" && (multiblock != nullptr) );
129 
130   // STEP 2: Get the global extent
131   int extent[6];
132   grd->GetExtent( extent );
133 
134   // STEP 3: Setup extent partitioner
135   vtkExtentRCBPartitioner *extentPartitioner = vtkExtentRCBPartitioner::New();
136   assert("pre: extent partitioner is nullptr" && (extentPartitioner != nullptr) );
137   extentPartitioner->SetGlobalExtent( extent );
138   extentPartitioner->SetNumberOfPartitions( this->NumberOfPartitions );
139   extentPartitioner->SetNumberOfGhostLayers( this->NumberOfGhostLayers );
140   if( this->DuplicateNodes == 1 )
141   {
142     extentPartitioner->DuplicateNodesOn();
143   }
144   else
145   {
146     extentPartitioner->DuplicateNodesOff();
147   }
148 
149   // STEP 4: Partition
150   extentPartitioner->Partition();
151 
152   // STEP 5: Extract partition in a multi-block
153   multiblock->SetNumberOfBlocks( extentPartitioner->GetNumExtents( ) );
154 
155   // Set the whole extent of the grid
156   multiblock->GetInformation()->Set(
157       vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(),extent,6);
158 
159   int subext[6];
160   unsigned int blockIdx = 0;
161   for( ; blockIdx < multiblock->GetNumberOfBlocks(); ++blockIdx )
162   {
163     extentPartitioner->GetPartitionExtent( blockIdx, subext );
164     vtkRectilinearGrid *subgrid = vtkRectilinearGrid::New();
165     subgrid->SetExtent( subext );
166 
167     vtkDoubleArray *xcoords = vtkDoubleArray::New();
168     vtkDoubleArray *ycoords = vtkDoubleArray::New();
169     vtkDoubleArray *zcoords = vtkDoubleArray::New();
170 
171     this->ExtractGridCoordinates(grd,subext,xcoords,ycoords,zcoords);
172 
173     subgrid->SetXCoordinates( xcoords );
174     subgrid->SetYCoordinates( ycoords );
175     subgrid->SetZCoordinates( zcoords );
176     xcoords->Delete();
177     ycoords->Delete();
178     zcoords->Delete();
179 
180     vtkInformation *metadata = multiblock->GetMetaData( blockIdx );
181     assert( "pre: metadata is nullptr" && (metadata != nullptr) );
182     metadata->Set( vtkDataObject::PIECE_EXTENT(), subext, 6);
183 
184     multiblock->SetBlock(blockIdx, subgrid);
185     subgrid->Delete();
186   } // END for all blocks
187 
188   extentPartitioner->Delete();
189   return 1;
190 }
191