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