1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkXdmfHeavyData.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 "vtkXdmfHeavyData.h"
16 
17 #include "vtkCellArray.h"
18 #include "vtkCellData.h"
19 #include "vtkCellTypes.h"
20 #include "vtkDataObjectTypes.h"
21 #include "vtkDoubleArray.h"
22 #include "vtkExtractSelectedIds.h"
23 #include "vtkFloatArray.h"
24 #include "vtkInformation.h"
25 #include "vtkMath.h"
26 #include "vtkMergePoints.h"
27 #include "vtkMultiBlockDataSet.h"
28 #include "vtkObjectFactory.h"
29 #include "vtkPointData.h"
30 #include "vtkPolyData.h"
31 #include "vtkRectilinearGrid.h"
32 #include "vtkSelection.h"
33 #include "vtkSelectionNode.h"
34 #include "vtkSmartPointer.h"
35 #include "vtkStructuredData.h"
36 #include "vtkStructuredGrid.h"
37 #include "vtkUniformGrid.h"
38 #include "vtkUnstructuredGrid.h"
39 #include "vtkXdmfDataArray.h"
40 #include "vtkXdmfReader.h"
41 #include "vtkXdmfReaderInternal.h"
42 
43 #include <deque>
44 #include <cassert>
45 
46 using namespace xdmf2;
47 
vtkScaleExtents(int in_exts[6],int out_exts[6],int stride[3])48 static void vtkScaleExtents(int in_exts[6], int out_exts[6], int stride[3])
49 {
50   out_exts[0] = in_exts[0] / stride[0];
51   out_exts[1] = in_exts[1] / stride[0];
52   out_exts[2] = in_exts[2] / stride[1];
53   out_exts[3] = in_exts[3] / stride[1];
54   out_exts[4] = in_exts[4] / stride[2];
55   out_exts[5] = in_exts[5] / stride[2];
56 }
57 
vtkGetDims(int exts[6],int dims[3])58 static void vtkGetDims(int exts[6], int dims[3])
59 {
60   dims[0] = exts[1] - exts[0] + 1;
61   dims[1] = exts[3] - exts[2] + 1;
62   dims[2] = exts[5] - exts[4] + 1;
63 }
64 
65 //----------------------------------------------------------------------------
vtkXdmfHeavyData(vtkXdmfDomain * domain,vtkAlgorithm * reader)66 vtkXdmfHeavyData::vtkXdmfHeavyData(vtkXdmfDomain* domain,
67   vtkAlgorithm* reader)
68 {
69   this->Reader = reader;
70   this->Piece = 0;
71   this->NumberOfPieces = 0;
72   this->GhostLevels = 0;
73   this->Extents[0] = this->Extents[2] = this->Extents[4] = 0;
74   this->Extents[1] = this->Extents[3] = this->Extents[5] = -1;
75   this->Domain = domain;
76   this->Stride[0] = this->Stride[1] = this->Stride[2] = 1;
77 }
78 
79 //----------------------------------------------------------------------------
~vtkXdmfHeavyData()80 vtkXdmfHeavyData::~vtkXdmfHeavyData()
81 {
82 }
83 
84 //----------------------------------------------------------------------------
ReadData()85 vtkDataObject* vtkXdmfHeavyData::ReadData()
86 {
87   if (this->Domain->GetNumberOfGrids() == 1)
88     {
89     // There's just 1 grid. Now in serial, this is all good. In parallel, we
90     // need to be care:
91     // 1. If the data is structured, we respect the update-extent and read
92     //    accordingly.
93     // 2. If the data is unstructrued, we read only on the root node. The user
94     //    can apply D3 or something to repartition the data.
95     return this->ReadData(this->Domain->GetGrid(0));
96     }
97 
98   // this code is similar to ReadComposite() however we cannot use the same code
99   // since the API for getting the children differs on the domain and the grid.
100 
101   bool distribute_leaf_nodes = this->NumberOfPieces > 1;
102   XdmfInt32 numChildren = this->Domain->GetNumberOfGrids();
103   int number_of_leaf_nodes = 0;
104 
105   vtkMultiBlockDataSet* mb = vtkMultiBlockDataSet::New();
106   mb->SetNumberOfBlocks(numChildren);
107 
108   for (XdmfInt32 cc=0; cc < numChildren; cc++)
109     {
110     XdmfGrid* xmfChild = this->Domain->GetGrid(cc);
111     mb->GetMetaData(cc)->Set(vtkCompositeDataSet::NAME(),
112       xmfChild->GetName());
113     bool child_is_leaf = (xmfChild->IsUniform() != 0);
114     if (!child_is_leaf || !distribute_leaf_nodes ||
115       (number_of_leaf_nodes % this->NumberOfPieces) == this->Piece)
116       {
117       // it's possible that the data has way too many blocks, in which case the
118       // reader didn't present the user with capabilities to select the actual
119       // leaf node blocks as is the norm, instead only top-level grids were
120       // shown. In that case we need to ensure that we skip grids the user
121       // wanted us to skip explicitly.
122       if (!this->Domain->GetGridSelection()->ArrayIsEnabled(xmfChild->GetName()))
123         {
124         continue;
125         }
126       vtkDataObject* childDO = this->ReadData(xmfChild);
127       if (childDO)
128         {
129         mb->SetBlock(cc, childDO);
130         childDO->Delete();
131         }
132       }
133     number_of_leaf_nodes += child_is_leaf? 1 : 0;
134     }
135 
136   return mb;
137 }
138 
139 //----------------------------------------------------------------------------
ReadData(XdmfGrid * xmfGrid)140 vtkDataObject* vtkXdmfHeavyData::ReadData(XdmfGrid* xmfGrid)
141 {
142   if (!xmfGrid || xmfGrid->GetGridType() == XDMF_GRID_UNSET)
143     {
144     // sanity check-ensure that the xmfGrid is valid.
145     return 0;
146     }
147 
148   XdmfInt32 gridType = (xmfGrid->GetGridType() & XDMF_GRID_MASK);
149   if (gridType == XDMF_GRID_COLLECTION &&
150     xmfGrid->GetCollectionType() == XDMF_GRID_COLLECTION_TEMPORAL)
151     {
152     // grid is a temporal collection, pick the sub-grid with matching time and
153     // process that.
154     return this->ReadTemporalCollection(xmfGrid);
155     }
156   else if (gridType == XDMF_GRID_COLLECTION ||
157     gridType == XDMF_GRID_TREE)
158     {
159     return this->ReadComposite(xmfGrid);
160     }
161 
162   // grid is a primitive grid, so read the data.
163   return this->ReadUniformData(xmfGrid);
164 }
165 
166 //----------------------------------------------------------------------------
ReadComposite(XdmfGrid * xmfComposite)167 vtkDataObject* vtkXdmfHeavyData::ReadComposite(XdmfGrid* xmfComposite)
168 {
169   assert((
170       (xmfComposite->GetGridType() & XDMF_GRID_COLLECTION &&
171        xmfComposite->GetCollectionType() != XDMF_GRID_COLLECTION_TEMPORAL) ||
172       (xmfComposite->GetGridType() & XDMF_GRID_TREE))
173     && "Input must be a spatial collection or a tree");
174 
175   vtkMultiBlockDataSet* multiBlock = vtkMultiBlockDataSet::New();
176   XdmfInt32 numChildren = xmfComposite->GetNumberOfChildren();
177   multiBlock->SetNumberOfBlocks(numChildren);
178 
179   bool distribute_leaf_nodes = (xmfComposite->GetGridType() & XDMF_GRID_COLLECTION &&
180      this->NumberOfPieces > 1);
181 
182   int number_of_leaf_nodes = 0;
183   for (XdmfInt32 cc=0; cc < numChildren; cc++)
184     {
185     XdmfGrid* xmfChild = xmfComposite->GetChild(cc);
186     multiBlock->GetMetaData(cc)->Set(vtkCompositeDataSet::NAME(),
187       xmfChild->GetName());
188     bool child_is_leaf = (xmfChild->IsUniform() != 0);
189     if (!child_is_leaf || !distribute_leaf_nodes ||
190       (number_of_leaf_nodes % this->NumberOfPieces) == this->Piece)
191       {
192       vtkDataObject* childDO = this->ReadData(xmfChild);
193       if (childDO)
194         {
195         multiBlock->SetBlock(cc, childDO);
196         childDO->Delete();
197         }
198       }
199     number_of_leaf_nodes += child_is_leaf? 1 : 0;
200     }
201 
202   return multiBlock;
203 }
204 
205 //----------------------------------------------------------------------------
ReadTemporalCollection(XdmfGrid * xmfTemporalCollection)206 vtkDataObject* vtkXdmfHeavyData::ReadTemporalCollection(
207   XdmfGrid* xmfTemporalCollection)
208 {
209   assert(xmfTemporalCollection->GetGridType() & XDMF_GRID_COLLECTION &&
210     xmfTemporalCollection->GetCollectionType() == XDMF_GRID_COLLECTION_TEMPORAL
211     && "Input must be a temporal collection");
212 
213   // Find the children that are valid for the requested time (this->Time) and
214   // read only those.
215 
216   // FIXME: I am tempted to remove support for supporting multiple matching
217   // sub-grids for a time-step since that changes the composite data hierarchy
218   // over time which makes it hard to use filters such as vtkExtractBlock etc.
219 
220   std::deque<XdmfGrid*> valid_children;
221   for (XdmfInt32 cc=0; cc < xmfTemporalCollection->GetNumberOfChildren(); cc++)
222     {
223     XdmfGrid* child = xmfTemporalCollection->GetChild(cc);
224     if (child)
225       {
226       // ensure that we set correct epsilon for comparison
227       // BUG #0013766.
228       child->GetTime()->SetEpsilon(VTK_DBL_EPSILON);
229       if (child->GetTime()->IsValid(this->Time, this->Time))
230         {
231         valid_children.push_back(child);
232         }
233       }
234     }
235   // if no child matched this timestep, handle the case where the user didn't
236   // specify any <Time /> element for the temporal collection.
237   for (XdmfInt32 cc=0;
238     valid_children.size() == 0 &&
239     cc < xmfTemporalCollection->GetNumberOfChildren(); cc++)
240     {
241     XdmfGrid* child = xmfTemporalCollection->GetChild(cc);
242     if (child && child->GetTime()->GetTimeType() == XDMF_TIME_UNSET)
243       {
244       valid_children.push_back(child);
245       }
246     }
247 
248   if (valid_children.size() == 0)
249     {
250     return 0;
251     }
252 
253   std::deque<vtkSmartPointer<vtkDataObject> > child_data_objects;
254   std::deque<XdmfGrid*>::iterator iter;
255   for (iter = valid_children.begin(); iter != valid_children.end(); ++iter)
256     {
257     vtkDataObject* childDO = this->ReadData(*iter);
258     if (childDO)
259       {
260       child_data_objects.push_back(childDO);
261       childDO->Delete();
262       }
263     }
264 
265   if (child_data_objects.size() == 1)
266     {
267     vtkDataObject* dataObject = child_data_objects[0];
268     dataObject->Register(NULL);
269     return dataObject;
270     }
271   else if (child_data_objects.size() > 1)
272     {
273     vtkMultiBlockDataSet* mb = vtkMultiBlockDataSet::New();
274     mb->SetNumberOfBlocks(static_cast<unsigned int>(child_data_objects.size()));
275     for (unsigned int cc=0;
276       cc < static_cast<unsigned int>(child_data_objects.size()); cc++)
277       {
278       mb->SetBlock(cc, child_data_objects[cc]);
279       }
280     return mb;
281     }
282 
283   return 0;
284 }
285 
286 //----------------------------------------------------------------------------
287 // Read a non-composite grid. Note here uniform has nothing to do with
288 // vtkUniformGrid but to what Xdmf's GridType="Uniform".
ReadUniformData(XdmfGrid * xmfGrid)289 vtkDataObject* vtkXdmfHeavyData::ReadUniformData(XdmfGrid* xmfGrid)
290 {
291   assert(xmfGrid->IsUniform() && "Input must be a uniform xdmf grid.");
292 
293   int vtk_data_type = this->Domain->GetVTKDataType(xmfGrid);
294 
295   if (!this->Domain->GetGridSelection()->ArrayIsEnabled(xmfGrid->GetName()))
296     {
297     // simply create an empty data-object of the correct type and return it.
298     return vtkDataObjectTypes::NewDataObject(vtk_data_type);
299     }
300 
301   // Read heavy data for grid geometry/topology. This does not read any
302   // data-arrays. They are read explicitly.
303   XdmfInt32 status = xmfGrid->Update();
304   if (status == XDMF_FAIL)
305     {
306     return 0;
307     }
308 
309   vtkDataObject* dataObject = 0;
310 
311   switch (vtk_data_type)
312     {
313   case VTK_UNIFORM_GRID:
314     dataObject = this->RequestImageData(xmfGrid, true);
315     break;
316 
317   case VTK_IMAGE_DATA:
318     dataObject = this->RequestImageData(xmfGrid, false);
319     break;
320 
321   case VTK_STRUCTURED_GRID:
322     dataObject = this->RequestStructuredGrid(xmfGrid);
323     break;
324 
325   case VTK_RECTILINEAR_GRID:
326     dataObject = this->RequestRectilinearGrid(xmfGrid);
327     break;
328 
329   case VTK_UNSTRUCTURED_GRID:
330     dataObject = this->ReadUnstructuredGrid(xmfGrid);
331     break;
332 
333   default:
334     // un-handled case.
335     return 0;
336     }
337 
338   return dataObject;
339 }
340 
341 //----------------------------------------------------------------------------
GetNumberOfPointsPerCell(int vtk_cell_type)342 int vtkXdmfHeavyData::GetNumberOfPointsPerCell(int vtk_cell_type)
343 {
344   switch (vtk_cell_type)
345     {
346   case VTK_POLY_VERTEX:
347     return 0;
348   case VTK_POLY_LINE:
349     return 0;
350   case VTK_POLYGON:
351     return 0;
352 
353   case VTK_TRIANGLE:
354     return 3;
355   case VTK_QUAD:
356     return 4;
357   case VTK_TETRA:
358     return 4;
359   case VTK_PYRAMID:
360     return 5;
361   case VTK_WEDGE:
362     return 6;
363   case VTK_HEXAHEDRON:
364     return 8;
365   case VTK_QUADRATIC_EDGE:
366     return 3;
367   case VTK_QUADRATIC_TRIANGLE:
368     return 6;
369   case VTK_QUADRATIC_QUAD:
370     return 8;
371   case VTK_BIQUADRATIC_QUAD:
372     return 9;
373   case VTK_QUADRATIC_TETRA:
374     return 10;
375   case VTK_QUADRATIC_PYRAMID:
376     return 13;
377   case VTK_QUADRATIC_WEDGE:
378     return 15;
379   case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
380     return 18;
381   case VTK_QUADRATIC_HEXAHEDRON:
382     return 20;
383   case VTK_BIQUADRATIC_QUADRATIC_HEXAHEDRON:
384     return 24;
385   case VTK_TRIQUADRATIC_HEXAHEDRON:
386     return 24;
387     }
388   return -1;
389 }
390 //----------------------------------------------------------------------------
GetVTKCellType(XdmfInt32 topologyType)391 int vtkXdmfHeavyData::GetVTKCellType(XdmfInt32 topologyType)
392 {
393   switch (topologyType)
394     {
395   case  XDMF_POLYVERTEX :
396     return VTK_POLY_VERTEX;
397   case  XDMF_POLYLINE :
398     return VTK_POLY_LINE;
399   case  XDMF_POLYGON :
400     return VTK_POLYGON; // FIXME: should this not be treated as mixed?
401   case  XDMF_TRI :
402     return VTK_TRIANGLE;
403   case  XDMF_QUAD :
404     return VTK_QUAD;
405   case  XDMF_TET :
406     return VTK_TETRA;
407   case  XDMF_PYRAMID :
408     return VTK_PYRAMID;
409   case  XDMF_WEDGE :
410     return VTK_WEDGE;
411   case  XDMF_HEX :
412     return VTK_HEXAHEDRON;
413   case  XDMF_EDGE_3 :
414     return VTK_QUADRATIC_EDGE ;
415   case  XDMF_TRI_6 :
416     return VTK_QUADRATIC_TRIANGLE ;
417   case  XDMF_QUAD_8 :
418     return VTK_QUADRATIC_QUAD ;
419   case  XDMF_QUAD_9 :
420     return VTK_BIQUADRATIC_QUAD ;
421   case  XDMF_TET_10 :
422     return VTK_QUADRATIC_TETRA ;
423   case  XDMF_PYRAMID_13 :
424     return VTK_QUADRATIC_PYRAMID ;
425   case  XDMF_WEDGE_15 :
426     return VTK_QUADRATIC_WEDGE ;
427   case  XDMF_WEDGE_18 :
428     return VTK_BIQUADRATIC_QUADRATIC_WEDGE ;
429   case  XDMF_HEX_20 :
430     return VTK_QUADRATIC_HEXAHEDRON ;
431   case  XDMF_HEX_24 :
432     return VTK_BIQUADRATIC_QUADRATIC_HEXAHEDRON ;
433   case  XDMF_HEX_27 :
434     return VTK_TRIQUADRATIC_HEXAHEDRON ;
435   case XDMF_MIXED :
436     return VTK_NUMBER_OF_CELL_TYPES;
437     }
438   // XdmfErrorMessage("Unknown Topology Type = "
439   //  << xmfGrid->GetTopology()->GetTopologyType());
440   return VTK_EMPTY_CELL;
441 }
442 
443 //----------------------------------------------------------------------------
ReadUnstructuredGrid(XdmfGrid * xmfGrid)444 vtkDataObject* vtkXdmfHeavyData::ReadUnstructuredGrid(XdmfGrid* xmfGrid)
445 {
446   vtkSmartPointer<vtkUnstructuredGrid> ugData =
447     vtkSmartPointer<vtkUnstructuredGrid>::New();
448 
449   // BUG #12527. For non-partitioned data, don't read unstructured grid on
450   // process id > 0.
451   if (this->Piece != 0 &&
452     this->Domain->GetNumberOfGrids() == 1 &&
453     this->Domain->GetVTKDataType() == VTK_UNSTRUCTURED_GRID &&
454     this->Domain->GetSetsSelection()->GetNumberOfArrays() == 0)
455     {
456     ugData->Register(NULL);
457     return ugData;
458     }
459 
460   XdmfTopology* xmfTopology = xmfGrid->GetTopology();
461   XdmfArray* xmfConnectivity = xmfTopology->GetConnectivity();
462 
463   int vtk_cell_type = vtkXdmfHeavyData::GetVTKCellType(
464       xmfTopology->GetTopologyType());
465 
466   if (vtk_cell_type == VTK_EMPTY_CELL)
467     {
468     // invalid topology.
469     return NULL;
470     }
471 
472   if (vtk_cell_type != VTK_NUMBER_OF_CELL_TYPES)
473     // i.e. topologyType != XDMF_MIXED
474     {
475     // all cells are of the same type.
476     XdmfInt32 numPointsPerCell= xmfTopology->GetNodesPerElement();
477 
478     // FIXME: is this needed, shouldn't xmfTopology->GetNodesPerElement()
479     // return the correct value always?
480     if (xmfConnectivity->GetRank() == 2)
481       {
482       numPointsPerCell = xmfConnectivity->GetDimension(1);
483       }
484 
485     /* Create Cell Type Array */
486     XdmfInt64 conn_length = xmfConnectivity->GetNumberOfElements();
487     XdmfInt64* xmfConnections = new XdmfInt64[conn_length];
488     xmfConnectivity->GetValues(0, xmfConnections, conn_length);
489 
490     vtkIdType numCells = xmfTopology->GetShapeDesc()->GetNumberOfElements();
491     int *cell_types = new int[numCells];
492 
493     /* Create Cell Array */
494     vtkCellArray* cells = vtkCellArray::New();
495 
496     /* Get the pointer */
497     vtkIdType* cells_ptr = cells->WritePointer(
498       numCells, numCells * (1 + numPointsPerCell));
499 
500     /* xmfConnections: N p1 p2 ... pN */
501     /* i.e. Triangles : 3 0 1 2    3 3 4 5   3 6 7 8 */
502     vtkIdType index = 0;
503     for(vtkIdType cc = 0 ; cc < numCells; cc++ )
504       {
505       cell_types[cc] = vtk_cell_type;
506       *cells_ptr++ = numPointsPerCell;
507       for (vtkIdType i = 0 ; i < numPointsPerCell; i++ )
508         {
509         *cells_ptr++ = xmfConnections[index++];
510         }
511       }
512     ugData->SetCells(cell_types, cells);
513     cells->Delete();
514     delete [] xmfConnections;
515     delete [] cell_types;
516     }
517   else
518     {
519     // We have cells with mixed types.
520     XdmfInt64 conn_length = xmfGrid->GetTopology()->GetConnectivity()->GetNumberOfElements();
521     XdmfInt64* xmfConnections = new XdmfInt64[conn_length];
522     xmfConnectivity->GetValues(0, xmfConnections, conn_length);
523 
524     vtkIdType numCells = xmfTopology->GetShapeDesc()->GetNumberOfElements();
525     int *cell_types = new int[numCells];
526 
527     /* Create Cell Array */
528     vtkCellArray* cells = vtkCellArray::New();
529 
530     /* Get the pointer. Make it Big enough ... too big for now */
531     vtkIdType* cells_ptr = cells->WritePointer(numCells, conn_length);
532 
533     /* xmfConnections : N p1 p2 ... pN */
534     /* i.e. Triangles : 3 0 1 2    3 3 4 5   3 6 7 8 */
535     vtkIdType index = 0;
536     int sub = 0;
537     for(vtkIdType cc = 0 ; cc < numCells; cc++ )
538       {
539       int vtk_cell_typeI = this->GetVTKCellType(xmfConnections[index++]);
540       XdmfInt32 numPointsPerCell =
541         this->GetNumberOfPointsPerCell(vtk_cell_typeI);
542       if (numPointsPerCell==-1)
543         {
544         // encountered an unknown cell.
545         cells->Delete();
546         delete [] cell_types;
547         delete [] xmfConnections;
548         return NULL;
549         }
550 
551       if (numPointsPerCell==0)
552         {
553         // cell type does not have a fixed number of points in which case the
554         // next entry in xmfConnections tells us the number of points.
555         numPointsPerCell = xmfConnections[index++];
556         sub++; // used to shrink the cells array at the end.
557         }
558 
559       cell_types[cc] = vtk_cell_typeI;
560       *cells_ptr++ = numPointsPerCell;
561       for(vtkIdType i = 0 ; i < numPointsPerCell; i++ )
562         {
563         *cells_ptr++ = xmfConnections[index++];
564         }
565       }
566     // Resize the Array to the Proper Size
567     cells->GetData()->Resize(index-sub);
568     ugData->SetCells(cell_types, cells);
569     cells->Delete();
570     delete [] cell_types;
571     delete [] xmfConnections;
572     }
573 
574   // Read the geometry.
575   vtkPoints* points = this->ReadPoints(xmfGrid->GetGeometry());
576   if (!points)
577     {
578     // failed to read points.
579     return NULL;
580     }
581   ugData->SetPoints(points);
582   points->Delete();
583 
584   this->ReadAttributes(ugData, xmfGrid);
585 
586   // Read ghost cell/point information.
587   this->ReadGhostSets(ugData, xmfGrid);
588 
589   // If this grid has sets defined on it, then we need to read those as well
590   vtkMultiBlockDataSet* sets = this->ReadSets(ugData, xmfGrid);
591   if (sets)
592     {
593     return sets;
594     }
595 
596   ugData->Register(NULL);
597   return ugData;
598 }
599 
vtkExtentsAreValid(int exts[6])600 inline bool vtkExtentsAreValid(int exts[6])
601 {
602   return exts[1] >= exts[0] && exts[3] >= exts[2] && exts[5] >= exts[4];
603 }
604 
vtkExtentsAreEqual(int * exts1,int * exts2)605 inline bool vtkExtentsAreEqual(int *exts1, int *exts2)
606 {
607   if (!exts1 && !exts2)
608     {
609     return true;
610     }
611   if (!exts1 || !exts2)
612     {
613     return false;
614     }
615   return (exts1[0] == exts2[0] &&
616     exts1[1] == exts2[1] &&
617     exts1[2] == exts2[2] &&
618     exts1[3] == exts2[3] &&
619     exts1[4] == exts2[4] &&
620     exts1[5] == exts2[5]);
621 }
622 
623 //-----------------------------------------------------------------------------
RequestRectilinearGrid(XdmfGrid * xmfGrid)624 vtkRectilinearGrid* vtkXdmfHeavyData::RequestRectilinearGrid(XdmfGrid* xmfGrid)
625 {
626   vtkSmartPointer<vtkRectilinearGrid> rg =
627     vtkSmartPointer<vtkRectilinearGrid>::New();
628   int whole_extents[6];
629   int update_extents[6];
630   this->Domain->GetWholeExtent(xmfGrid, whole_extents);
631 
632   if (!vtkExtentsAreValid(this->Extents))
633     {
634     // if this->Extents are not valid, then simply read the whole image.
635     memcpy(update_extents, whole_extents, sizeof(int)*6);
636     }
637   else
638     {
639     memcpy(update_extents, this->Extents, sizeof(int)*6);
640     }
641 
642   // convert to stridden update extents.
643   int scaled_extents[6];
644   vtkScaleExtents(update_extents, scaled_extents, this->Stride);
645 
646   int scaled_dims[3];
647   vtkGetDims(scaled_extents, scaled_dims);
648 
649   rg->SetExtent(scaled_extents);
650 
651   // Now read rectilinear geometry.
652   XdmfGeometry* xmfGeometry = xmfGrid->GetGeometry();
653 
654   vtkSmartPointer<vtkDoubleArray> xarray =
655     vtkSmartPointer<vtkDoubleArray>::New();
656   xarray->SetNumberOfTuples(scaled_dims[0]);
657 
658   vtkSmartPointer<vtkDoubleArray> yarray =
659     vtkSmartPointer<vtkDoubleArray>::New();
660   yarray->SetNumberOfTuples(scaled_dims[1]);
661 
662   vtkSmartPointer<vtkDoubleArray> zarray =
663     vtkSmartPointer<vtkDoubleArray>::New();
664   zarray->SetNumberOfTuples(scaled_dims[2]);
665 
666   rg->SetXCoordinates(xarray);
667   rg->SetYCoordinates(yarray);
668   rg->SetZCoordinates(zarray);
669 
670   switch (xmfGeometry->GetGeometryType())
671     {
672   case XDMF_GEOMETRY_ORIGIN_DXDY:
673   case XDMF_GEOMETRY_ORIGIN_DXDYDZ:
674       {
675       XdmfFloat64* origin = xmfGeometry->GetOrigin();
676       XdmfFloat64* dxdydz = xmfGeometry->GetDxDyDz();
677       for (int cc= scaled_extents[0]; cc <= scaled_extents[1]; cc++)
678         {
679         xarray->GetPointer(0)[cc - scaled_extents[0]] =
680           origin[0] + (dxdydz[0] * cc * this->Stride[0]);
681         }
682       for (int cc= scaled_extents[2]; cc <= scaled_extents[3]; cc++)
683         {
684         yarray->GetPointer(0)[cc - scaled_extents[2]] =
685           origin[1] + (dxdydz[1] * cc * this->Stride[1]);
686         }
687       for (int cc= scaled_extents[4]; cc <= scaled_extents[5]; cc++)
688         {
689         zarray->GetPointer(0)[cc - scaled_extents[4]] =
690           origin[2] + (dxdydz[2] * cc * this->Stride[2]);
691         }
692       }
693     break;
694 
695 
696   case XDMF_GEOMETRY_VXVY:
697       {
698       xarray->FillComponent(0, 0);
699       xmfGeometry->GetVectorY()->GetValues(update_extents[2],
700         yarray->GetPointer(0), scaled_dims[1], this->Stride[1]);
701       xmfGeometry->GetVectorX()->GetValues(update_extents[4],
702         zarray->GetPointer(0), scaled_dims[2], this->Stride[2]);
703       }
704     break;
705 
706   case XDMF_GEOMETRY_VXVYVZ:
707       {
708       xmfGeometry->GetVectorX()->GetValues(update_extents[0],
709         xarray->GetPointer(0), scaled_dims[0], this->Stride[0]);
710       xmfGeometry->GetVectorY()->GetValues(update_extents[2],
711         yarray->GetPointer(0), scaled_dims[1], this->Stride[1]);
712       xmfGeometry->GetVectorZ()->GetValues(update_extents[4],
713         zarray->GetPointer(0), scaled_dims[2], this->Stride[2]);
714       }
715     break;
716 
717   default:
718     vtkErrorWithObjectMacro(this->Reader,
719       "Geometry type : "
720       << xmfGeometry->GetGeometryTypeAsString() << " is not supported for "
721       << xmfGrid->GetTopology()->GetTopologyTypeAsString());
722     return NULL;
723     }
724 
725   this->ReadAttributes(rg, xmfGrid, update_extents);
726   rg->Register(NULL);
727   return rg;
728 }
729 
730 //-----------------------------------------------------------------------------
RequestStructuredGrid(XdmfGrid * xmfGrid)731 vtkStructuredGrid* vtkXdmfHeavyData::RequestStructuredGrid(XdmfGrid* xmfGrid)
732 {
733   vtkStructuredGrid* sg = vtkStructuredGrid::New();
734 
735   int whole_extents[6];
736   int update_extents[6];
737   this->Domain->GetWholeExtent(xmfGrid, whole_extents);
738 
739   if (!vtkExtentsAreValid(this->Extents))
740     {
741     // if this->Extents are not valid, then simply read the whole image.
742     memcpy(update_extents, whole_extents, sizeof(int)*6);
743     }
744   else
745     {
746     memcpy(update_extents, this->Extents, sizeof(int)*6);
747     }
748 
749   int scaled_extents[6];
750   vtkScaleExtents(update_extents, scaled_extents, this->Stride);
751   sg->SetExtent(scaled_extents);
752 
753   vtkPoints* points = this->ReadPoints(xmfGrid->GetGeometry(),
754     update_extents, whole_extents);
755   sg->SetPoints(points);
756   points->Delete();
757 
758   this->ReadAttributes(sg, xmfGrid, update_extents);
759   return sg;
760 }
761 
762 //-----------------------------------------------------------------------------
RequestImageData(XdmfGrid * xmfGrid,bool use_uniform_grid)763 vtkImageData* vtkXdmfHeavyData::RequestImageData(XdmfGrid* xmfGrid,
764   bool use_uniform_grid)
765 {
766   vtkImageData* imageData = use_uniform_grid?
767     static_cast<vtkImageData*>(vtkUniformGrid::New()) :
768     vtkImageData::New();
769 
770   int whole_extents[6];
771   this->Domain->GetWholeExtent(xmfGrid, whole_extents);
772 
773   int update_extents[6];
774 
775   if (!vtkExtentsAreValid(this->Extents))
776     {
777     // if this->Extents are not valid, then simply read the whole image.
778     memcpy(update_extents, whole_extents, sizeof(int)*6);
779     }
780   else
781     {
782     memcpy(update_extents, this->Extents, sizeof(int)*6);
783     }
784 
785   int scaled_extents[6];
786   vtkScaleExtents(update_extents, scaled_extents, this->Stride);
787   imageData->SetExtent(scaled_extents);
788 
789   double origin[3], spacing[3];
790   if (!this->Domain->GetOriginAndSpacing(xmfGrid, origin, spacing))
791     {
792     vtkErrorWithObjectMacro(this->Reader,
793       "Could not determine image-data origin and spacing. "
794       "Required geometry type is ORIGIN_DXDY or ORIGIN_DXDYDZ. "
795       "The specified geometry type is : " <<
796       xmfGrid->GetGeometry()->GetGeometryTypeAsString());
797     // release image data.
798     imageData->Delete();
799     return NULL;
800     }
801   imageData->SetOrigin(origin);
802   imageData->SetSpacing(
803     spacing[0] * this->Stride[0],
804     spacing[1] * this->Stride[1],
805     spacing[2] * this->Stride[2]);
806   this->ReadAttributes(imageData, xmfGrid, update_extents);
807   return imageData;
808 }
809 
810 //-----------------------------------------------------------------------------
ReadPoints(XdmfGeometry * xmfGeometry,int * update_extents,int * whole_extents)811 vtkPoints* vtkXdmfHeavyData::ReadPoints(XdmfGeometry* xmfGeometry,
812   int *update_extents /*=NULL*/, int *whole_extents /*=NULL*/)
813 {
814   XdmfInt32 geomType = xmfGeometry->GetGeometryType();
815 
816   if (geomType != XDMF_GEOMETRY_X_Y_Z && geomType != XDMF_GEOMETRY_XYZ &&
817     geomType != XDMF_GEOMETRY_X_Y && geomType != XDMF_GEOMETRY_XY)
818     {
819     return NULL;
820     }
821 
822   XdmfArray* xmfPoints = xmfGeometry->GetPoints();
823   if (!xmfPoints)
824     {
825     XdmfErrorMessage("No Points to Set");
826     return NULL;
827     }
828 
829   vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
830 
831   if (xmfPoints->GetNumberType() == XDMF_FLOAT32_TYPE)
832     {
833     vtkFloatArray* da = vtkFloatArray::New();
834     da->SetNumberOfComponents(3);
835     points->SetData(da);
836     da->Delete();
837     }
838   else // means == XDMF_FLOAT64_TYPE
839     {
840     vtkDoubleArray* da = vtkDoubleArray::New();
841     da->SetNumberOfComponents(3);
842     points->SetData(da);
843     da->Delete();
844     }
845 
846   XdmfInt64 numGeometryPoints = xmfGeometry->GetNumberOfPoints();
847   vtkIdType numPoints = numGeometryPoints;
848   bool structured_data = false;
849   if (update_extents && whole_extents)
850     {
851     // we are reading a sub-extent.
852     structured_data = true;
853     int scaled_extents[6];
854     int scaled_dims[3];
855     vtkScaleExtents(update_extents, scaled_extents, this->Stride);
856     vtkGetDims(scaled_extents, scaled_dims);
857     numPoints = (scaled_dims[0] * scaled_dims[1] * scaled_dims[2]);
858     }
859   points->SetNumberOfPoints(numPoints);
860 
861   if (!structured_data)
862     {
863     // read all the points.
864     switch (points->GetData()->GetDataType())
865       {
866     case VTK_DOUBLE:
867       xmfPoints->GetValues(0, reinterpret_cast<double*>(
868           points->GetVoidPointer(0)), numPoints*3);
869       break;
870 
871     case VTK_FLOAT:
872       xmfPoints->GetValues(0, reinterpret_cast<float*>(
873           points->GetVoidPointer(0)), numPoints*3);
874       break;
875 
876     default:
877       return NULL;
878       }
879     }
880   else
881     {
882     // treating the points as structured points
883     XdmfFloat64* tempPoints = new XdmfFloat64[numGeometryPoints*3];
884     xmfPoints->GetValues(0, tempPoints, numGeometryPoints*3);
885     vtkIdType pointId=0;
886     int xdmf_dims[3];
887     vtkGetDims(whole_extents, xdmf_dims);
888 
889     for (int z = update_extents[4]; z <= update_extents[5]; z++)
890       {
891       if ((z-update_extents[4]) % this->Stride[2])
892         {
893         continue;
894         }
895 
896       for (int y = update_extents[2]; y <= update_extents[3]; y++)
897         {
898         if ((y-update_extents[2]) % this->Stride[1])
899           {
900           continue;
901           }
902 
903         for (int x = update_extents[0]; x <= update_extents[1]; x++)
904           {
905           if ((x-update_extents[0]) % this->Stride[0])
906             {
907             continue;
908             }
909 
910           int xdmf_index[3] = {x,y,z};
911           XdmfInt64 offset = vtkStructuredData::ComputePointId(xdmf_dims, xdmf_index);
912           points->SetPoint(pointId, tempPoints[3*offset],
913             tempPoints[3*offset+1], tempPoints[3*offset+2]);
914           pointId++;
915           }
916         }
917       }
918     delete [] tempPoints;
919     }
920 
921   points->Register(0);
922   return points;
923 }
924 
925 //-----------------------------------------------------------------------------
ReadAttributes(vtkDataSet * dataSet,XdmfGrid * xmfGrid,int * update_extents)926 bool vtkXdmfHeavyData::ReadAttributes(
927   vtkDataSet* dataSet, XdmfGrid* xmfGrid, int* update_extents)
928 {
929   int data_dimensionality = this->Domain->GetDataDimensionality(xmfGrid);
930 
931   int numAttributes = xmfGrid->GetNumberOfAttributes();
932   for (int cc=0; cc < numAttributes; cc++)
933     {
934     XdmfAttribute* xmfAttribute = xmfGrid->GetAttribute(cc);
935     const char* attrName = xmfAttribute->GetName();
936     int attrCenter = xmfAttribute->GetAttributeCenter();
937     if (!attrName)
938       {
939       vtkWarningWithObjectMacro(this->Reader,
940         "Skipping unnamed attributes.");
941       continue;
942       }
943 
944     vtkFieldData * fieldData = 0;
945     // skip disabled arrays.
946     switch (attrCenter)
947       {
948     case XDMF_ATTRIBUTE_CENTER_GRID:
949       fieldData = dataSet->GetFieldData();
950       break;
951 
952     case XDMF_ATTRIBUTE_CENTER_CELL:
953       if (!this->Domain->GetCellArraySelection()->ArrayIsEnabled(attrName))
954         {
955         continue;
956         }
957       fieldData = dataSet->GetCellData();
958       break;
959 
960     case XDMF_ATTRIBUTE_CENTER_NODE:
961       if (!this->Domain->GetPointArraySelection()->ArrayIsEnabled(attrName))
962         {
963         continue;
964         }
965       fieldData = dataSet->GetPointData();
966       break;
967 
968     case XDMF_ATTRIBUTE_CENTER_FACE:
969     case XDMF_ATTRIBUTE_CENTER_EDGE:
970     default:
971       vtkWarningWithObjectMacro(this->Reader,
972         "Skipping attribute " << attrName << " at " <<
973         xmfAttribute->GetAttributeCenterAsString());
974       continue; // unhandled.
975       }
976 
977     vtkDataArray* array = this->ReadAttribute(xmfAttribute,
978       data_dimensionality, update_extents);
979     if (array)
980       {
981       array->SetName(attrName);
982       fieldData->AddArray(array);
983       bool is_active = xmfAttribute->GetActive() != 0;
984       vtkDataSetAttributes* attributes =
985         vtkDataSetAttributes::SafeDownCast(fieldData);
986       if (attributes)
987         {
988         // make attribute active.
989         switch (xmfAttribute->GetAttributeType())
990           {
991         case XDMF_ATTRIBUTE_TYPE_SCALAR:
992           if (is_active || attributes->GetScalars() == NULL)
993             {
994             attributes->SetActiveScalars(attrName);
995             }
996           break;
997 
998         case XDMF_ATTRIBUTE_TYPE_VECTOR:
999           if (is_active || attributes->GetVectors() == NULL)
1000             {
1001             attributes->SetActiveVectors(attrName);
1002             }
1003           break;
1004 
1005         case XDMF_ATTRIBUTE_TYPE_TENSOR:
1006         case XDMF_ATTRIBUTE_TYPE_TENSOR6:
1007           if (is_active || attributes->GetTensors() == NULL)
1008             {
1009             attributes->SetActiveTensors(attrName);
1010             }
1011           break;
1012 
1013         case XDMF_ATTRIBUTE_TYPE_GLOBALID:
1014           if (is_active || attributes->GetGlobalIds() == NULL)
1015             {
1016             attributes->SetActiveGlobalIds(attrName);
1017             }
1018           }
1019         }
1020       array->Delete();
1021       }
1022     }
1023   return true;
1024 }
1025 
1026 // used to convert a symmetric tensor to a regular tensor.
1027 template <class T>
vtkConvertTensor6(T * source,T * dest,vtkIdType numTensors)1028 void vtkConvertTensor6(T* source, T* dest, vtkIdType numTensors)
1029 {
1030   for (vtkIdType cc=0; cc < numTensors; cc++)
1031     {
1032     dest[cc*9 + 0] = source[cc*6 + 0];
1033     dest[cc*9 + 1] = source[cc*6 + 1];
1034     dest[cc*9 + 2] = source[cc*6 + 2];
1035 
1036     dest[cc*9 + 3] = source[cc*6 + 1];
1037     dest[cc*9 + 4] = source[cc*6 + 3];
1038     dest[cc*9 + 5] = source[cc*6 + 4];
1039 
1040     dest[cc*9 + 6] = source[cc*6 + 2];
1041     dest[cc*9 + 7] = source[cc*6 + 4];
1042     dest[cc*9 + 8] = source[cc*6 + 5];
1043     }
1044 }
1045 
1046 //-----------------------------------------------------------------------------
ReadAttribute(XdmfAttribute * xmfAttribute,int data_dimensionality,int * update_extents)1047 vtkDataArray* vtkXdmfHeavyData::ReadAttribute(XdmfAttribute* xmfAttribute,
1048   int data_dimensionality, int* update_extents/*=0*/)
1049 {
1050   if (!xmfAttribute)
1051     {
1052     return NULL;
1053     }
1054 
1055   int attrType = xmfAttribute->GetAttributeType();
1056   int attrCenter = xmfAttribute->GetAttributeCenter();
1057   int numComponents = 1;
1058 
1059   switch (attrType)
1060     {
1061   case XDMF_ATTRIBUTE_TYPE_TENSOR :
1062     numComponents = 9;
1063     break;
1064   case XDMF_ATTRIBUTE_TYPE_TENSOR6:
1065     numComponents = 6;
1066     break;
1067   case XDMF_ATTRIBUTE_TYPE_VECTOR:
1068     numComponents = 3;
1069     break;
1070   default :
1071     numComponents = 1;
1072     break;
1073     }
1074 
1075   XdmfDataItem xmfDataItem;
1076   xmfDataItem.SetDOM(xmfAttribute->GetDOM());
1077   xmfDataItem.SetElement(xmfAttribute->GetDOM()->FindDataElement(0,
1078       xmfAttribute->GetElement()));
1079   xmfDataItem.UpdateInformation();
1080 
1081   XdmfInt64 data_dims[XDMF_MAX_DIMENSION];
1082   int data_rank = xmfDataItem.GetDataDesc()->GetShape(data_dims);
1083 
1084   if (update_extents && attrCenter != XDMF_ATTRIBUTE_CENTER_GRID)
1085     {
1086     // for hyperslab selection to work, the data shape must match the topology
1087     // shape.
1088     if (data_rank < 0)
1089       {
1090       vtkErrorWithObjectMacro(this->Reader,
1091         "Unsupported attribute rank: " << data_rank);
1092       return NULL;
1093       }
1094     if (data_rank > (data_dimensionality + 1))
1095       {
1096       vtkErrorWithObjectMacro(this->Reader,
1097         "The data_dimensionality and topology dimensionality mismatch");
1098       return NULL;
1099       }
1100     XdmfInt64 start[4] = { update_extents[4], update_extents[2], update_extents[0], 0 };
1101     XdmfInt64 stride[4] = {this->Stride[2], this->Stride[1], this->Stride[0], 1};
1102     XdmfInt64 count[4] = {0, 0, 0, 0};
1103     int scaled_dims[3];
1104     int scaled_extents[6];
1105     vtkScaleExtents(update_extents, scaled_extents, this->Stride);
1106     vtkGetDims(scaled_extents, scaled_dims);
1107     count[0] = (scaled_dims[2]-1);
1108     count[1] = (scaled_dims[1]-1);
1109     count[2] = (scaled_dims[0]-1);
1110     if (data_rank == (data_dimensionality+1))
1111       {
1112       // this refers the number of components in the attribute.
1113       count[data_dimensionality] = data_dims[data_dimensionality];
1114       }
1115 
1116     if (attrCenter == XDMF_ATTRIBUTE_CENTER_NODE)
1117       {
1118       // Point count is 1 + cell extent if not a single layer
1119       count[0] += (update_extents[5] - update_extents[4] > 0)? 1 : 1;
1120       count[1] += (update_extents[3] - update_extents[2] > 0)? 1 : 1;
1121       count[2] += (update_extents[1] - update_extents[0] > 0)? 1 : 1;
1122       }
1123     xmfDataItem.GetDataDesc()->SelectHyperSlab(start, stride, count);
1124     }
1125 
1126   if (xmfDataItem.Update()==XDMF_FAIL)
1127     {
1128     vtkErrorWithObjectMacro(this->Reader, "Failed to read attribute data");
1129     return 0;
1130     }
1131 
1132   vtkXdmfDataArray* xmfConvertor = vtkXdmfDataArray::New();
1133   vtkDataArray* dataArray = xmfConvertor->FromXdmfArray(
1134     xmfDataItem.GetArray()->GetTagName(), 1, data_rank, numComponents, 0);
1135   xmfConvertor->Delete();
1136 
1137   if (attrType == XDMF_ATTRIBUTE_TYPE_TENSOR6)
1138     {
1139     // convert Tensor6 to Tensor.
1140     vtkDataArray* tensor = dataArray->NewInstance();
1141     vtkIdType numTensors = dataArray->GetNumberOfTuples();
1142     tensor->SetNumberOfComponents(9);
1143     tensor->SetNumberOfTuples(numTensors);
1144 
1145     // Copy Symmetrical Tensor Values to Correct Positions in 3x3 matrix
1146     void* source = dataArray->GetVoidPointer(0);
1147     void* dest = tensor->GetVoidPointer(0);
1148     switch (tensor->GetDataType())
1149       {
1150       vtkTemplateMacro(
1151         vtkConvertTensor6(reinterpret_cast<VTK_TT*>(source),
1152           reinterpret_cast<VTK_TT*>(dest), numTensors)
1153       );
1154       }
1155     dataArray->Delete();
1156     return tensor;
1157     }
1158   return dataArray;
1159 }
1160 
1161 //-----------------------------------------------------------------------------
1162 // Read ghost cell/point information. This is simply loaded info a
1163 // vtkGhostLevels attribute array.
ReadGhostSets(vtkDataSet * dataSet,XdmfGrid * xmfGrid,int * vtkNotUsed (update_extents))1164 bool vtkXdmfHeavyData::ReadGhostSets(vtkDataSet* dataSet, XdmfGrid* xmfGrid,
1165   int *vtkNotUsed(update_extents)/*=0*/)
1166 {
1167   //int data_dimensionality = this->Domain->GetDataDimensionality(xmfGrid);
1168   for (int cc=0; cc < xmfGrid->GetNumberOfSets(); cc++)
1169     {
1170     XdmfSet *xmfSet = xmfGrid->GetSets(cc);
1171     int ghost_value = xmfSet->GetGhost();
1172     if (ghost_value <= 0)
1173       {
1174       // not a ghost-set, simply continue.
1175       continue;
1176       }
1177     XdmfInt32 setCenter = xmfSet->GetSetType();
1178     vtkIdType numElems = 0;
1179     vtkDataSetAttributes* dsa = 0;
1180     switch (setCenter)
1181       {
1182     case XDMF_SET_TYPE_NODE:
1183       dsa = dataSet->GetPointData();
1184       numElems = dataSet->GetNumberOfPoints();
1185       break;
1186 
1187     case XDMF_SET_TYPE_CELL:
1188       dsa = dataSet->GetCellData();
1189       numElems = dataSet->GetNumberOfCells();
1190       break;
1191 
1192     default:
1193       vtkWarningWithObjectMacro(this->Reader,
1194         "Only ghost-cells and ghost-nodes are currently supported.");
1195       continue;
1196       }
1197 
1198     vtkUnsignedCharArray* ghostLevels = vtkUnsignedCharArray::SafeDownCast(
1199       dsa->GetArray("vtkGhostLevels"));
1200     if (!ghostLevels)
1201       {
1202       ghostLevels = vtkUnsignedCharArray::New();
1203       ghostLevels->SetName("vtkGhostLevels");
1204       ghostLevels->SetNumberOfComponents(1);
1205       ghostLevels->SetNumberOfTuples(numElems);
1206       ghostLevels->FillComponent(0, 0);
1207       dsa->AddArray(ghostLevels);
1208       ghostLevels->Delete();
1209       }
1210 
1211     unsigned char* ptrGhostLevels = ghostLevels->GetPointer(0);
1212 
1213     // Read heavy data. We cannot do anything smart if update_extents or stride
1214     // is specified here. We have to read the entire set and then prune it.
1215     xmfSet->Update();
1216 
1217     XdmfArray* xmfIds = xmfSet->GetIds();
1218     XdmfInt64 numIds = xmfIds->GetNumberOfElements();
1219     XdmfInt64 *ids = new XdmfInt64[numIds+1];
1220     xmfIds->GetValues(0, ids, numIds);
1221 
1222     // release the heavy data that was read.
1223     xmfSet->Release();
1224 
1225     for (vtkIdType kk=0; kk < numIds; kk++)
1226       {
1227       if (ids[kk] < 0 || ids[kk] > numElems)
1228         {
1229         vtkWarningWithObjectMacro(this->Reader,
1230           "No such cell or point exists: " << ids[kk]);
1231         continue;
1232         }
1233       ptrGhostLevels[ids[kk]] = ghost_value;
1234       }
1235     delete []ids;
1236     }
1237   return true;
1238 }
1239 
1240 
1241 //-----------------------------------------------------------------------------
ReadSets(vtkDataSet * dataSet,XdmfGrid * xmfGrid,int * vtkNotUsed (update_extents))1242 vtkMultiBlockDataSet* vtkXdmfHeavyData::ReadSets(
1243   vtkDataSet* dataSet, XdmfGrid* xmfGrid, int *vtkNotUsed(update_extents)/*=0*/)
1244 {
1245   unsigned int number_of_sets = 0;
1246   for (int cc=0; cc < xmfGrid->GetNumberOfSets(); cc++)
1247     {
1248     XdmfSet *xmfSet = xmfGrid->GetSets(cc);
1249     int ghost_value = xmfSet->GetGhost();
1250     if (ghost_value != 0)
1251       {
1252       // skip ghost-sets.
1253       continue;
1254       }
1255     number_of_sets++;
1256     }
1257   if (number_of_sets == 0)
1258     {
1259     return NULL;
1260     }
1261 
1262   vtkMultiBlockDataSet* mb = vtkMultiBlockDataSet::New();
1263   mb->SetNumberOfBlocks(1+number_of_sets);
1264   mb->SetBlock(0, dataSet);
1265   mb->GetMetaData(static_cast<unsigned int>(0))->Set(vtkCompositeDataSet::NAME(), "Data");
1266 
1267   unsigned int current_set_index = 1;
1268   for (int cc=0; cc < xmfGrid->GetNumberOfSets(); cc++)
1269     {
1270     XdmfSet *xmfSet = xmfGrid->GetSets(cc);
1271     int ghost_value = xmfSet->GetGhost();
1272     if (ghost_value != 0)
1273       {
1274       // skip ghost-sets.
1275       continue;
1276       }
1277 
1278     const char* setName = xmfSet->GetName();
1279     mb->GetMetaData(current_set_index)->Set(vtkCompositeDataSet::NAME(),
1280       setName);
1281     if (!this->Domain->GetSetsSelection()->ArrayIsEnabled(setName))
1282       {
1283       continue;
1284       }
1285 
1286     // Okay now we have an enabled set. Create a new dataset for it
1287     vtkDataSet* set = 0;
1288 
1289     XdmfInt32 setType = xmfSet->GetSetType();
1290     switch (setType)
1291       {
1292     case XDMF_SET_TYPE_NODE:
1293       set = this->ExtractPoints(xmfSet, dataSet);
1294       break;
1295 
1296     case XDMF_SET_TYPE_CELL:
1297       set = this->ExtractCells(xmfSet, dataSet);
1298       break;
1299 
1300     case XDMF_SET_TYPE_FACE:
1301       set = this->ExtractFaces(xmfSet, dataSet);
1302       break;
1303 
1304     case XDMF_SET_TYPE_EDGE:
1305       set = this->ExtractEdges(xmfSet, dataSet);
1306       break;
1307       }
1308 
1309     if (set)
1310       {
1311       mb->SetBlock(current_set_index, set);
1312       set->Delete();
1313       }
1314     current_set_index++;
1315     }
1316   return mb;
1317 }
1318 
1319 //-----------------------------------------------------------------------------
ExtractPoints(XdmfSet * xmfSet,vtkDataSet * dataSet)1320 vtkDataSet* vtkXdmfHeavyData::ExtractPoints(XdmfSet* xmfSet,
1321   vtkDataSet* dataSet)
1322 {
1323   // TODO: How to handle structured datasets with update_extents/strides etc.
1324   // Do they too always produce vtkUniformGrid or do we want to produce
1325   // structured dataset
1326 
1327   // Read heavy data. We cannot do anything smart if update_extents or stride
1328   // is specified here. We have to read the entire set and then prune it.
1329   xmfSet->Update();
1330 
1331   XdmfArray* xmfIds = xmfSet->GetIds();
1332   XdmfInt64 numIds = xmfIds->GetNumberOfElements();
1333   XdmfInt64 *ids = new XdmfInt64[numIds+1];
1334   xmfIds->GetValues(0, ids, numIds);
1335 
1336   // release heavy data.
1337   xmfSet->Release();
1338 
1339   vtkUnstructuredGrid* output = vtkUnstructuredGrid::New();
1340   vtkPoints* outputPoints = vtkPoints::New();
1341   outputPoints->SetNumberOfPoints(numIds);
1342   output->SetPoints(outputPoints);
1343   outputPoints->Delete();
1344 
1345   vtkIdType numInPoints = dataSet->GetNumberOfPoints();
1346   for (vtkIdType kk=0; kk < numIds; kk++)
1347     {
1348     if (ids[kk] < 0 || ids[kk] > numInPoints)
1349       {
1350       vtkWarningWithObjectMacro(this->Reader,
1351         "No such cell or point exists: " << ids[kk]);
1352       continue;
1353       }
1354     double point_location[3];
1355     dataSet->GetPoint(ids[kk], point_location);
1356     outputPoints->SetPoint(kk, point_location);
1357     }
1358   delete []ids;
1359   ids = NULL;
1360 
1361   // Read node-centered attributes that may be defined on this set.
1362   int numAttributes = xmfSet->GetNumberOfAttributes();
1363   for (int cc=0; cc < numAttributes; cc++)
1364     {
1365     XdmfAttribute* xmfAttribute = xmfSet->GetAttribute(cc);
1366     const char* attrName = xmfAttribute->GetName();
1367     int attrCenter = xmfAttribute->GetAttributeCenter();
1368     if (attrCenter != XDMF_ATTRIBUTE_CENTER_NODE)
1369       {
1370       continue;
1371       }
1372     vtkDataArray* array = this->ReadAttribute(xmfAttribute,
1373       1, NULL);
1374     if (array)
1375       {
1376       array->SetName(attrName);
1377       output->GetPointData()->AddArray(array);
1378       array->Delete();
1379       }
1380     }
1381 
1382   vtkIdType *vtk_cell_ids = new vtkIdType[numIds];
1383   for (vtkIdType cc=0; cc < numIds; cc++)
1384     {
1385     vtk_cell_ids[cc] = cc;
1386     }
1387   output->InsertNextCell(VTK_POLY_VERTEX, numIds, vtk_cell_ids);
1388   delete []vtk_cell_ids;
1389   vtk_cell_ids = NULL;
1390 
1391   return output;
1392 }
1393 
1394 //-----------------------------------------------------------------------------
ExtractCells(XdmfSet * xmfSet,vtkDataSet * dataSet)1395 vtkDataSet* vtkXdmfHeavyData::ExtractCells(XdmfSet* xmfSet,
1396   vtkDataSet* dataSet)
1397 {
1398   // TODO: How to handle structured datasets with update_extents/strides etc.
1399   // Do they too always produce vtkUniformGrid or do we want to produce
1400   // structured dataset
1401 
1402   // Read heavy data.
1403   xmfSet->Update();
1404 
1405   XdmfArray* xmfIds = xmfSet->GetIds();
1406   XdmfInt64 numIds = xmfIds->GetNumberOfElements();
1407 
1408   vtkIdTypeArray* ids = vtkIdTypeArray::New();
1409   ids->SetNumberOfComponents(1);
1410   ids->SetNumberOfTuples(numIds);
1411   xmfIds->GetValues(0, ids->GetPointer(0), numIds);
1412 
1413   // release heavy data.
1414   xmfSet->Release();
1415 
1416   // We directly use vtkExtractSelectedIds for extract cells since the logic to
1417   // extract cells it no trivial (like extracting points).
1418   vtkSelectionNode* selNode = vtkSelectionNode::New();
1419   selNode->SetContentType(vtkSelectionNode::INDICES);
1420   selNode->SetFieldType(vtkSelectionNode::CELL);
1421   selNode->SetSelectionList(ids);
1422 
1423   vtkSelection* sel = vtkSelection::New();
1424   sel->AddNode(selNode);
1425   selNode->Delete();
1426 
1427   vtkExtractSelectedIds* extractCells = vtkExtractSelectedIds::New();
1428   extractCells->SetInputData(0, dataSet);
1429   extractCells->SetInputData(1, sel);
1430   extractCells->Update();
1431 
1432   vtkDataSet* output = vtkDataSet::SafeDownCast(
1433     extractCells->GetOutput()->NewInstance());
1434   output->CopyStructure(vtkDataSet::SafeDownCast(extractCells->GetOutput()));
1435 
1436   sel->Delete();
1437   extractCells->Delete();
1438   ids->Delete();
1439 
1440   // Read cell-centered attributes that may be defined on this set.
1441   int numAttributes = xmfSet->GetNumberOfAttributes();
1442   for (int cc=0; cc < numAttributes; cc++)
1443     {
1444     XdmfAttribute* xmfAttribute = xmfSet->GetAttribute(cc);
1445     const char* attrName = xmfAttribute->GetName();
1446     int attrCenter = xmfAttribute->GetAttributeCenter();
1447     if (attrCenter != XDMF_ATTRIBUTE_CENTER_CELL)
1448       {
1449       continue;
1450       }
1451     vtkDataArray* array = this->ReadAttribute(xmfAttribute, 1, NULL);
1452     if (array)
1453       {
1454       array->SetName(attrName);
1455       output->GetCellData()->AddArray(array);
1456       array->Delete();
1457       }
1458     }
1459 
1460   return output;
1461 }
1462 
1463 //-----------------------------------------------------------------------------
ExtractFaces(XdmfSet * xmfSet,vtkDataSet * dataSet)1464 vtkDataSet* vtkXdmfHeavyData::ExtractFaces(XdmfSet* xmfSet, vtkDataSet* dataSet)
1465 {
1466   xmfSet->Update();
1467 
1468   XdmfArray* xmfIds = xmfSet->GetIds();
1469   XdmfArray* xmfCellIds = xmfSet->GetCellIds();
1470 
1471   XdmfInt64 numFaces = xmfIds->GetNumberOfElements();
1472 
1473   // ids is a 2 component array were each tuple is (cell-id, face-id).
1474   vtkIdTypeArray* ids = vtkIdTypeArray::New();
1475   ids->SetNumberOfComponents(2);
1476   ids->SetNumberOfTuples(numFaces);
1477   xmfCellIds->GetValues(0, ids->GetPointer(0), numFaces, 1, 2);
1478   xmfIds->GetValues(0, ids->GetPointer(1), numFaces, 1, 2);
1479 
1480   vtkPolyData* output = vtkPolyData::New();
1481   vtkCellArray* polys = vtkCellArray::New();
1482   output->SetPolys(polys);
1483   polys->Delete();
1484 
1485   vtkPoints* outPoints = vtkPoints::New();
1486   output->SetPoints(outPoints);
1487   outPoints->Delete();
1488 
1489   vtkMergePoints* mergePoints = vtkMergePoints::New();
1490   mergePoints->InitPointInsertion(outPoints,
1491     dataSet->GetBounds());
1492 
1493   for (vtkIdType cc=0; cc < numFaces; cc++)
1494     {
1495     vtkIdType cellId = ids->GetValue(cc*2);
1496     vtkIdType faceId = ids->GetValue(cc*2+1);
1497     vtkCell* cell = dataSet->GetCell(cellId);
1498     if (!cell)
1499       {
1500       vtkWarningWithObjectMacro(
1501         this->Reader, "Invalid cellId: " << cellId)
1502       continue;
1503       }
1504     vtkCell* face = cell->GetFace(faceId);
1505     if (!face)
1506       {
1507       vtkWarningWithObjectMacro(this->Reader,
1508         "Invalid faceId " << faceId << " on cell " << cellId);
1509       continue;
1510       }
1511 
1512     // Now insert this face a new cell in the output dataset.
1513     vtkIdType numPoints = face->GetNumberOfPoints();
1514     vtkPoints* facePoints = face->GetPoints();
1515     vtkIdType* outputPts = new vtkIdType[numPoints+1];
1516     for (vtkIdType kk=0; kk < numPoints; kk++)
1517       {
1518       mergePoints->InsertUniquePoint(
1519         facePoints->GetPoint(kk), outputPts[kk]);
1520       }
1521     polys->InsertNextCell(numPoints, outputPts);
1522     delete [] outputPts;
1523     }
1524 
1525   ids->Delete();
1526   xmfSet->Release();
1527   mergePoints->Delete();
1528 
1529   // Read face-centered attributes that may be defined on this set.
1530   int numAttributes = xmfSet->GetNumberOfAttributes();
1531   for (int cc=0; cc < numAttributes; cc++)
1532     {
1533     XdmfAttribute* xmfAttribute = xmfSet->GetAttribute(cc);
1534     const char* attrName = xmfAttribute->GetName();
1535     int attrCenter = xmfAttribute->GetAttributeCenter();
1536     if (attrCenter != XDMF_ATTRIBUTE_CENTER_FACE)
1537       {
1538       continue;
1539       }
1540     vtkDataArray* array = this->ReadAttribute(xmfAttribute, 1, NULL);
1541     if (array)
1542       {
1543       array->SetName(attrName);
1544       output->GetCellData()->AddArray(array);
1545       array->Delete();
1546       }
1547     }
1548 
1549   return output;
1550 }
1551 
1552 //-----------------------------------------------------------------------------
ExtractEdges(XdmfSet * xmfSet,vtkDataSet * dataSet)1553 vtkDataSet* vtkXdmfHeavyData::ExtractEdges(XdmfSet* xmfSet, vtkDataSet* dataSet)
1554 {
1555   xmfSet->Update();
1556 
1557   XdmfArray* xmfIds = xmfSet->GetIds();
1558   XdmfArray* xmfCellIds = xmfSet->GetCellIds();
1559   XdmfArray* xmfFaceIds = xmfSet->GetFaceIds();
1560 
1561   XdmfInt64 numEdges = xmfIds->GetNumberOfElements();
1562 
1563   // ids is a 3 component array were each tuple is (cell-id, face-id, edge-id).
1564   vtkIdTypeArray* ids = vtkIdTypeArray::New();
1565   ids->SetNumberOfComponents(3);
1566   ids->SetNumberOfTuples(numEdges);
1567   xmfCellIds->GetValues(0, ids->GetPointer(0), numEdges, 1, 3);
1568   xmfFaceIds->GetValues(0, ids->GetPointer(1), numEdges, 1, 3);
1569   xmfIds->GetValues(0, ids->GetPointer(2), numEdges, 1, 3);
1570 
1571   vtkPolyData* output = vtkPolyData::New();
1572   vtkCellArray* lines = vtkCellArray::New();
1573   output->SetLines(lines);
1574   lines->Delete();
1575 
1576   vtkPoints* outPoints = vtkPoints::New();
1577   output->SetPoints(outPoints);
1578   outPoints->Delete();
1579 
1580   vtkMergePoints* mergePoints = vtkMergePoints::New();
1581   mergePoints->InitPointInsertion(outPoints,
1582     dataSet->GetBounds());
1583 
1584   for (vtkIdType cc=0; cc < numEdges; cc++)
1585     {
1586     vtkIdType cellId = ids->GetValue(cc*3);
1587     vtkIdType faceId = ids->GetValue(cc*3+1);
1588     vtkIdType edgeId = ids->GetValue(cc*3+2);
1589     vtkCell* cell = dataSet->GetCell(cellId);
1590     if (!cell)
1591       {
1592       vtkWarningWithObjectMacro(this->Reader,
1593         "Invalid cellId: " << cellId);
1594       continue;
1595       }
1596     vtkCell* face = cell->GetFace(faceId);
1597     if (!face)
1598       {
1599       vtkWarningWithObjectMacro(this->Reader,
1600         "Invalid faceId " << faceId << " on cell " << cellId);
1601       continue;
1602       }
1603     vtkCell* edge = cell->GetEdge(edgeId);
1604     if (!edge)
1605       {
1606       vtkWarningWithObjectMacro(this->Reader,
1607         "Invalid edgeId " << edgeId << " on face "
1608         << faceId << " on cell " << cellId);
1609       continue;
1610       }
1611 
1612     // Now insert this edge as a new cell in the output dataset.
1613     vtkIdType numPoints = edge->GetNumberOfPoints();
1614     vtkPoints* edgePoints = edge->GetPoints();
1615     vtkIdType* outputPts = new vtkIdType[numPoints+1];
1616     for (vtkIdType kk=0; kk < numPoints; kk++)
1617       {
1618       mergePoints->InsertUniquePoint(
1619         edgePoints->GetPoint(kk), outputPts[kk]);
1620       }
1621     lines->InsertNextCell(numPoints, outputPts);
1622     delete [] outputPts;
1623     }
1624 
1625   ids->Delete();
1626   xmfSet->Release();
1627   mergePoints->Delete();
1628 
1629   // Read edge-centered attributes that may be defined on this set.
1630   int numAttributes = xmfSet->GetNumberOfAttributes();
1631   for (int cc=0; cc < numAttributes; cc++)
1632     {
1633     XdmfAttribute* xmfAttribute = xmfSet->GetAttribute(cc);
1634     const char* attrName = xmfAttribute->GetName();
1635     int attrCenter = xmfAttribute->GetAttributeCenter();
1636     if (attrCenter != XDMF_ATTRIBUTE_CENTER_EDGE)
1637       {
1638       continue;
1639       }
1640     vtkDataArray* array = this->ReadAttribute(xmfAttribute, 1, NULL);
1641     if (array)
1642       {
1643       array->SetName(attrName);
1644       output->GetCellData()->AddArray(array);
1645       array->Delete();
1646       }
1647     }
1648 
1649   return output;
1650 }
1651