1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkExodusIIReader.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 /*----------------------------------------------------------------------------
16 Copyright (c) Sandia Corporation
17 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
18 ----------------------------------------------------------------------------*/
19 #include "vtkExodusIIReader.h"
20 #include "vtkExodusIICache.h"
21
22 #include "vtkCellArray.h"
23 #include "vtkCellData.h"
24 #include "vtkCellType.h"
25 #include "vtkCharArray.h"
26 #include "vtkDoubleArray.h"
27 #include "vtkFloatArray.h"
28 #include "vtkIdTypeArray.h"
29 #include "vtkInformation.h"
30 #include "vtkInformationVector.h"
31 #include "vtkIntArray.h"
32 #include "vtkMath.h"
33 #include "vtkMultiBlockDataSet.h"
34 #include "vtkMutableDirectedGraph.h"
35 #include "vtkNew.h"
36 #include "vtkObjectFactory.h"
37 #include "vtkPointData.h"
38 #include "vtkPoints.h"
39 #include "vtkPolyData.h"
40 #include "vtkSortDataArray.h"
41 #include "vtkStdString.h"
42 #include "vtkStreamingDemandDrivenPipeline.h"
43 #include "vtkTypeInt64Array.h"
44 #include "vtkUnstructuredGrid.h"
45 #include "vtkXMLParser.h"
46 #include "vtkStringArray.h"
47 #include "vtkUnsignedCharArray.h"
48 #include "vtkVariantArray.h"
49 #include "vtkSmartPointer.h"
50 #include "vtkExodusIIReaderParser.h"
51
52 #include <algorithm>
53 #include <vector>
54 #include <map>
55 #include <set>
56 #include <deque>
57 #include <string>
58 #include "vtksys/SystemTools.hxx"
59
60 #include "vtksys/RegularExpression.hxx"
61
62 #include "vtk_exodusII.h"
63 #include <cstdio>
64 #include <cstdlib> /* for free() */
65 #include <cstring> /* for memset() */
66 #include <cctype> /* for toupper(), isgraph() */
67 #include <cmath> /* for cos() */
68
69 #ifdef EXODUSII_HAVE_MALLOC_H
70 # include <malloc.h>
71 #endif /* EXODUSII_HAVE_MALLOC_H */
72
73 /// Define this to get printouts summarizing array glomming process
74 #undef VTK_DBG_GLOM
75
76 #define VTK_EXO_FUNC(funcall,errmsg)\
77 if ( (funcall) < 0 ) \
78 { \
79 vtkErrorMacro( errmsg ); \
80 return 1; \
81 }
82
83 // ------------------------------------------------------------------- CONSTANTS
84 static int obj_types[] = {
85 EX_EDGE_BLOCK,
86 EX_FACE_BLOCK,
87 EX_ELEM_BLOCK,
88 EX_NODE_SET,
89 EX_EDGE_SET,
90 EX_FACE_SET,
91 EX_SIDE_SET,
92 EX_ELEM_SET,
93 EX_NODE_MAP,
94 EX_EDGE_MAP,
95 EX_FACE_MAP,
96 EX_ELEM_MAP,
97 EX_NODAL
98 };
99
100 static int num_obj_types = (int)(sizeof(obj_types)/sizeof(obj_types[0]));
101
102 static int obj_sizes[] = {
103 EX_INQ_EDGE_BLK,
104 EX_INQ_FACE_BLK,
105 EX_INQ_ELEM_BLK,
106 EX_INQ_NODE_SETS,
107 EX_INQ_EDGE_SETS,
108 EX_INQ_FACE_SETS,
109 EX_INQ_SIDE_SETS,
110 EX_INQ_ELEM_SETS,
111 EX_INQ_NODE_MAP,
112 EX_INQ_EDGE_MAP,
113 EX_INQ_FACE_MAP,
114 EX_INQ_ELEM_MAP,
115 EX_INQ_NODES
116 };
117
118 static const char* objtype_names[] = {
119 "Edge block",
120 "Face block",
121 "Element block",
122 "Node set",
123 "Edge set",
124 "Face set",
125 "Side set",
126 "Element set",
127 "Node map",
128 "Edge map",
129 "Face map",
130 "Element map",
131 "Nodal"
132 };
133
134 static const char* obj_typestr[] = {
135 "L",
136 "F",
137 "E",
138 "M",
139 "D",
140 "A",
141 "S",
142 "T",
143 nullptr, /* maps have no result variables */
144 nullptr,
145 nullptr,
146 nullptr,
147 "N"
148 };
149
150 #define OBJTYPE_IS_BLOCK(i) (((i)>=0)&&((i)<3))
151 #define OBJTYPE_IS_SET(i) (((i)>2)&&((i)<8))
152 #define OBJTYPE_IS_MAP(i) (((i)>7)&&((i)<12))
153 #define OBJTYPE_IS_NODAL(i) ((i)==12)
154
155 // Unlike obj* items above:
156 // - conn* arrays only reference objects that generate connectivity information
157 // - conn* arrays are ordered the way users expect the output (*not* the same as above)
158 static int conn_types[] = {
159 vtkExodusIIReader::ELEM_BLOCK_ELEM_CONN,
160 vtkExodusIIReader::FACE_BLOCK_CONN,
161 vtkExodusIIReader::EDGE_BLOCK_CONN,
162 vtkExodusIIReader::ELEM_SET_CONN,
163 vtkExodusIIReader::SIDE_SET_CONN,
164 vtkExodusIIReader::FACE_SET_CONN,
165 vtkExodusIIReader::EDGE_SET_CONN,
166 vtkExodusIIReader::NODE_SET_CONN
167 };
168
169 static const char* conn_types_names[] = {
170 "Element Blocks",
171 "Face Blocks",
172 "Edge Blocks",
173 "Element Sets",
174 "Side Sets",
175 "Face Sets",
176 "Edge Sets",
177 "Node Sets"
178 };
179
180 static int num_conn_types = (int)(sizeof(conn_types)/sizeof(conn_types[0]));
181
182 // Given a conn_type index, what is its matching obj_type index?
183 static int conn_obj_idx_cvt[] = {
184 2, 1, 0, 7, 6, 5, 4, 3
185 };
186
187 #define CONNTYPE_IS_BLOCK(i) (((i)>=0)&&((i)<3))
188 #define CONNTYPE_IS_SET(i) (((i)>2)&&((i)<8))
189
190 static const char* glomTypeNames[] = {
191 "Scalar",
192 "Vector2",
193 "Vector3",
194 "Symmetric Tensor",
195 "Integration Point Values"
196 };
197
198 // used to store pointer to ex_get_node_num_map or ex_get_elem_num_map:
199 extern "C" { typedef int (*vtkExodusIIGetMapFunc)( int, int* ); }
200
201 // --------------------------------------------------- PRIVATE CLASS DECLARATION
202 #include "vtkExodusIIReaderPrivate.h"
203 #include "vtkExodusIIReaderVariableCheck.h"
204
205 // --------------------------------------------------- PRIVATE CLASS Implementations
BlockSetInfoType(const vtkExodusIIReaderPrivate::BlockSetInfoType & block)206 vtkExodusIIReaderPrivate::BlockSetInfoType::BlockSetInfoType(
207 const vtkExodusIIReaderPrivate::BlockSetInfoType &block):
208 vtkExodusIIReaderPrivate::ObjectInfoType(block),
209 FileOffset(block.FileOffset),
210 PointMap(block.PointMap),
211 ReversePointMap(block.ReversePointMap),
212 CachedConnectivity(nullptr)
213 {
214 //this is needed to properly manage memory.
215 //when vectors are resized or reserved the container
216 //might be copied to a memory spot, so we need a proper copy constructor
217 //so that the cache remains valid
218 this->CachedConnectivity = block.CachedConnectivity;
219 }
220
~BlockSetInfoType()221 vtkExodusIIReaderPrivate::BlockSetInfoType::~BlockSetInfoType()
222 {
223 if (this->CachedConnectivity)
224 {
225 this->CachedConnectivity->Delete();
226 }
227 }
228
operator =(const vtkExodusIIReaderPrivate::BlockSetInfoType & block)229 vtkExodusIIReaderPrivate::BlockSetInfoType& vtkExodusIIReaderPrivate::BlockSetInfoType::operator=(const vtkExodusIIReaderPrivate::BlockSetInfoType& block)
230 {
231 // protect against invalid self-assignment
232 if (this != &block)
233 {
234 // superclass
235 this->ObjectInfoType::operator=(static_cast<ObjectInfoType const&>(block));
236
237 // delete existing
238 if (this->CachedConnectivity)
239 {
240 this->CachedConnectivity->Delete();
241 this->CachedConnectivity = nullptr;
242 }
243
244 this->FileOffset = block.FileOffset;
245 this->PointMap = block.PointMap;
246 this->ReversePointMap = block.ReversePointMap;
247 this->NextSqueezePoint = block.NextSqueezePoint;
248 if (block.CachedConnectivity)
249 {
250 this->CachedConnectivity = vtkUnstructuredGrid::New();
251 this->CachedConnectivity->ShallowCopy(block.CachedConnectivity);
252 }
253 }
254
255 return *this;
256 }
257
258 // ----------------------------------------------------------- UTILITY ROUTINES
259
260 // This function exists because FORTRAN ordering sucks.
extractTruthForVar(int num_obj,int num_vars,const int * truth_tab,int var,std::vector<int> & truth)261 static void extractTruthForVar( int num_obj, int num_vars, const int* truth_tab, int var, std::vector<int>& truth )
262 {
263 truth.clear();
264
265 int obj;
266 int ttObj; // truth table entry for variable var on object obj.
267 for ( obj = 0; obj < num_obj; ++obj )
268 {
269 ttObj = truth_tab[ var + obj * num_vars ];
270 truth.push_back( ttObj );
271 }
272 }
273
printBlock(ostream & os,vtkIndent indent,int btyp,vtkExodusIIReaderPrivate::BlockInfoType & binfo)274 static void printBlock( ostream& os, vtkIndent indent, int btyp,
275 vtkExodusIIReaderPrivate::BlockInfoType& binfo )
276 {
277 int b = 0;
278 while ( obj_types[b] >= 0 && obj_types[b] != btyp )
279 ++b;
280 const char* btypnam = objtype_names[b];
281 os << indent << btypnam << " " << binfo.Id << " \"" << binfo.Name.c_str()
282 << "\" (" << binfo.Size << ")\n";
283 os << indent << " FileOffset: " << binfo.FileOffset << "\n";
284 os << indent << " CachedConn: " << binfo.CachedConnectivity << " ("
285 << binfo.Status << ")\n";
286 os << indent << " PointMap: " << binfo.PointMap.size() << " entries, "
287 << "ReversePointMap: " << binfo.ReversePointMap.size() << " entries\n";
288 os << indent << " Type: " << binfo.TypeName.c_str() << "\n";
289 os << indent << " Bounds per entry, Node: " << binfo.BdsPerEntry[0]
290 << " Edge: " << binfo.BdsPerEntry[1] << " Face: " << binfo.BdsPerEntry[2]
291 << "\n";
292 os << indent << " Attributes (" << binfo.AttributesPerEntry << "):";
293 int a;
294 for ( a = 0; a < binfo.AttributesPerEntry; ++a )
295 {
296 os << " \"" << binfo.AttributeNames[a].c_str() << "\"("
297 << binfo.AttributeStatus[a] << ")";
298 }
299 os << "\n";
300 }
301
printSet(ostream & os,vtkIndent indent,int styp,vtkExodusIIReaderPrivate::SetInfoType & sinfo)302 static void printSet( ostream& os, vtkIndent indent, int styp,
303 vtkExodusIIReaderPrivate::SetInfoType& sinfo )
304 {
305 int s = 0;
306 while ( obj_types[s] >= 0 && obj_types[s] != styp )
307 ++s;
308 const char* stypnam = objtype_names[s];
309 os << indent << stypnam << " " << sinfo.Id << " \"" << sinfo.Name.c_str()
310 << "\" (" << sinfo.Size << ")\n";
311 os << indent << " FileOffset: " << sinfo.FileOffset << "\n";
312 os << indent << " CachedConn: " << sinfo.CachedConnectivity << " ("
313 << sinfo.Status << ")\n";
314 os << indent << " PointMap: " << sinfo.PointMap.size() << " entries, "
315 << "ReversePointMap: " << sinfo.ReversePointMap.size() << " entries\n";
316 os << indent << " DistFact: " << sinfo.DistFact << "\n";
317 }
318
printMap(ostream & os,vtkIndent indent,int mtyp,vtkExodusIIReaderPrivate::MapInfoType & minfo)319 static void printMap( ostream& os,
320 vtkIndent indent,
321 int mtyp,
322 vtkExodusIIReaderPrivate::MapInfoType& minfo )
323 {
324 int m = 0;
325 while ( obj_types[m] >= 0 && obj_types[m] != mtyp )
326 ++m;
327 const char* mtypnam = objtype_names[m];
328 os << indent << mtypnam << " " << minfo.Id << " \"" << minfo.Name.c_str()
329 << "\" (" << minfo.Size << ")\n";
330 os << indent << " Status: " << minfo.Status << "\n";
331 }
332
printArray(ostream & os,vtkIndent indent,int atyp,vtkExodusIIReaderPrivate::ArrayInfoType & ainfo)333 static void printArray( ostream& os, vtkIndent indent, int atyp,
334 vtkExodusIIReaderPrivate::ArrayInfoType& ainfo )
335 {
336 (void)atyp;
337 os << indent << " " << ainfo.Name.c_str() << " [" << ainfo.Status << "] ( "
338 << ainfo.Components << " = { ";
339 os << ainfo.OriginalIndices[0] << " \"" << ainfo.OriginalNames[0] << "\"";
340 int i;
341 for ( i = 1; i < (int) ainfo.OriginalIndices.size(); ++i )
342 {
343 os << ", " << ainfo.OriginalIndices[i] << " \"" << ainfo.OriginalNames[i]
344 << "\"";
345 }
346 os << " } )\n";
347 os << indent << " " << glomTypeNames[ ainfo.GlomType ] << " Truth:";
348 for ( i = 0; i < (int)ainfo.ObjectTruth.size(); ++i )
349 {
350 os << " " << ainfo.ObjectTruth[i];
351 }
352 os << "\n";
353 }
354
355 // --------------------------------------------------- PRIVATE SUBCLASS MEMBERS
Reset()356 void vtkExodusIIReaderPrivate::ArrayInfoType::Reset()
357 {
358 if ( ! this->Name.empty() )
359 {
360 this->Name.erase( this->Name.begin(), this->Name.end() );
361 }
362 this->Components = 0;
363 this->GlomType = -1;
364 this->Status = 0;
365 this->Source = -1;
366 this->OriginalNames.clear();
367 this->OriginalIndices.clear();
368 this->ObjectTruth.clear();
369 }
370
371 // ------------------------------------------------------- PRIVATE CLASS MEMBERS
372 vtkStandardNewMacro(vtkExodusIIReaderPrivate);
373
374 //-----------------------------------------------------------------------------
vtkExodusIIReaderPrivate()375 vtkExodusIIReaderPrivate::vtkExodusIIReaderPrivate()
376 {
377 this->Exoid = -1;
378 this->ExodusVersion = -1.;
379
380 this->AppWordSize = 8;
381 this->DiskWordSize = 8;
382
383 this->Cache = vtkExodusIICache::New();
384 this->CacheSize = 0;
385
386 this->HasModeShapes = 0;
387 this->ModeShapeTime = -1.;
388 this->AnimateModeShapes = 1;
389
390 this->IgnoreFileTime = false;
391
392 this->GenerateObjectIdArray = 1;
393 this->GenerateGlobalElementIdArray = 0;
394 this->GenerateGlobalNodeIdArray = 0;
395 this->GenerateImplicitElementIdArray = 0;
396 this->GenerateImplicitNodeIdArray = 0;
397 this->GenerateGlobalIdArray = 0;
398 this->GenerateFileIdArray = 0;
399 this->FileId = 0;
400 this->ApplyDisplacements = 1;
401 this->DisplacementMagnitude = 1.;
402
403 this->SqueezePoints = 1;
404
405 this->Parser = nullptr;
406
407 this->SIL = vtkMutableDirectedGraph::New();
408 this->SkipUpdateTimeInformation = false;
409
410 memset( (void*)&this->ModelParameters, 0, sizeof(this->ModelParameters) );
411 }
412
413 //-----------------------------------------------------------------------------
~vtkExodusIIReaderPrivate()414 vtkExodusIIReaderPrivate::~vtkExodusIIReaderPrivate()
415 {
416 this->CloseFile();
417 this->Cache->Delete();
418 this->CacheSize = 0;
419 this->ClearConnectivityCaches();
420 if(this->Parser)
421 {
422 this->Parser->Delete();
423 this->Parser = nullptr;
424 }
425 this->SIL->Delete();
426 this->SIL = nullptr;
427 }
428
429 //-----------------------------------------------------------------------------
GlomArrayNames(int objtyp,int num_obj,int num_vars,char ** var_names,int * truth_tab)430 void vtkExodusIIReaderPrivate::GlomArrayNames( int objtyp,
431 int num_obj,
432 int num_vars,
433 char** var_names,
434 int* truth_tab )
435 {
436 // Clear out existing array names since we are re-reading them in.
437 this->ArrayInfo[objtyp].clear();
438
439 // Create some objects that try to glom names together in different ways.
440 const char endRZ[] = "RZ";
441 const char endV2[] = "xy";
442 const char endV3[] = "xYz";
443 const char endST23[] = "XXYYZZXYXZYZ";
444 const char endST34[] = "XXXYYYZZZWWWXXYXXZXXWXYYXYZXYWXZZXZWXWWYYZYYWYZZYZWYWWZZWZWW";
445
446 vtkExodusIIReaderScalarCheck* scalar = new vtkExodusIIReaderScalarCheck;
447 //vtkExodusIIReaderVectorCheck* vecx2 = new vtkExodusIIReaderVectorCheck( endV2, 2 );
448 //vtkExodusIIReaderVectorCheck* vecx3 = new vtkExodusIIReaderVectorCheck( endV3, 3 );
449 //vtkExodusIIReaderVectorCheck* vecrz = new vtkExodusIIReaderVectorCheck( endRZ, 2 );
450 vtkExodusIIReaderTensorCheck* vecx2 = new vtkExodusIIReaderTensorCheck( endV2, 2, 1, 2 );
451 vtkExodusIIReaderTensorCheck* vecx3 = new vtkExodusIIReaderTensorCheck( endV3, 3, 1, 3 );
452 vtkExodusIIReaderTensorCheck* vecrz = new vtkExodusIIReaderTensorCheck( endRZ, 2, 1, 2 );
453 vtkExodusIIReaderTensorCheck* ten23 = new vtkExodusIIReaderTensorCheck( endST23, 6, 2, 3 );
454 vtkExodusIIReaderTensorCheck* ten34 = new vtkExodusIIReaderTensorCheck( endST34, 20, 3, 4 );
455 vtkExodusIIReaderIntPointCheck* intpt = new vtkExodusIIReaderIntPointCheck;
456 typedef std::vector<vtkExodusIIReaderVariableCheck*> glomVec;
457 glomVec glommers;
458 glommers.push_back( scalar );
459 glommers.push_back( vecx2 );
460 glommers.push_back( vecx3 );
461 glommers.push_back( vecrz );
462 glommers.push_back( ten23 );
463 glommers.push_back( ten34 );
464 glommers.push_back( intpt );
465 glomVec::iterator glommer;
466 std::vector<int> tmpTruth;
467 // Advance through the variable names.
468 for ( int i = 0; i < num_vars; ++ i )
469 {
470 // Prepare all the glommers with the next unused variable name
471 extractTruthForVar( num_obj, num_vars, truth_tab, i, tmpTruth );
472 bool stop = true;
473 for ( glommer = glommers.begin(); glommer != glommers.end(); ++ glommer )
474 {
475 if ( (*glommer)->Start( var_names[i], &tmpTruth[0], num_obj ) )
476 {
477 stop = false;
478 }
479 }
480 int j = i + 1;
481 // If any glommers can continue accepting names, give them more names until no more can accept names
482 while ( j < num_vars && ! stop )
483 {
484 stop = true;
485 for ( glommer = glommers.begin(); glommer != glommers.end(); ++ glommer )
486 {
487 if ( (*glommer)->Add( var_names[j], &tmpTruth[0] ) )
488 {
489 stop = false;
490 }
491 }
492 ++ j;
493 }
494 // Find longest glom that worked. (The scalar glommer always works with Length() 1.)
495 unsigned int longestGlom = 0;
496 glomVec::iterator longestGlommer = glommers.end();
497 for ( glommer = glommers.begin(); glommer != glommers.end(); ++ glommer )
498 {
499 if ( (*glommer)->Length() > longestGlom )
500 {
501 longestGlom = static_cast<unsigned int>( (*glommer)->Length() );
502 longestGlommer = glommer;
503 }
504 }
505 if ( longestGlommer != glommers.end() )
506 {
507 i += (*longestGlommer)->Accept( this->ArrayInfo[objtyp], i, this, objtyp ) - 1; // the ++i takes care of length 1
508 }
509 }
510
511 // Now see what the gloms were.
512 /*
513 typedef std::vector<vtkExodusIIReaderPrivate::ArrayInfoType> varVec;
514 for ( varVec::iterator it = this->ArrayInfo[objtyp].begin(); it != this->ArrayInfo[objtyp].end(); ++ it )
515 {
516 cout << "Name: \"" << it->Name.c_str() << "\" (" << it->Components << ")\n";
517 }
518 */
519
520 delete scalar;
521 delete vecx2;
522 delete vecx3;
523 delete vecrz;
524 delete ten23;
525 delete ten34;
526 delete intpt;
527 }
528
529 //-----------------------------------------------------------------------------
AssembleOutputConnectivity(vtkIdType timeStep,int otyp,int oidx,int conntypidx,BlockSetInfoType * bsinfop,vtkUnstructuredGrid * output)530 int vtkExodusIIReaderPrivate::AssembleOutputConnectivity(
531 vtkIdType timeStep, int otyp, int oidx, int conntypidx,
532 BlockSetInfoType* bsinfop, vtkUnstructuredGrid* output )
533 {
534 // FIXME: Don't think I need this, since we ShallowCopy over it... right?
535 output->Reset();
536 if ( bsinfop->CachedConnectivity )
537 {
538 output->ShallowCopy( bsinfop->CachedConnectivity );
539 return 1;
540 }
541
542 // OK, we needed to remake the cache...
543 bsinfop->CachedConnectivity = vtkUnstructuredGrid::New();
544 bsinfop->CachedConnectivity->Allocate( bsinfop->Size );
545 if ( this->SqueezePoints )
546 {
547 bsinfop->NextSqueezePoint = 0;
548 bsinfop->PointMap.clear();
549 bsinfop->ReversePointMap.clear();
550 }
551
552 // Need to assemble connectivity array from smaller ones.
553 // Call GetCacheOrRead() for each smaller array
554
555 // Might want to experiment with the effectiveness of caching connectivity...
556 // set up the ExodusIICache class with the ability to never cache some
557 // key types.
558 // Might also want to experiment with policies other than LRU, especially
559 // applied to arrays that are not time-varying. During animations, they
560 // will most likely get dropped even though that might not be wise.
561
562 if ( CONNTYPE_IS_BLOCK(conntypidx) )
563 {
564 this->InsertBlockCells( otyp, oidx, conn_types[conntypidx],
565 timeStep, static_cast<BlockInfoType*>( bsinfop ) );
566 }
567 else if ( CONNTYPE_IS_SET(conntypidx) )
568 {
569 this->InsertSetCells( otyp, oidx, conn_types[conntypidx],
570 timeStep, static_cast<SetInfoType*>( bsinfop ) );
571 }
572 else
573 {
574 vtkErrorMacro( "Bad connectivity object type. Harass the responsible programmer." );
575 }
576
577 // OK, now copy our cache to the output...
578 output->ShallowCopy( bsinfop->CachedConnectivity );
579 //this->CachedConnectivity->ShallowCopy( output );
580 if ( this->SqueezePoints )
581 {
582 vtkDebugMacro( << "Squeezed down to " << bsinfop->NextSqueezePoint << " points\n" );
583 }
584 return 0;
585 }
586
AssembleOutputPoints(vtkIdType timeStep,BlockSetInfoType * bsinfop,vtkUnstructuredGrid * output)587 int vtkExodusIIReaderPrivate::AssembleOutputPoints(
588 vtkIdType timeStep, BlockSetInfoType* bsinfop, vtkUnstructuredGrid* output )
589 {
590 (void)timeStep;
591 vtkPoints* pts = output->GetPoints();
592 if ( ! pts )
593 {
594 pts = vtkPoints::New();
595 output->SetPoints( pts );
596 pts->FastDelete();
597 }
598 else
599 {
600 pts->Reset();
601 }
602
603 int ts = -1; // If we don't have displacements, only cache the array under one key.
604 if ( this->ApplyDisplacements && this->FindDisplacementVectors( timeStep ) )
605 { // Otherwise, each time step's array will be different.
606 ts = timeStep;
607 }
608
609 vtkDataArray* arr = this->GetCacheOrRead( vtkExodusIICacheKey( ts, vtkExodusIIReader::NODAL_COORDS, 0, 0 ) );
610 if ( ! arr )
611 {
612 vtkErrorMacro( "Unable to read points from file." );
613 return 0;
614 }
615
616 if ( this->SqueezePoints )
617 {
618 pts->SetNumberOfPoints( bsinfop->NextSqueezePoint );
619 std::map<vtkIdType,vtkIdType>::iterator it;
620 for ( it = bsinfop->PointMap.begin(); it != bsinfop->PointMap.end(); ++ it )
621 {
622 pts->SetPoint( it->second, arr->GetTuple( it->first ) );
623 }
624 }
625 else
626 {
627 pts->SetData( arr );
628 }
629 return 1;
630 }
631
632 //-----------------------------------------------------------------------------
AssembleOutputPointArrays(vtkIdType timeStep,BlockSetInfoType * bsinfop,vtkUnstructuredGrid * output)633 int vtkExodusIIReaderPrivate::AssembleOutputPointArrays(
634 vtkIdType timeStep, BlockSetInfoType* bsinfop, vtkUnstructuredGrid* output )
635 {
636 int status = 1;
637 std::vector<ArrayInfoType>::iterator ai;
638 int aidx = 0;
639
640 for (
641 ai = this->ArrayInfo[ vtkExodusIIReader::NODAL ].begin();
642 ai != this->ArrayInfo[ vtkExodusIIReader::NODAL ].end();
643 ++ai, ++aidx )
644 {
645 if ( ! ai->Status )
646 continue; // Skip arrays we don't want.
647
648 vtkExodusIICacheKey key( timeStep, vtkExodusIIReader::NODAL, 0, aidx );
649 vtkDataArray* src = this->GetCacheOrRead( key );
650 if ( !src )
651 {
652 vtkDebugMacro( "Unable to read point array " << ai->Name.c_str() << " at time step " << timeStep );
653 status = 0;
654 continue;
655 }
656
657 this->AddPointArray( src, bsinfop, output );
658 }
659 return status;
660 }
661
662 //-----------------------------------------------------------------------------
663 #if 0
664 // Copy tuples from one array to another, possibly with a different number of components per tuple.
665 static void vtkEmbedTuplesInLargerArray(
666 vtkDataSetAttributes* attr, vtkDataArray* dst, vtkDataArray* src, vtkIdType numTuples, vtkIdType offset )
667 {
668 vtkIdType i;
669 int srcNumComp = src->GetNumberOfComponents();
670 int dstNumComp = dst->GetNumberOfComponents();
671 if ( dstNumComp != srcNumComp )
672 { // We've promoted the array from 2-D to 3-D... can't use CopyTuple
673 if ( dst->GetDataType() != src->GetDataType() )
674 {
675 return;
676 }
677 vtkIdType sid = 0;
678 vtkIdType did = offset * dstNumComp;
679 int minNumComp = dstNumComp < srcNumComp ? dstNumComp : srcNumComp;
680 switch( dst->GetDataType() )
681 {
682 vtkTemplateMacro(
683 {
684 VTK_TT* srcTuple = (VTK_TT*) src->GetVoidPointer( sid );
685 VTK_TT* dstTuple = (VTK_TT*) dst->GetVoidPointer( did );
686 for ( i = 0; i < numTuples; ++i, srcTuple += srcNumComp, dstTuple += dstNumComp )
687 {
688 for ( int j = 0; j < minNumComp; ++j )
689 {
690 dstTuple[j] = srcTuple[j];
691 }
692 }
693 }
694 );
695 }
696 }
697 else
698 {
699 for ( i = 0; i < numTuples; ++i )
700 {
701 attr->CopyTuple( src, dst, i, i + offset );
702 }
703 }
704 }
705 #endif // 0
706
707 //-----------------------------------------------------------------------------
AssembleOutputCellArrays(vtkIdType timeStep,int otyp,int obj,BlockSetInfoType * bsinfop,vtkUnstructuredGrid * output)708 int vtkExodusIIReaderPrivate::AssembleOutputCellArrays(
709 vtkIdType timeStep, int otyp, int obj, BlockSetInfoType* bsinfop,
710 vtkUnstructuredGrid* output )
711 {
712 // Don't create arrays for deselected objects
713 if ( !output || ! bsinfop->Status )
714 {
715 return 1;
716 }
717
718 vtkCellData* cd = output->GetCellData();
719 // Load (time-constant) attributes first because their status is in the block info.
720 if (
721 otyp == vtkExodusIIReader::ELEM_BLOCK ||
722 otyp == vtkExodusIIReader::EDGE_BLOCK ||
723 otyp == vtkExodusIIReader::FACE_BLOCK)
724 {
725 BlockInfoType* binfop = (BlockInfoType*)bsinfop;
726 std::vector<int>::iterator atit;
727 vtkIdType a = 0;
728 for (atit = binfop->AttributeStatus.begin(); atit != binfop->AttributeStatus.end(); ++atit, ++a)
729 {
730 if (*atit)
731 {
732 vtkDataArray* arr = this->GetCacheOrRead(
733 vtkExodusIICacheKey( timeStep, vtkExodusIIReader::ELEM_BLOCK_ATTRIB, obj, a ) );
734 if ( arr )
735 {
736 cd->AddArray( arr );
737 }
738 }
739 }
740 }
741
742 // Panic if we're given a bad otyp.
743 std::map<int,std::vector<ArrayInfoType> >::iterator ami = this->ArrayInfo.find( otyp );
744 if ( ami == this->ArrayInfo.end() )
745 {
746 #if 0
747 vtkErrorMacro( "Unknown block or set type \"" << otyp << "\" encountered." );
748 for ( ami = this->ArrayInfo.begin(); ami != this->ArrayInfo.end(); ++ ami )
749 {
750 cerr << " Have type: \"" << ami->first << "\"\n";
751 }
752 return 0;
753 #else
754 return 1;
755 #endif // 0
756 }
757
758 // For each array defined on objects of the same type as our output,
759 // look for ones that are turned on (Status != 0) and have a truth
760 // table indicating values are present for object obj in the file.
761 std::vector<ArrayInfoType>::iterator ai;
762 int aidx = 0;
763 for ( ai = ami->second.begin(); ai != ami->second.end(); ++ai, ++aidx )
764 {
765 if ( ! ai->Status )
766 continue;
767
768 if ( ! ai->ObjectTruth[obj] )
769 continue;
770
771 vtkDataArray* arr = this->GetCacheOrRead( vtkExodusIICacheKey( timeStep, ami->first, obj, aidx ) );
772 if ( arr )
773 {
774 cd->AddArray( arr );
775 }
776 }
777
778 return 1;
779 }
780
781 //-----------------------------------------------------------------------------
AssembleOutputProceduralArrays(vtkIdType timeStep,int otyp,int obj,vtkUnstructuredGrid * output)782 int vtkExodusIIReaderPrivate::AssembleOutputProceduralArrays(
783 vtkIdType timeStep, int otyp, int obj,
784 vtkUnstructuredGrid* output )
785 {
786 (void)timeStep;
787 int status = 7;
788 vtkCellData* cd = output->GetCellData();
789 if ( this->GenerateObjectIdArray )
790 {
791 vtkExodusIICacheKey key( -1, vtkExodusIIReader::OBJECT_ID, otyp, obj );
792 vtkDataArray* arr = this->GetCacheOrRead( key );
793 if ( arr )
794 {
795 cd->AddArray( arr );
796 status -= 1;
797 }
798 }
799
800 if ( this->GenerateGlobalElementIdArray &&
801 ( otyp == vtkExodusIIReader::SIDE_SET_CONN ||
802 otyp == vtkExodusIIReader::SIDE_SET ) )
803 {
804 vtkExodusIICacheKey ckey( -1, vtkExodusIIReader::ELEMENT_ID, 0, 0 );
805 vtkIdTypeArray* src = nullptr;
806
807 if ( vtkDataArray* elems = this->GetCacheOrRead( ckey ) )
808 {
809 src = vtkIdTypeArray::New ();
810 src->DeepCopy (elems);
811 }
812
813 vtkExodusIICacheKey key( -1, vtkExodusIIReader::SIDE_SET_CONN, obj, 1 );
814 if ( vtkDataArray* arr = this->GetCacheOrRead( key ) )
815 {
816
817 vtkIdTypeArray* idarray = vtkArrayDownCast<vtkIdTypeArray>(arr);
818 vtkIdTypeArray* elementid = vtkIdTypeArray::New();
819 elementid->SetNumberOfTuples(idarray->GetNumberOfTuples());
820 elementid->SetName(vtkExodusIIReader::GetSideSetSourceElementIdArrayName());
821 vtkIntArray* elementside = vtkIntArray::New();
822 elementside->SetNumberOfTuples(idarray->GetNumberOfTuples());
823 elementside->SetName(vtkExodusIIReader::GetSideSetSourceElementSideArrayName());
824 vtkIdType values[2];
825
826 for(vtkIdType i=0;i<idarray->GetNumberOfTuples();i++)
827 {
828 idarray->GetTypedTuple(i, values);
829 if (src == nullptr || src->GetValue (values[0] - 1) <= 0)
830 {
831 elementid->SetValue(i, values[0] - 1);
832 }
833 else
834 {
835 elementid->SetValue(i, src->GetValue (values[0] - 1) - 1); // find the global element id
836 }
837 // now we have to worry about mapping from exodus canonical side
838 // ordering to vtk canonical side ordering for wedges and hexes.
839 // Even if the element block isn't loaded that we still know what
840 // types of cells it would have contained since all elements
841 // in a block are of the same type.
842 BlockInfoType* type =
843 this->GetBlockFromFileGlobalId(vtkExodusIIReader::ELEM_BLOCK, values[0]);
844 switch(type->CellType)
845 {
846 case VTK_WEDGE:
847 {
848 int wedgeMapping[5] = {2, 3, 4, 0, 1};
849 elementside->SetValue(i, wedgeMapping[ values[1]-1 ] );
850 break;
851 }
852 case VTK_HEXAHEDRON:
853 {
854 int hexMapping[6] = {2, 1, 3, 0, 4, 5};
855 elementside->SetValue(i, hexMapping[ values[1]-1 ] );
856 break;
857 }
858 default:
859 { // switch to 0-based indexing
860 elementside->SetValue(i, values[1]-1 );
861 }
862 }
863 }
864 cd->AddArray( elementid );
865 cd->AddArray( elementside );
866 elementid->FastDelete();
867 elementside->FastDelete();
868 status -= 2;
869 }
870
871 if (src != nullptr)
872 {
873 src->Delete ();
874 }
875 }
876
877 if ( this->GenerateGlobalElementIdArray && ! OBJTYPE_IS_SET( otyp ) )
878 {
879 // This retrieves the first new-style map, or if that is not present,
880 // the solitary old-style map (which always exists but may be
881 // procedurally generated if it is not stored with the file).
882 vtkExodusIICacheKey key( -1, vtkExodusIIReader::GLOBAL_ELEMENT_ID, otyp, obj );
883 vtkDataArray* arr = this->GetCacheOrRead( key );
884 if ( arr )
885 {
886 vtkDataArray* ped = vtkIdTypeArray::New();
887 ped->DeepCopy( arr );
888 ped->SetName( vtkExodusIIReader::GetPedigreeElementIdArrayName() );
889
890 cd->SetGlobalIds( arr );
891 cd->SetPedigreeIds( ped );
892 ped->FastDelete();
893
894 status -= 2;
895 }
896 }
897
898 if ( this->GenerateGlobalNodeIdArray )
899 {
900 // This retrieves the first new-style map, or if that is not present,
901 // the solitary old-style map (which always exists but may be
902 // procedurally generated if it is not stored with the file).
903 vtkExodusIICacheKey key( -1, vtkExodusIIReader::GLOBAL_NODE_ID, otyp, obj );
904 vtkDataArray* arr = this->GetCacheOrRead( key );
905 vtkPointData* pd = output->GetPointData();
906 if ( arr )
907 {
908 vtkDataArray* ped = vtkIdTypeArray::New();
909 ped->DeepCopy( arr );
910 ped->SetName( vtkExodusIIReader::GetPedigreeNodeIdArrayName() );
911
912 pd->SetGlobalIds( arr );
913 pd->SetPedigreeIds( ped );
914 ped->FastDelete();
915
916 status -= 4;
917 }
918 }
919
920 if ( this->GenerateImplicitElementIdArray )
921 {
922 // This retrieves the old style map if it is a parallel data set. The old
923 // style map stores the global implicit id if parallel. Otherwise it
924 // generates the implicit id.
925 vtkExodusIICacheKey key( -1, vtkExodusIIReader::IMPLICIT_ELEMENT_ID, otyp, obj );
926 vtkDataArray* arr = this->GetCacheOrRead( key );
927 if ( arr )
928 {
929 cd->AddArray( arr );
930 }
931
932 }
933
934 if ( this->GenerateImplicitNodeIdArray )
935 {
936 // This retrieves the old style map if it is a parallel data set. The old
937 // style map stores the global implicit id if parallel. Otherwise it
938 // generates the implicit id.
939 vtkExodusIICacheKey key( -1, vtkExodusIIReader::IMPLICIT_NODE_ID, otyp, obj );
940 vtkDataArray* arr = this->GetCacheOrRead( key );
941 vtkPointData* pd = output->GetPointData();
942 if ( arr )
943 {
944 pd->AddArray( arr );
945 }
946 }
947
948 if ( this->GenerateFileIdArray )
949 { // Don't cache this... it's not worth it.
950 vtkIdType numCells = output->GetNumberOfCells();
951 vtkIntArray* iarr = vtkIntArray::New();
952 iarr->SetNumberOfComponents( 1 );
953 iarr->SetNumberOfTuples( numCells );
954 iarr->SetName( this->GetFileIdArrayName() );
955 cd->AddArray( iarr );
956 iarr->FastDelete();
957 for ( vtkIdType i = 0; i < numCells; ++ i )
958 {
959 iarr->SetValue( i, this->FileId );
960 }
961 }
962
963 return status;
964 }
965
966 //-----------------------------------------------------------------------------
AssembleOutputGlobalArrays(vtkIdType timeStep,int otyp,int obj,BlockSetInfoType * bsinfop,vtkUnstructuredGrid * output)967 int vtkExodusIIReaderPrivate::AssembleOutputGlobalArrays(
968 vtkIdType timeStep, int otyp, int obj, BlockSetInfoType* bsinfop,
969 vtkUnstructuredGrid* output )
970 {
971 (void)obj;
972 vtkFieldData *ofieldData = output->GetFieldData();
973
974 int status = 1;
975 std::vector<ArrayInfoType>::iterator ai;
976 int aidx = 0;
977
978 for (
979 ai = this->ArrayInfo[ vtkExodusIIReader::GLOBAL ].begin();
980 ai != this->ArrayInfo[ vtkExodusIIReader::GLOBAL ].end();
981 ++ai, ++aidx )
982 {
983 if ( ! ai->Status )
984 {
985 continue;
986 }
987
988 // Add time-varying global data
989 vtkExodusIICacheKey tdKey( -1, vtkExodusIIReader::GLOBAL_TEMPORAL, -1, aidx );
990 vtkDataArray* temporalData = this->GetCacheOrRead( tdKey );
991 if ( ! temporalData )
992 {
993 vtkDebugMacro( "Unable to read array " << ai->Name.c_str() );
994 status = 0;
995 continue;
996 }
997
998 ofieldData->AddArray(temporalData);
999 }
1000
1001 // Add block id information for the exodus writer (if we're an element block)
1002 if ( otyp == vtkExodusIIReader::ELEM_BLOCK )
1003 {
1004 vtkIntArray *elemBlockIdArray = vtkIntArray::New();
1005 elemBlockIdArray->SetNumberOfComponents( 1 );
1006 elemBlockIdArray->SetNumberOfValues( 1 ); // one elem block per unstructured grid
1007 elemBlockIdArray->SetName( "ElementBlockIds" );
1008 elemBlockIdArray->SetValue( 0, bsinfop->Id );
1009 ofieldData->AddArray( elemBlockIdArray );
1010 elemBlockIdArray->Delete();
1011 }
1012
1013 // Add QA record, title, and INFO record metadata from the Exodus II file
1014 vtkExodusIICacheKey qakey( -1, vtkExodusIIReader::QA_RECORDS, 0, 0 );
1015 vtkDataArray* arr = this->GetCacheOrRead( qakey );
1016 if ( arr )
1017 {
1018 ofieldData->AddArray(arr);
1019 }
1020
1021 // Add the title
1022 {
1023 vtkStringArray* sarr = vtkStringArray::New();
1024 sarr->SetName( "Title" );
1025 sarr->SetNumberOfComponents( 1 );
1026 sarr->SetNumberOfTuples(1);
1027 sarr->SetValue(0, this->ModelParameters.title);
1028 ofieldData->AddArray(sarr);
1029 sarr->Delete();
1030 }
1031
1032 // Add mode_shape/time_step
1033 if (this->HasModeShapes)
1034 {
1035 vtkNew<vtkIntArray> dataIndexArray;
1036 dataIndexArray->SetName("mode_shape");
1037 dataIndexArray->SetNumberOfComponents(1);
1038 dataIndexArray->SetNumberOfTuples(1);
1039 // mode-shape == (timestep + 1). See vtkExodusIIReader::SetModeShape().
1040 dataIndexArray->SetValue(0, (timeStep + 1));
1041 ofieldData->AddArray(dataIndexArray);
1042
1043 vtkNew<vtkIntArray> modeShapeRange;
1044 modeShapeRange->SetName("mode_shape_range");
1045 modeShapeRange->SetNumberOfComponents(2);
1046 modeShapeRange->SetNumberOfTuples(1);
1047 modeShapeRange->SetValue(0, this->Parent->GetModeShapesRange()[0]);
1048 modeShapeRange->SetValue(1, this->Parent->GetModeShapesRange()[1]);
1049 ofieldData->AddArray(modeShapeRange);
1050 }
1051
1052 vtkExodusIICacheKey infokey( -1, vtkExodusIIReader::INFO_RECORDS, 0, 0 );
1053 arr = this->GetCacheOrRead( infokey );
1054 if ( arr )
1055 {
1056 ofieldData->AddArray(arr);
1057 }
1058
1059 return status;
1060 }
1061
1062 //-----------------------------------------------------------------------------
AssembleOutputPointMaps(vtkIdType timeStep,BlockSetInfoType * bsinfop,vtkUnstructuredGrid * output)1063 int vtkExodusIIReaderPrivate::AssembleOutputPointMaps( vtkIdType timeStep,
1064 BlockSetInfoType* bsinfop, vtkUnstructuredGrid* output )
1065 {
1066 (void)timeStep;
1067 int status = 1;
1068 std::vector<MapInfoType>::iterator mi;
1069 int midx = 0;
1070
1071 for (
1072 mi = this->MapInfo[ vtkExodusIIReader::NODE_MAP ].begin();
1073 mi != this->MapInfo[ vtkExodusIIReader::NODE_MAP ].end();
1074 ++mi, ++midx )
1075 {
1076 if ( ! mi->Status )
1077 continue; // Skip arrays we don't want.
1078
1079 vtkIdTypeArray* src = vtkArrayDownCast<vtkIdTypeArray>( this->GetCacheOrRead(
1080 vtkExodusIICacheKey( -1, vtkExodusIIReader::NODE_MAP, 0, midx ) ) );
1081 if ( !src )
1082 {
1083 vtkDebugMacro(
1084 "Unable to read point map array \""
1085 << mi->Name.c_str() << "\" (" << midx << ")" );
1086 status = 0;
1087 continue;
1088 }
1089
1090 this->AddPointArray( src, bsinfop, output );
1091 }
1092 return status;
1093 }
1094
1095 //-----------------------------------------------------------------------------
AssembleOutputCellMaps(vtkIdType vtkNotUsed (timeStep),int otyp,int obj,BlockSetInfoType * bsinfop,vtkUnstructuredGrid * output)1096 int vtkExodusIIReaderPrivate::AssembleOutputCellMaps(
1097 vtkIdType vtkNotUsed(timeStep), int otyp, int obj, BlockSetInfoType* bsinfop,
1098 vtkUnstructuredGrid* output )
1099 {
1100 (void)obj;
1101 // Don't create arrays for deselected objects
1102 if ( ! output || ! bsinfop->Status )
1103 {
1104 return 1;
1105 }
1106
1107 // Ignore invalid otyp values (sets cannot have maps, only blocks).
1108 int mtyp = this->GetMapTypeFromObjectType( otyp );
1109 std::map<int,std::vector<MapInfoType> >::iterator mmi =
1110 this->MapInfo.find( mtyp );
1111 if ( mmi == this->MapInfo.end() )
1112 {
1113 return 1;
1114 }
1115
1116 vtkCellData* cd = output->GetCellData();
1117 // For each map defined on objects of the same type as our output,
1118 // look for ones that are turned on (Status != 0).
1119 std::vector<MapInfoType>::iterator mi;
1120 int midx = 0;
1121 for ( mi = mmi->second.begin(); mi != mmi->second.end(); ++mi, ++midx )
1122 {
1123 if ( ! mi->Status )
1124 continue;
1125
1126 vtkDataArray* src = this->GetCacheOrRead(
1127 vtkExodusIICacheKey( -1, mmi->first, 0, midx ) );
1128 if ( ! src )
1129 continue;
1130
1131 if ( otyp == vtkExodusIIReader::ELEM_BLOCK )
1132 {
1133 if (
1134 bsinfop->Size == src->GetNumberOfTuples() &&
1135 bsinfop->FileOffset == 1 &&
1136 this->BlockInfo[otyp].size() == 1 )
1137 {
1138 cd->AddArray( src );
1139 }
1140 else
1141 {
1142 // Create the array and copy the applicable subset from the map
1143 vtkIdTypeArray* arr = vtkIdTypeArray::New();
1144 arr->SetName( mi->Name.c_str() );
1145 arr->SetNumberOfComponents( 1 );
1146 arr->SetNumberOfTuples( bsinfop->Size );
1147 memcpy( arr->GetVoidPointer(0), src->GetVoidPointer( bsinfop->FileOffset - 1 ),
1148 bsinfop->Size * sizeof(vtkIdType) );
1149 cd->AddArray( arr );
1150 arr->FastDelete();
1151 }
1152 }
1153 else
1154 {
1155 // FIXME: We have a set (no maps are defined on sets but we could determine
1156 // map values given the set generators) or an edge/face block (unclear
1157 // whether maps are useful/possible on these block types).
1158 }
1159 }
1160 return 1;
1161 }
1162
1163 //-----------------------------------------------------------------------------
GetPolyhedronFaceConnectivity(vtkIdType fileLocalFaceId,vtkIdType * & facePtIds)1164 vtkIdType vtkExodusIIReaderPrivate::GetPolyhedronFaceConnectivity(
1165 vtkIdType fileLocalFaceId,
1166 vtkIdType*& facePtIds)
1167 {
1168 // I. Find the face block containing \a fileLocalFaceId.
1169 // An element may refer to faces anywhere in the file, not just in
1170 // a corresponding face block, so each face of an element may be
1171 // in a different face block.
1172 if (this->BlockInfo.find(EX_FACE_BLOCK) == this->BlockInfo.end())
1173 {
1174 vtkWarningMacro("No face blocks in exodus file, but polyhedral cell requires at least 1");
1175 return -1;
1176 }
1177 std::vector<BlockInfoType>& faceBlocks(this->BlockInfo[EX_FACE_BLOCK]);
1178 std::vector<BlockInfoType>::const_iterator fbit;
1179 int fbidx = 0;
1180 vtkIdType blockLocalFaceId = -1;
1181 for (
1182 fbit = faceBlocks.begin();
1183 fbit != faceBlocks.end() && (blockLocalFaceId = fileLocalFaceId + 1 - fbit->FileOffset) > fbit->Size;
1184 ++fbit)
1185 {
1186 ++fbidx;
1187 //std::cout << "Skipping block " << fbit->Id << " (" << fbit->Name << ") offset " << fbit->FileOffset << "\n";
1188 }
1189 if (fbit == faceBlocks.end() || blockLocalFaceId < 0)
1190 {
1191 vtkWarningMacro(
1192 "Could not find a face block containing face " << fileLocalFaceId <<
1193 " (block-relative " << blockLocalFaceId << ").");
1194 return -1;
1195 }
1196 std::map<int, std::vector< std::vector< vtkIdType > > >::iterator fcit =
1197 this->PolyhedralFaceConnArrays.find(fbidx);
1198 if (fcit == this->PolyhedralFaceConnArrays.end())
1199 {
1200 // Add faces for the entire face-block to the cache (because
1201 // the connectivity is run-length encoded). Hopefully each
1202 // polyhedral element block will use many faces from each
1203 // face block so the cost is amortized.
1204 vtkSmartPointer<vtkIdTypeArray> fconn =
1205 vtkArrayDownCast<vtkIdTypeArray>(
1206 this->GetCacheOrRead(
1207 vtkExodusIICacheKey(
1208 -1, vtkExodusIIReader::FACE_BLOCK_CONN, fbidx, 0 )));
1209 if (!fconn)
1210 {
1211 vtkWarningMacro(
1212 "Face block " << fbidx
1213 << " (id " << fbit->Id << ") missing its connectivity array.");
1214 return -1;
1215 }
1216 vtkSmartPointer<vtkIntArray> ptsPerFace =
1217 vtkArrayDownCast<vtkIntArray>(
1218 this->GetCacheOrRead(
1219 vtkExodusIICacheKey(
1220 -1, vtkExodusIIReader::ENTITY_COUNTS, fbidx,
1221 /* get counts for face-block as opposed to element-block: */ 1)));
1222 if (!ptsPerFace)
1223 {
1224 vtkWarningMacro(
1225 "Face block " << fbidx
1226 << " (id " << fbit->Id << ") missing its points-per-face array.");
1227 return -1;
1228 }
1229 // Decompose the whole face block into a ragged
1230 // array (vector of vectors) to future lookups
1231 // are fast:
1232 static std::vector<std::vector<vtkIdType> > blank;
1233 this->PolyhedralFaceConnArrays[fbidx] = blank;
1234 fcit = this->PolyhedralFaceConnArrays.find(fbidx);
1235 vtkIdType numFaces = ptsPerFace->GetNumberOfTuples();
1236 fcit->second.resize(numFaces);
1237 vtkIdType cc = 0;
1238 for (vtkIdType ii = 0; ii < numFaces; ++ii)
1239 {
1240 int numPts = ptsPerFace->GetValue(ii);
1241 std::vector<vtkIdType>& facePts(fcit->second[ii]);
1242 facePts.resize(numPts);
1243 for (int jj = 0; jj < numPts; ++jj)
1244 {
1245 facePts[jj] = fconn->GetValue(cc++);
1246 }
1247 }
1248 }
1249 // II. Now that we have a cache for the face block, look up the
1250 // one face in the block we currently need:
1251 vtkIdType numPoints =
1252 static_cast<vtkIdType>(fcit->second[blockLocalFaceId].size());
1253 facePtIds = &fcit->second[blockLocalFaceId][0];
1254 return numPoints;
1255 }
1256
1257 //-----------------------------------------------------------------------------
FreePolyhedronFaceArrays()1258 void vtkExodusIIReaderPrivate::FreePolyhedronFaceArrays()
1259 {
1260 this->PolyhedralFaceConnArrays.clear();
1261 }
1262
1263 //-----------------------------------------------------------------------------
InsertBlockPolyhedra(BlockInfoType * binfo,vtkIntArray * facesPerCell,vtkIdTypeArray * exoCellConn)1264 void vtkExodusIIReaderPrivate::InsertBlockPolyhedra(
1265 BlockInfoType* binfo,
1266 vtkIntArray* facesPerCell,
1267 vtkIdTypeArray* exoCellConn)
1268 {
1269 vtkIdType numCells = facesPerCell->GetMaxId() + 1;
1270
1271 // The Exodus file format is more compact than VTK's; it
1272 // allows multiple elements(cells) to refer to the same face so
1273 // that no face->point connectivity needs to be repeated.
1274 // VTK's polyhedral cells unpacks each element's faces
1275 // into a contiguous list for fast access to each element's
1276 // face->point connectivity.
1277 // So, we cannot use the arrays we are given as-is.
1278 // Also, VTK requires a list, without duplicates, of all the
1279 // points per cell (across all its faces), which Exodus does
1280 // not provide.
1281
1282 // II. Insert cells using face-point connectivity.
1283 vtkIdType curCell = 0;
1284 vtkIdType curCellCurFace = 0;
1285 std::vector<vtkIdType> vtkCellPts;
1286 for (vtkIdType i = 0; i < numCells; ++i)
1287 {
1288 vtkCellPts.clear();
1289 int numFacesThisCell = facesPerCell->GetValue(curCell++);
1290 for (vtkIdType j = 0; j < numFacesThisCell; ++j)
1291 {
1292 vtkIdType curFace = exoCellConn->GetValue(curCellCurFace++);
1293 //std::vector<vtkIdType>& curFacePts(facePointLists[curFace]);
1294 vtkIdType* facePtsRaw;
1295 vtkIdType numFacePts = this->GetPolyhedronFaceConnectivity(curFace, facePtsRaw);
1296 // Copy face connectivity, optionally (and usually) mapping to squeezed-points for the block
1297 vtkCellPts.push_back(numFacePts);
1298 for (vtkIdType pp = 0; pp < numFacePts; ++pp)
1299 {
1300 vtkCellPts.push_back(this->SqueezePoints ?
1301 this->GetSqueezePointId(binfo, facePtsRaw[pp]) :
1302 facePtsRaw[pp]);
1303 }
1304 }
1305 binfo->CachedConnectivity->InsertNextCell(
1306 VTK_POLYHEDRON, numFacesThisCell, &vtkCellPts[0]);
1307 }
1308 this->FreePolyhedronFaceArrays();
1309 }
1310
1311 //-----------------------------------------------------------------------------
InsertBlockCells(int otyp,int obj,int conn_type,int timeStep,BlockInfoType * binfo)1312 void vtkExodusIIReaderPrivate::InsertBlockCells(
1313 int otyp, int obj, int conn_type, int timeStep, BlockInfoType* binfo )
1314 {
1315 (void)timeStep;
1316 (void)otyp;
1317 if ( binfo->Size == 0 )
1318 {
1319 // No entries in this block.
1320 // This happens in parallel filesets when all
1321 // elements are distributed to other files.
1322 // Silently ignore.
1323 return;
1324 }
1325
1326 vtkIntArray* ent = nullptr;
1327 if ( binfo->PointsPerCell == 0 )
1328 {
1329 int arrId = (conn_type == vtkExodusIIReader::ELEM_BLOCK_ELEM_CONN ? 0 : 1);
1330 ent = vtkArrayDownCast<vtkIntArray>(
1331 this->GetCacheOrRead(
1332 vtkExodusIICacheKey( -1, vtkExodusIIReader::ENTITY_COUNTS, obj, arrId
1333 )));
1334 if ( ! ent )
1335 {
1336 vtkErrorMacro(
1337 "Entity used 0 points per cell, "
1338 "but didn't return polyhedra correctly" );
1339 binfo->Status = 0;
1340 return;
1341 }
1342 ent->Register(this);
1343 }
1344
1345 // Handle 3-D polyhedra (not 2-D polygons) separately
1346 // from other cell types for simplicity.
1347 // In addition to the element block connectivity (which
1348 // lists faces bounding the polyhedra, we must load face
1349 // block connectivity (which lists corner nodes for each
1350 // face).
1351 if (binfo->CellType == VTK_POLYHEDRON)
1352 {
1353 vtkIdTypeArray* efconn = vtkArrayDownCast<vtkIdTypeArray>(
1354 this->GetCacheOrRead(
1355 vtkExodusIICacheKey( -1, vtkExodusIIReader::ELEM_BLOCK_FACE_CONN, obj, 0 )));
1356 if (efconn)
1357 efconn->Register(this);
1358 if (!efconn || !ent)
1359 {
1360 vtkWarningMacro(
1361 << "Element block (" << efconn << ") and "
1362 << "number of faces per poly (" << ent << ") arrays are both required. "
1363 << "Skipping block id " << binfo->Id << "; expect trouble." );
1364 binfo->Status = 0;
1365 if (ent) ent->UnRegister(this);
1366 if (efconn) efconn->UnRegister(this);
1367 return;
1368 }
1369 this->InsertBlockPolyhedra(binfo, ent, efconn);
1370 efconn->UnRegister(this);
1371 ent->UnRegister(this);
1372 return;
1373 }
1374
1375 vtkIdTypeArray* arr = vtkArrayDownCast<vtkIdTypeArray>(
1376 this->GetCacheOrRead(
1377 vtkExodusIICacheKey( -1, conn_type, obj, 0 )));
1378 if ( ! arr )
1379 {
1380 vtkWarningMacro(
1381 "Block wasn't present in file? Working around it. Expect trouble." );
1382 binfo->Status = 0;
1383 if (ent)
1384 {
1385 ent->UnRegister(this);
1386 }
1387 return;
1388 }
1389
1390 if (this->SqueezePoints)
1391 {
1392 std::vector<vtkIdType> cellIds;
1393 cellIds.resize( binfo->PointsPerCell );
1394 auto srcIds = arr->GetPointer( 0 );
1395
1396 for ( int i = 0; i < binfo->Size; ++i )
1397 {
1398 int entitiesPerCell;
1399 if (ent)
1400 {
1401 entitiesPerCell = ent->GetValue (i);
1402 cellIds.resize( entitiesPerCell );
1403 }
1404 else
1405 {
1406 entitiesPerCell = binfo->PointsPerCell;
1407 }
1408
1409 for ( int p = 0; p < entitiesPerCell; ++p )
1410 {
1411 cellIds[p] = this->GetSqueezePointId( binfo, srcIds[p] );
1412 //cout << " " << srcIds[p] << "(" << cellIds[p] << ")";
1413 }
1414 //cout << "\n";
1415 //cout << " " <<
1416 binfo->CachedConnectivity->InsertNextCell( binfo->CellType, entitiesPerCell, &cellIds[0] );
1417 srcIds += entitiesPerCell;
1418 }
1419 //cout << "\n";
1420 }
1421 else
1422 {
1423 // The id type size used by exodus should match VTK_USE_64BIT_IDS length
1424 vtkIdType* srcIds = (vtkIdType*) arr->GetPointer( 0 );
1425
1426 for ( int i = 0; i < binfo->Size; ++i )
1427 {
1428 int entitiesPerCell = binfo->PointsPerCell;
1429 if ( ent != nullptr)
1430 {
1431 entitiesPerCell = ent->GetValue (i);
1432 }
1433 binfo->CachedConnectivity->InsertNextCell( binfo->CellType, entitiesPerCell, srcIds );
1434 srcIds += entitiesPerCell;
1435 //for ( int k = 0; k < binfo->PointsPerCell; ++k )
1436 //cout << " " << srcIds[k];
1437 //cout << "\n";
1438 }
1439 }
1440 if (ent)
1441 {
1442 ent->UnRegister (this);
1443 }
1444 }
1445
1446 //-----------------------------------------------------------------------------
InsertSetCells(int otyp,int obj,int conn_type,int timeStep,SetInfoType * sinfo)1447 void vtkExodusIIReaderPrivate::InsertSetCells(
1448 int otyp, int obj, int conn_type, int timeStep,
1449 SetInfoType* sinfo )
1450 {
1451 (void)timeStep;
1452 if ( sinfo->Size == 0 )
1453 {
1454 // No entries in this set.
1455 // This happens in parallel filesets when all elements are distributed to other files.
1456 // Silently ignore.
1457 return;
1458 }
1459
1460 auto* arr = vtkArrayDownCast<vtkIdTypeArray>(
1461 this->GetCacheOrRead( vtkExodusIICacheKey( -1, conn_type, obj, 0 ) ) );
1462 if ( ! arr )
1463 {
1464 vtkWarningMacro( "Set wasn't present in file? Working around it. Expect trouble." );
1465 sinfo->Status = 0;
1466 return;
1467 }
1468
1469 switch ( otyp )
1470 {
1471 case vtkExodusIIReader::NODE_SET:
1472 // Easy
1473 this->InsertSetNodeCopies( arr, otyp, obj, sinfo );
1474 break;
1475 case vtkExodusIIReader::EDGE_SET:
1476 // Not so fun. We must copy cells from possibly many edge blocks.
1477 this->InsertSetCellCopies( arr, vtkExodusIIReader::EDGE_BLOCK, obj, sinfo );
1478 break;
1479 case vtkExodusIIReader::FACE_SET:
1480 // Not so fun. We must copy cells from possibly many face blocks.
1481 this->InsertSetCellCopies( arr, vtkExodusIIReader::FACE_BLOCK, obj, sinfo );
1482 break;
1483 case vtkExodusIIReader::SIDE_SET:
1484 // Way hard even when we let Exodus do a lot for us.
1485 this->InsertSetSides( arr, otyp, obj, sinfo );
1486 break;
1487 case vtkExodusIIReader::ELEM_SET:
1488 // Not so fun. We must copy cells from possibly many element blocks.
1489 this->InsertSetCellCopies( arr, vtkExodusIIReader::ELEM_BLOCK, obj, sinfo );
1490 break;
1491 }
1492 }
1493
1494 //-----------------------------------------------------------------------------
AddPointArray(vtkDataArray * src,BlockSetInfoType * bsinfop,vtkUnstructuredGrid * output)1495 void vtkExodusIIReaderPrivate::AddPointArray(
1496 vtkDataArray* src, BlockSetInfoType* bsinfop, vtkUnstructuredGrid* output )
1497 {
1498 vtkPointData* pd = output->GetPointData();
1499 if ( this->SqueezePoints )
1500 {
1501 // subset the array using PointMap
1502 vtkDataArray* dest = vtkDataArray::CreateDataArray( src->GetDataType() );
1503 dest->SetName( src->GetName() );
1504 dest->SetNumberOfComponents( src->GetNumberOfComponents() );
1505 dest->SetNumberOfTuples( bsinfop->NextSqueezePoint );
1506 std::map<vtkIdType,vtkIdType>::iterator it, itEnd;
1507 //
1508 // I moved the end condition of the loop out of the for(;;) loop.
1509 // Assuming it doesn't change within the loop itself!
1510 // The reason is that the code was making the call every loop.
1511 //
1512 itEnd = bsinfop->PointMap.end();
1513 for ( it = bsinfop->PointMap.begin(); it != itEnd; ++ it )
1514 {
1515 pd->CopyTuple( src, dest, it->first, it->second );
1516 }
1517 pd->AddArray( dest );
1518 dest->FastDelete();
1519 }
1520 else
1521 {
1522 pd->AddArray( src );
1523 }
1524 }
1525
1526 //-----------------------------------------------------------------------------
InsertSetNodeCopies(vtkIdTypeArray * refs,int otyp,int obj,SetInfoType * sinfo)1527 void vtkExodusIIReaderPrivate::InsertSetNodeCopies( vtkIdTypeArray* refs, int otyp, int obj, SetInfoType* sinfo )
1528 {
1529 (void)otyp;
1530 (void)obj;
1531 // Insert a "VERTEX" cell for each node in the set.
1532 vtkIdType ref;
1533 vtkIdType tmp;
1534 auto* iptr = refs->GetPointer( 0 );
1535
1536 if ( this->SqueezePoints )
1537 { // this loop is separated out to handle case (stride > 1 && pref[1] < 0 && this->SqueezePoints)
1538 for ( ref = 0; ref < refs->GetNumberOfTuples(); ++ref, ++iptr )
1539 {
1540 tmp = *iptr;
1541 vtkIdType x = this->GetSqueezePointId( sinfo, tmp );
1542 sinfo->CachedConnectivity->InsertNextCell( VTK_VERTEX, 1, &x );
1543 }
1544 }
1545 else
1546 {
1547 for ( ref = 0; ref < refs->GetNumberOfTuples(); ++ref, ++iptr )
1548 {
1549 tmp = *iptr;
1550 sinfo->CachedConnectivity->InsertNextCell( VTK_VERTEX, 1, &tmp );
1551 }
1552 }
1553 }
1554
1555 //-----------------------------------------------------------------------------
InsertSetCellCopies(vtkIdTypeArray * refs,int otyp,int obj,SetInfoType * sinfo)1556 void vtkExodusIIReaderPrivate::InsertSetCellCopies(
1557 vtkIdTypeArray* refs, int otyp, int obj, SetInfoType* sinfo )
1558 {
1559 (void)obj;
1560 // First, sort the set by entry number (element, face, or edge ID)
1561 // so that we can refer to each block just once as we process cells.
1562 vtkSortDataArray::SortArrayByComponent( refs, 0 );
1563 refs->Register( this ); // Don't let the cache delete this array when we fetch others...
1564
1565 vtkIdType nrefs = refs->GetNumberOfTuples();
1566 vtkIdType ref = 0;
1567 vtkIdType bnum = -1;
1568 vtkIdType lastBlockEntry = -1;
1569 auto* pref = refs->GetPointer( 0 );
1570 int stride = refs->GetNumberOfComponents();
1571 BlockInfoType* binfop = nullptr; //&this->BlockInfo[otyp][bnum];
1572 int* nodeconn = nullptr;
1573 vtkIdType* cellConn;
1574 int nnpe = 0;
1575 vtkIntArray* nconn;
1576 std::vector<vtkIdType> tmpTuple;
1577 while ( ref < nrefs )
1578 {
1579 int loadNewBlk = 0;
1580 while ( pref[0] >= lastBlockEntry )
1581 { // advance to the next block (always true first time through parent loop)
1582 ++bnum;
1583 if ( bnum >= (int) this->BlockInfo[otyp].size() )
1584 return;
1585 binfop = &this->BlockInfo[otyp][bnum];
1586 lastBlockEntry = binfop->FileOffset + binfop->Size - 1;
1587 loadNewBlk = 1;
1588 }
1589 if ( loadNewBlk )
1590 {
1591 nconn = vtkArrayDownCast<vtkIntArray>(
1592 this->GetCacheOrRead( vtkExodusIICacheKey( -1, this->GetBlockConnTypeFromBlockType( otyp ), bnum, 0 ) )
1593 );
1594 if ( ! nconn )
1595 {
1596 vtkErrorMacro( "Unable to read block \"" << binfop->Name.c_str() << "\" (" << binfop->Id << ")" );
1597 break;
1598 }
1599 nodeconn = nconn->GetPointer( 0 );
1600 nnpe = nconn->GetNumberOfComponents();
1601 if ( stride > 1 || this->SqueezePoints )
1602 {
1603 tmpTuple.resize( nnpe );
1604 }
1605 }
1606
1607 if ( stride > 1 && pref[1] < 0 )
1608 { // negative orientation => reverse cell connectivity
1609 vtkIdType off = (pref[0] + 2 - binfop->FileOffset) * nnpe - 1;
1610 for ( int k = 0; k < nnpe; ++k )
1611 tmpTuple[k] = nodeconn[off-k];
1612 cellConn = &tmpTuple[0];
1613 }
1614 else
1615 #ifndef VTK_USE_64BIT_IDS
1616 if ( this->SqueezePoints )
1617 #endif // VTK_USE_64BIT_IDS
1618 {
1619 vtkIdType off = (pref[0] + 1 - binfop->FileOffset) * nnpe;
1620 for ( int k = 0; k < nnpe; ++k )
1621 tmpTuple[k] = nodeconn[off+k];
1622 cellConn = &tmpTuple[0];
1623 }
1624 #ifndef VTK_USE_64BIT_IDS
1625 else
1626 {
1627 cellConn = (int*)nodeconn + (pref[0] + 1 - binfop->FileOffset) * nnpe;
1628 }
1629 #endif // VTK_USE_64BIT_IDS
1630
1631 if ( this->SqueezePoints )
1632 { // this loop is separated out to handle case (stride > 1 && pref[1] < 0 && this->SqueezePoints)
1633 for ( int k = 0; k < nnpe; ++k )
1634 { // FIXME: Double-check that cellConn[k] should be in-place re-assigned.
1635 cellConn[k] = this->GetSqueezePointId( sinfo, cellConn[k] );
1636 }
1637 }
1638
1639 sinfo->CachedConnectivity->InsertNextCell( binfop->CellType, nnpe, cellConn );
1640
1641 pref += stride;
1642 ++ref;
1643 }
1644
1645 refs->UnRegister( this );
1646 }
1647
1648 //-----------------------------------------------------------------------------
InsertSetSides(vtkIdTypeArray * refs,int otyp,int obj,SetInfoType * sinfo)1649 void vtkExodusIIReaderPrivate::InsertSetSides(
1650 vtkIdTypeArray* refs, int otyp, int obj, SetInfoType* sinfo )
1651 {
1652 static const int sideCellTypes[] =
1653 {
1654 VTK_EMPTY_CELL, // don't support any cells with 0 nodes per side
1655 VTK_VERTEX,
1656 VTK_LINE,
1657 VTK_TRIANGLE,
1658 VTK_QUAD,
1659 VTK_EMPTY_CELL, // don't support any cells with 5 nodes per side
1660 VTK_QUADRATIC_TRIANGLE,
1661 VTK_EMPTY_CELL, // don't support any cells with 7 nodes per side
1662 VTK_QUADRATIC_QUAD,
1663 VTK_BIQUADRATIC_QUAD
1664 };
1665
1666 int numSides = this->SetInfo[otyp][obj].Size;
1667 auto* nodesPerSide = refs->GetPointer( 0 );
1668 auto* sideNodes = nodesPerSide + numSides;
1669 std::vector<vtkIdType> cellConn;
1670 cellConn.resize( 9 );
1671
1672 if ( this->SqueezePoints )
1673 {
1674 int nnpe;
1675 for ( int side = 0; side < numSides; ++side )
1676 {
1677 nnpe = nodesPerSide[side];
1678 for ( int k = 0; k < nnpe; ++k )
1679 {
1680 cellConn[k] = this->GetSqueezePointId( sinfo, sideNodes[k] );
1681 }
1682 sinfo->CachedConnectivity->InsertNextCell( sideCellTypes[nnpe], nnpe, &cellConn[0] );
1683 sideNodes += nnpe;
1684 }
1685 }
1686 else
1687 {
1688 int nnpe;
1689 for ( int side = 0; side < numSides; ++side )
1690 {
1691 nnpe = nodesPerSide[side];
1692 #ifdef VTK_USE_64BIT_IDS
1693 for ( int k = 0; k < nnpe; ++k )
1694 {
1695 cellConn[k] = sideNodes[k];
1696 }
1697 sinfo->CachedConnectivity->InsertNextCell( sideCellTypes[nnpe], nnpe, &cellConn[0] );
1698 #else // VTK_USE_64BIT_IDS
1699 sinfo->CachedConnectivity->InsertNextCell( sideCellTypes[nnpe], nnpe, sideNodes );
1700 #endif // VTK_USE_64BIT_IDS
1701 sideNodes += nnpe;
1702 }
1703 }
1704 }
1705
1706 //-----------------------------------------------------------------------------
GetCacheOrRead(vtkExodusIICacheKey key)1707 vtkDataArray* vtkExodusIIReaderPrivate::GetCacheOrRead( vtkExodusIICacheKey key )
1708 {
1709 vtkDataArray* arr;
1710 // Never cache points deflected for a mode shape animation... doubles don't make good keys.
1711 if ( this->HasModeShapes && key.ObjectType == vtkExodusIIReader::NODAL_COORDS )
1712 {
1713 arr = nullptr;
1714 }
1715 else
1716 {
1717 arr = this->Cache->Find( key );
1718 }
1719
1720 if ( arr )
1721 {
1722 //
1723 return arr;
1724 }
1725
1726 int exoid = this->Exoid;
1727 int maxNameLength = this->Parent->GetMaxNameLength();
1728
1729 // If array is nullptr, try reading it from file.
1730 if ( key.ObjectType == vtkExodusIIReader::GLOBAL )
1731 {
1732 // need to assemble result array from smaller ones.
1733 // call GetCacheOrRead() for each smaller array
1734 // pay attention to SqueezePoints
1735
1736 //ArrayInfoType* ainfop = &this->ArrayInfo[vtkExodusIIReader::GLOBAL][key.ArrayId];
1737 arr = vtkDataArray::CreateDataArray( VTK_DOUBLE );
1738 arr->SetName( this->GetGlobalVariableValuesArrayName() );
1739 arr->SetNumberOfComponents( 1 );
1740 arr->SetNumberOfTuples(
1741 static_cast<vtkIdType>(
1742 this->ArrayInfo[ vtkExodusIIReader::GLOBAL ].size()));
1743
1744 if ( ex_get_glob_vars( exoid, key.Time + 1, arr->GetNumberOfTuples(),
1745 arr->GetVoidPointer( 0 ) ) < 0 )
1746 {
1747 vtkErrorMacro( "Could not read global variable " << this->GetGlobalVariableValuesArrayName() << "." );
1748 arr->Delete();
1749 arr = nullptr;
1750 }
1751 }
1752 else if ( key.ObjectType == vtkExodusIIReader::NODAL )
1753 {
1754 // read nodal array
1755 ArrayInfoType* ainfop = &this->ArrayInfo[vtkExodusIIReader::NODAL][key.ArrayId];
1756 int ncomps = ( this->ModelParameters.num_dim == 2 && ainfop->Components == 2 ) ? 3 : ainfop->Components;
1757 arr = vtkDataArray::CreateDataArray( ainfop->StorageType );
1758 arr->SetName( ainfop->Name.c_str() );
1759 arr->SetNumberOfComponents( ncomps );
1760 arr->SetNumberOfTuples( this->ModelParameters.num_nodes );
1761 if ( ncomps != ainfop->Components )
1762 {
1763 arr->FillComponent( 2, 0. );
1764 }
1765 if ( ncomps == 1 )
1766 {
1767 if ( ex_get_var( exoid, key.Time + 1, static_cast<ex_entity_type>( key.ObjectType ),
1768 ainfop->OriginalIndices[0], 0, arr->GetNumberOfTuples(),
1769 arr->GetVoidPointer( 0 ) ) < 0 )
1770 {
1771 vtkErrorMacro( "Could not read nodal result variable " << ainfop->Name.c_str() << "." );
1772 arr->Delete();
1773 arr = nullptr;
1774 }
1775 }
1776 else
1777 {
1778 // Exodus doesn't support reading with a stride, so we have to manually interleave the arrays. Bleh.
1779 std::vector<std::vector<double> > tmpVal;
1780 tmpVal.resize( ainfop->Components );
1781 int c;
1782 for ( c = 0; c < ainfop->Components; ++c )
1783 {
1784 vtkIdType N = this->ModelParameters.num_nodes;
1785 tmpVal[c].resize( N );
1786 if ( ex_get_var( exoid, key.Time + 1, static_cast<ex_entity_type>( key.ObjectType ),
1787 ainfop->OriginalIndices[c], 0, arr->GetNumberOfTuples(),
1788 &tmpVal[c][0] ) < 0)
1789 {
1790 vtkErrorMacro( "Could not read nodal result variable " << ainfop->OriginalNames[c].c_str() << "." );
1791 arr->Delete();
1792 arr = nullptr;
1793 return nullptr;
1794 }
1795 }
1796 int t;
1797 std::vector<double> tmpTuple;
1798 tmpTuple.resize( ncomps );
1799 tmpTuple[ncomps - 1] = 0.; // In case we're embedding a 2-D vector in 3-D
1800
1801 //
1802 // Lets unroll the most common case - components == 3.
1803 //
1804 if ( ainfop->Components == 3)
1805 {
1806 int maxTuples = arr->GetNumberOfTuples();
1807 for ( t = 0; t < maxTuples; ++t )
1808 {
1809 tmpTuple[0] = tmpVal[0][t];
1810 tmpTuple[1] = tmpVal[1][t];
1811 tmpTuple[2] = tmpVal[2][t];
1812 arr->SetTuple( t, &tmpTuple[0] );
1813 }
1814 }
1815 else
1816 {
1817 for ( t = 0; t < arr->GetNumberOfTuples(); ++t )
1818 {
1819 for ( c = 0; c < ainfop->Components; ++c )
1820 {
1821 tmpTuple[c] = tmpVal[c][t];
1822 }
1823 arr->SetTuple( t, &tmpTuple[0] );
1824 }
1825 }
1826 }
1827 }
1828 else if ( key.ObjectType == vtkExodusIIReader::GLOBAL_TEMPORAL )
1829 {
1830 // read temporal nodal array
1831 ArrayInfoType* ainfop = &this->ArrayInfo[vtkExodusIIReader::GLOBAL][key.ArrayId];
1832 arr = vtkDataArray::CreateDataArray( ainfop->StorageType );
1833 //vtkStdString newArrayName = ainfop->Name + "OverTime";
1834 arr->SetName( ainfop->Name );
1835 arr->SetNumberOfComponents( ainfop->Components );
1836 arr->SetNumberOfTuples( this->GetNumberOfTimeSteps() );
1837 if ( ainfop->Components != 1 )
1838 {
1839 // Exodus doesn't support reading with a stride, so we have to manually interleave the arrays. Bleh.
1840 std::vector<std::vector<double> > tmpVal;
1841 tmpVal.resize( ainfop->Components );
1842 int c;
1843 for ( c = 0; c < ainfop->Components; ++c )
1844 {
1845 vtkIdType N = this->GetNumberOfTimeSteps();
1846 tmpVal[c].resize( N );
1847 if ( ex_get_var_time( exoid, EX_GLOBAL,
1848 ainfop->OriginalIndices[c], key.ObjectId,
1849 1, this->GetNumberOfTimeSteps(), &tmpVal[c][0] ) < 0 )
1850 {
1851 vtkErrorMacro(
1852 "Could not read temporal global result variable "
1853 << ainfop->OriginalNames[c].c_str() << "." );
1854 arr->Delete();
1855 arr = nullptr;
1856 return nullptr;
1857 }
1858 }
1859 int t;
1860 std::vector<double> tmpTuple;
1861 tmpTuple.resize( ainfop->Components );
1862 for ( t = 0; t < arr->GetNumberOfTuples(); ++t )
1863 {
1864 for ( c = 0; c < ainfop->Components; ++c )
1865 {
1866 tmpTuple[c] = tmpVal[c][t];
1867 }
1868 arr->SetTuple( t, &tmpTuple[0] );
1869 }
1870 }
1871 else if ( ex_get_var_time( exoid, EX_GLOBAL,
1872 ainfop->OriginalIndices[0], key.ObjectId,
1873 1, this->GetNumberOfTimeSteps(), arr->GetVoidPointer( 0 ) ) < 0 )
1874 {
1875 vtkErrorMacro(
1876 "Could not read global result variable "
1877 << ainfop->Name.c_str() << "." );
1878 arr->Delete();
1879 arr = nullptr;
1880 }
1881 }
1882 else if ( key.ObjectType == vtkExodusIIReader::NODAL_TEMPORAL )
1883 {
1884 // read temporal nodal array
1885 ArrayInfoType* ainfop = &this->ArrayInfo[vtkExodusIIReader::NODAL][key.ArrayId];
1886 arr = vtkDataArray::CreateDataArray( ainfop->StorageType );
1887 vtkStdString newArrayName = ainfop->Name + "OverTime";
1888 arr->SetName( newArrayName.c_str() );
1889 arr->SetNumberOfComponents( ainfop->Components );
1890 arr->SetNumberOfTuples( this->GetNumberOfTimeSteps() );
1891 if ( ainfop->Components == 1 )
1892 {
1893 if ( ex_get_var_time( exoid, EX_NODAL,
1894 ainfop->OriginalIndices[0], key.ObjectId,
1895 1, this->GetNumberOfTimeSteps(), arr->GetVoidPointer( 0 ) ) < 0 )
1896 {
1897 vtkErrorMacro( "Could not read nodal result variable " << ainfop->Name.c_str() << "." );
1898 arr->Delete();
1899 arr = nullptr;
1900 }
1901 }
1902 else
1903 {
1904 // Exodus doesn't support reading with a stride, so we have to manually interleave the arrays. Bleh.
1905 std::vector<std::vector<double> > tmpVal;
1906 tmpVal.resize( ainfop->Components );
1907 int c;
1908 for ( c = 0; c < ainfop->Components; ++c )
1909 {
1910 vtkIdType N = this->GetNumberOfTimeSteps();
1911 tmpVal[c].resize( N );
1912 if ( ex_get_var_time( exoid, EX_NODAL,
1913 ainfop->OriginalIndices[c], key.ObjectId,
1914 1, this->GetNumberOfTimeSteps(), &tmpVal[c][0] ) < 0 )
1915 {
1916 vtkErrorMacro( "Could not read temporal nodal result variable " << ainfop->OriginalNames[c].c_str() << "." );
1917 arr->Delete();
1918 arr = nullptr;
1919 return nullptr;
1920 }
1921 }
1922 int t;
1923 std::vector<double> tmpTuple;
1924 tmpTuple.resize( ainfop->Components );
1925 for ( t = 0; t < arr->GetNumberOfTuples(); ++t )
1926 {
1927 for ( c = 0; c < ainfop->Components; ++c )
1928 {
1929 tmpTuple[c] = tmpVal[c][t];
1930 }
1931 arr->SetTuple( t, &tmpTuple[0] );
1932 }
1933 }
1934 }
1935 else if ( key.ObjectType == vtkExodusIIReader::ELEM_BLOCK_TEMPORAL )
1936 {
1937 // read temporal element array
1938 ArrayInfoType* ainfop = &this->ArrayInfo[vtkExodusIIReader::ELEM_BLOCK][key.ArrayId];
1939 arr = vtkDataArray::CreateDataArray( ainfop->StorageType );
1940 vtkStdString newArrayName = ainfop->Name + "OverTime";
1941 arr->SetName( newArrayName.c_str() );
1942 arr->SetNumberOfComponents( ainfop->Components );
1943 arr->SetNumberOfTuples( this->GetNumberOfTimeSteps() );
1944 if ( ainfop->Components == 1 )
1945 {
1946 if ( ex_get_var_time( exoid, EX_ELEM_BLOCK,
1947 ainfop->OriginalIndices[0], key.ObjectId,
1948 1, this->GetNumberOfTimeSteps(), arr->GetVoidPointer( 0 ) ) < 0 )
1949 {
1950 vtkErrorMacro( "Could not read element result variable " << ainfop->Name.c_str() << "." );
1951 arr->Delete();
1952 arr = nullptr;
1953 }
1954 }
1955 else
1956 {
1957 // Exodus doesn't support reading with a stride, so we have to manually interleave the arrays. Bleh.
1958 std::vector<std::vector<double> > tmpVal;
1959 tmpVal.resize( ainfop->Components );
1960 int c;
1961 for ( c = 0; c < ainfop->Components; ++c )
1962 {
1963 vtkIdType N = this->GetNumberOfTimeSteps();
1964 tmpVal[c].resize( N );
1965 if ( ex_get_var_time( exoid, EX_ELEM_BLOCK,
1966 ainfop->OriginalIndices[c], key.ObjectId,
1967 1, this->GetNumberOfTimeSteps(), &tmpVal[c][0] ) < 0 )
1968 {
1969 vtkErrorMacro( "Could not read temporal element result variable " << ainfop->OriginalNames[c].c_str() << "." );
1970 arr->Delete();
1971 arr = nullptr;
1972 return nullptr;
1973 }
1974 }
1975 int t;
1976 std::vector<double> tmpTuple;
1977 tmpTuple.resize( ainfop->Components );
1978 for ( t = 0; t < arr->GetNumberOfTuples(); ++t )
1979 {
1980 for ( c = 0; c < ainfop->Components; ++c )
1981 {
1982 tmpTuple[c] = tmpVal[c][t];
1983 }
1984 arr->SetTuple( t, &tmpTuple[0] );
1985 }
1986 }
1987 }
1988 else if (
1989 key.ObjectType == vtkExodusIIReader::EDGE_BLOCK ||
1990 key.ObjectType == vtkExodusIIReader::FACE_BLOCK ||
1991 key.ObjectType == vtkExodusIIReader::ELEM_BLOCK ||
1992 key.ObjectType == vtkExodusIIReader::NODE_SET ||
1993 key.ObjectType == vtkExodusIIReader::EDGE_SET ||
1994 key.ObjectType == vtkExodusIIReader::FACE_SET ||
1995 key.ObjectType == vtkExodusIIReader::SIDE_SET ||
1996 key.ObjectType == vtkExodusIIReader::ELEM_SET
1997 )
1998 {
1999 int otypidx = this->GetObjectTypeIndexFromObjectType( key.ObjectType );
2000 ArrayInfoType* ainfop = &this->ArrayInfo[key.ObjectType][key.ArrayId];
2001 ObjectInfoType* oinfop = this->GetObjectInfo( otypidx, key.ObjectId );
2002
2003 arr = vtkDataArray::CreateDataArray( ainfop->StorageType );
2004 arr->SetName( ainfop->Name.c_str() );
2005 if ( ainfop->Components == 2 && this->ModelParameters.num_dim == 2 )
2006 {
2007 // Promote 2-component arrays to 3-component arrays when we have 2-D coordinates
2008 arr->SetNumberOfComponents( 3 );
2009 }
2010 else
2011 {
2012 arr->SetNumberOfComponents( ainfop->Components );
2013 }
2014 arr->SetNumberOfTuples( oinfop->Size );
2015 if ( ainfop->Components == 1 )
2016 {
2017 if ( ex_get_var( exoid, key.Time + 1, static_cast<ex_entity_type>( key.ObjectType ),
2018 ainfop->OriginalIndices[0], oinfop->Id, arr->GetNumberOfTuples(),
2019 arr->GetVoidPointer( 0 ) ) < 0)
2020 {
2021 vtkErrorMacro( "Could not read result variable " << ainfop->Name.c_str() <<
2022 " for " << objtype_names[otypidx] << " " << oinfop->Id << "." );
2023 arr->Delete();
2024 arr = nullptr;
2025 }
2026 }
2027 else
2028 {
2029 // Exodus doesn't support reading with a stride, so we have to manually interleave the arrays. Bleh.
2030 std::vector<std::vector<double> > tmpVal;
2031 tmpVal.resize( ainfop->Components );
2032 int c;
2033 for ( c = 0; c < ainfop->Components; ++c )
2034 {
2035 vtkIdType N = arr->GetNumberOfTuples();
2036 tmpVal[c].resize( N+1 ); // + 1 to avoid errors when N == 0.
2037 // BUG #8746.
2038 if ( ex_get_var( exoid, key.Time + 1, static_cast<ex_entity_type>( key.ObjectType ),
2039 ainfop->OriginalIndices[c], oinfop->Id, arr->GetNumberOfTuples(),
2040 &tmpVal[c][0] ) < 0)
2041 {
2042 vtkErrorMacro( "Could not read result variable " << ainfop->OriginalNames[c].c_str() <<
2043 " for " << objtype_names[otypidx] << " " << oinfop->Id << "." );
2044 arr->Delete();
2045 arr = nullptr;
2046 }
2047 }
2048 // Carefully use arr->GetNumberOfComponents() when sizing
2049 // output as we may have promoted 2-D arrays to 3-D.
2050 int t = arr->GetNumberOfComponents();
2051 std::vector<double> tmpTuple;
2052 tmpTuple.resize( t );
2053 tmpTuple[t - 1] = 0.;
2054 for ( t = 0; t < arr->GetNumberOfTuples(); ++t )
2055 {
2056 for ( c = 0; c < ainfop->Components; ++c )
2057 {
2058 tmpTuple[c] = tmpVal[c][t];
2059 }
2060 arr->SetTuple( t, &tmpTuple[0] );
2061 }
2062 }
2063 }
2064 else if (
2065 key.ObjectType == vtkExodusIIReader::NODE_MAP ||
2066 key.ObjectType == vtkExodusIIReader::EDGE_MAP ||
2067 key.ObjectType == vtkExodusIIReader::FACE_MAP ||
2068 key.ObjectType == vtkExodusIIReader::ELEM_MAP
2069 )
2070 {
2071 MapInfoType* minfop = &this->MapInfo[key.ObjectType][key.ArrayId];
2072 vtkIdTypeArray* iarr = vtkIdTypeArray::New();
2073 arr = iarr;
2074 arr->SetName( minfop->Name.c_str() );
2075 arr->SetNumberOfComponents( 1 );
2076 switch ( key.ObjectType )
2077 {
2078 case vtkExodusIIReader::NODE_MAP:
2079 arr->SetNumberOfTuples( this->ModelParameters.num_nodes );
2080 break;
2081 case vtkExodusIIReader::EDGE_MAP:
2082 arr->SetNumberOfTuples( this->ModelParameters.num_edge );
2083 break;
2084 case vtkExodusIIReader::FACE_MAP:
2085 arr->SetNumberOfTuples( this->ModelParameters.num_face );
2086 break;
2087 case vtkExodusIIReader::ELEM_MAP:
2088 arr->SetNumberOfTuples( this->ModelParameters.num_elem );
2089 break;
2090 }
2091 if ( ex_get_num_map( exoid, static_cast<ex_entity_type>( key.ObjectType ), minfop->Id, (vtkIdType*)arr->GetVoidPointer( 0 ) ) < 0 )
2092 {
2093 vtkErrorMacro( "Could not read nodal map variable " << minfop->Name.c_str() << "." );
2094 arr->Delete();
2095 arr = nullptr;
2096 }
2097 }
2098 else if ( key.ObjectType == vtkExodusIIReader::GLOBAL_ELEMENT_ID )
2099 {
2100 // Yes, the next 2 statements are an intentional misuse of key
2101 // fields reserved for the ObjectId and ArrayId (since ObjectType
2102 // is used to signal that we want IDs instead of a field value).
2103 int otypidx = this->GetObjectTypeIndexFromObjectType( key.ObjectId );
2104 int obj = key.ArrayId;
2105 BlockSetInfoType* bsinfop = (BlockSetInfoType*) this->GetObjectInfo( otypidx, obj );
2106
2107 vtkExodusIICacheKey ckey( -1, -1, 0, 0 );
2108 switch ( key.ObjectId )
2109 {
2110 case vtkExodusIIReader::EDGE_BLOCK:
2111 ckey.ObjectType = vtkExodusIIReader::EDGE_ID;
2112 break;
2113 case vtkExodusIIReader::FACE_BLOCK:
2114 ckey.ObjectType = vtkExodusIIReader::FACE_ID;
2115 break;
2116 case vtkExodusIIReader::ELEM_BLOCK:
2117 default:
2118 ckey.ObjectType = vtkExodusIIReader::ELEMENT_ID;
2119 break;
2120 }
2121 vtkIdTypeArray* src = vtkArrayDownCast<vtkIdTypeArray>( this->GetCacheOrRead( ckey ) );
2122 if ( ! src )
2123 {
2124 arr = nullptr;
2125 return nullptr;
2126 }
2127 vtkIdTypeArray* iarr = vtkIdTypeArray::New();
2128 iarr->SetName( vtkExodusIIReader::GetGlobalElementIdArrayName() );
2129 iarr->SetNumberOfComponents( 1 );
2130 iarr->SetNumberOfTuples( bsinfop->Size );
2131 vtkIdType* gloIds = iarr->GetPointer( 0 );
2132 vtkIdType* srcIds = src->GetPointer( bsinfop->FileOffset - 1 );
2133 memcpy( gloIds, srcIds, sizeof(vtkIdType) * bsinfop->Size );
2134 arr = iarr;
2135 }
2136 else if ( key.ObjectType == vtkExodusIIReader::IMPLICIT_ELEMENT_ID )
2137 {
2138 // Yes, the next 2 statements are an intentional misuse of key
2139 // fields reserved for the ObjectId and ArrayId (since ObjectType
2140 // is used to signal that we want IDs instead of a field value).
2141 int otypidx = this->GetObjectTypeIndexFromObjectType( key.ObjectId );
2142 int obj = key.ArrayId;
2143 BlockSetInfoType* bsinfop = (BlockSetInfoType*) this->GetObjectInfo( otypidx, obj );
2144
2145 vtkExodusIICacheKey ckey( -1, -1, 0, 0 );
2146 vtkIdType mapSize;
2147 int nMaps;
2148 switch ( key.ObjectId )
2149 {
2150 case vtkExodusIIReader::EDGE_BLOCK:
2151 ckey.ObjectType = vtkExodusIIReader::EDGE_ID;
2152 mapSize = this->ModelParameters.num_edge;
2153 nMaps = this->ModelParameters.num_edge_maps;
2154 break;
2155 case vtkExodusIIReader::FACE_BLOCK:
2156 ckey.ObjectType = vtkExodusIIReader::FACE_ID;
2157 mapSize = this->ModelParameters.num_face;
2158 nMaps = this->ModelParameters.num_face_maps;
2159 break;
2160 case vtkExodusIIReader::ELEM_BLOCK:
2161 default:
2162 ckey.ObjectType = vtkExodusIIReader::ELEMENT_ID;
2163 mapSize = this->ModelParameters.num_elem;
2164 nMaps = this->ModelParameters.num_elem_maps;
2165 break;
2166 }
2167 vtkIdTypeArray* src = vtkIdTypeArray::New ();
2168 src->SetNumberOfComponents( 1 );
2169 src->SetNumberOfTuples( mapSize );
2170 if (nMaps > 0) // FIXME correctly detect parallel
2171 {
2172 if ( ex_get_id_map( exoid, static_cast<ex_entity_type>( ckey.ObjectType ), (vtkIdType*)src->GetPointer( 0 ) ) < 0 )
2173 {
2174 vtkErrorMacro( "Could not read elem num map for global implicit id" );
2175 src->Delete();
2176 return nullptr;
2177 }
2178 }
2179 else // single file, just make the implicit index explicit
2180 {
2181 for (vtkIdType i = 0; i < src->GetNumberOfTuples (); i ++)
2182 {
2183 src->SetValue (i, i + 1);
2184 }
2185 }
2186 vtkIdTypeArray* iarr = vtkIdTypeArray::New();
2187 iarr->SetName( vtkExodusIIReader::GetImplicitElementIdArrayName() );
2188 iarr->SetNumberOfComponents( 1 );
2189 iarr->SetNumberOfTuples( bsinfop->Size );
2190 vtkIdType* gloIds = iarr->GetPointer( 0 );
2191 vtkIdType* srcIds = src->GetPointer( bsinfop->FileOffset - 1 );
2192 memcpy( gloIds, srcIds, sizeof(vtkIdType) * bsinfop->Size );
2193 arr = iarr;
2194 src->Delete ();
2195 }
2196 else if ( key.ObjectType == vtkExodusIIReader::GLOBAL_NODE_ID )
2197 { // subset the NODE_ID array choosing only entries for nodes in output grid (using PointMap)
2198 // Yes, the next 2 statements are an intentional misuse of key
2199 // fields reserved for the ObjectId and ArrayId (since ObjectType
2200 // is used to signal that we want IDs instead of a field value).
2201 int otypidx = this->GetObjectTypeIndexFromObjectType( key.ObjectId );
2202 int obj = key.ArrayId;
2203 BlockSetInfoType* bsinfop = (BlockSetInfoType*) this->GetObjectInfo( otypidx, obj );
2204 vtkIdTypeArray* src = vtkArrayDownCast<vtkIdTypeArray>(
2205 this->GetCacheOrRead( vtkExodusIICacheKey( -1, vtkExodusIIReader::NODE_ID, 0, 0 ) ) );
2206 if ( this->SqueezePoints && src )
2207 {
2208 vtkIdTypeArray* iarr = vtkIdTypeArray::New();
2209 iarr->SetName( vtkExodusIIReader::GetGlobalNodeIdArrayName() );
2210 iarr->SetNumberOfComponents( 1 );
2211 iarr->SetNumberOfTuples( bsinfop->NextSqueezePoint );
2212 vtkIdType* gloIds = iarr->GetPointer( 0 );
2213 vtkIdType* srcIds = src->GetPointer( 0 );
2214 std::map<vtkIdType,vtkIdType>::iterator it;
2215 for ( it = bsinfop->PointMap.begin(); it != bsinfop->PointMap.end(); ++ it )
2216 {
2217 gloIds[it->second] = srcIds[it->first];
2218 }
2219 arr = iarr;
2220 }
2221 else
2222 {
2223 arr = src;
2224 }
2225 }
2226 else if ( key.ObjectType == vtkExodusIIReader::IMPLICIT_NODE_ID )
2227 { // subset the NODE_ID array choosing only entries for nodes in output grid (using PointMap)
2228 // Yes, the next 2 statements are an intentional misuse of key
2229 // fields reserved for the ObjectId and ArrayId (since ObjectType
2230 // is used to signal that we want IDs instead of a field value).
2231 int otypidx = this->GetObjectTypeIndexFromObjectType( key.ObjectId );
2232 int obj = key.ArrayId;
2233 BlockSetInfoType* bsinfop = (BlockSetInfoType*) this->GetObjectInfo( otypidx, obj );
2234 vtkIdTypeArray* src = vtkIdTypeArray::New ();
2235 src->SetNumberOfComponents( 1 );
2236 src->SetNumberOfTuples( this->ModelParameters.num_nodes );
2237 if (this->ModelParameters.num_node_maps > 0) // FIXME correctly detect parallel
2238 {
2239 if ( ex_get_id_map( exoid, (ex_entity_type)( vtkExodusIIReader::NODE_MAP ), (vtkIdType*)src->GetPointer( 0 ) ) < 0 )
2240 {
2241 vtkErrorMacro( "Could not node node num map for global implicit id" );
2242 src->Delete();
2243 return nullptr;
2244 }
2245 }
2246 else // single file, just make the implicit index explicit
2247 {
2248 for (vtkIdType i = 0; i < src->GetNumberOfTuples (); i ++)
2249 {
2250 src->SetValue (i, i + 1);
2251 }
2252 }
2253 if ( this->SqueezePoints && src )
2254 {
2255 vtkIdTypeArray* iarr = vtkIdTypeArray::New();
2256 iarr->SetName( vtkExodusIIReader::GetImplicitNodeIdArrayName() );
2257 iarr->SetNumberOfComponents( 1 );
2258 iarr->SetNumberOfTuples( bsinfop->NextSqueezePoint );
2259 vtkIdType* gloIds = iarr->GetPointer( 0 );
2260 vtkIdType* srcIds = src->GetPointer( 0 );
2261 std::map<vtkIdType,vtkIdType>::iterator it;
2262 for ( it = bsinfop->PointMap.begin(); it != bsinfop->PointMap.end(); ++ it )
2263 {
2264 gloIds[it->second] = srcIds[it->first];
2265 }
2266 arr = iarr;
2267 }
2268 else
2269 {
2270 arr = src;
2271 }
2272 src->Delete ();
2273 }
2274 else if (
2275 key.ObjectType == vtkExodusIIReader::ELEMENT_ID ||
2276 key.ObjectType == vtkExodusIIReader::EDGE_ID ||
2277 key.ObjectType == vtkExodusIIReader::FACE_ID ||
2278 key.ObjectType == vtkExodusIIReader::NODE_ID
2279 )
2280 {
2281 vtkIdTypeArray* iarr;
2282 int nMaps;
2283 vtkIdType mapSize;
2284 vtkExodusIICacheKey ktmp;
2285 if ( key.ObjectType == vtkExodusIIReader::ELEMENT_ID )
2286 {
2287 nMaps = this->ModelParameters.num_elem_maps;
2288 mapSize = this->ModelParameters.num_elem;
2289 ktmp = vtkExodusIICacheKey( -1, vtkExodusIIReader::ELEM_MAP, 0, 0 );
2290 }
2291 else if ( key.ObjectType == vtkExodusIIReader::FACE_ID )
2292 {
2293 nMaps = this->ModelParameters.num_face_maps;
2294 mapSize = this->ModelParameters.num_face;
2295 ktmp = vtkExodusIICacheKey( -1, vtkExodusIIReader::FACE_MAP, 0, 0 );
2296 }
2297 else if ( key.ObjectType == vtkExodusIIReader::EDGE_ID )
2298 {
2299 nMaps = this->ModelParameters.num_edge_maps;
2300 mapSize = this->ModelParameters.num_edge;
2301 ktmp = vtkExodusIICacheKey( -1, vtkExodusIIReader::EDGE_MAP, 0, 0 );
2302 }
2303 else // ( key.ObjectType == vtkExodusIIReader::NODE_ID )
2304 {
2305 nMaps = this->ModelParameters.num_node_maps;
2306 mapSize = this->ModelParameters.num_nodes;
2307 ktmp = vtkExodusIICacheKey( -1, vtkExodusIIReader::NODE_MAP, 0, 0 );
2308 }
2309 // If there are no new-style maps, get the old-style map (which creates a default if nothing is stored on disk).
2310 if ( nMaps < 1 || ! (iarr = vtkArrayDownCast<vtkIdTypeArray>(this->GetCacheOrRead( ktmp ))) )
2311 {
2312 iarr = vtkIdTypeArray::New();
2313 iarr->SetNumberOfComponents( 1 );
2314 iarr->SetNumberOfTuples( mapSize );
2315 if ( mapSize )
2316 {
2317 if ( ex_get_id_map( exoid, static_cast<ex_entity_type>( ktmp.ObjectType ), (vtkIdType*)iarr->GetPointer( 0 ) ) < 0 )
2318 {
2319 vtkErrorMacro( "Could not read old-style node or element map." );
2320 iarr->Delete();
2321 iarr = nullptr;
2322 }
2323 }
2324 }
2325 else
2326 {
2327 // FastDelete will be called below (because we are assumed to have created the array with New()).
2328 // So we must reference the array one extra time here to account for the extra delete...
2329 iarr->Register( this );
2330 }
2331 arr = iarr;
2332 }
2333 else if ( key.ObjectType == vtkExodusIIReader::GLOBAL_CONN )
2334 {
2335 vtkErrorMacro(
2336 "Global connectivity is created in AssembleOutputConnectivity since it can't be cached\n"
2337 "with a single vtkDataArray. Who told you to call this routine to get it?"
2338 );
2339 }
2340 else if ( key.ObjectType == vtkExodusIIReader::ENTITY_COUNTS )
2341 {
2342 int ctypidx = (key.ArrayId == 0 ? 0 : 1);
2343 int otypidx = conn_obj_idx_cvt[ctypidx];
2344 int otyp = obj_types[ otypidx ];
2345 BlockInfoType* binfop = (BlockInfoType*) this->GetObjectInfo( otypidx, key.ObjectId );
2346 vtkIntArray* iarr = vtkIntArray::New();
2347 iarr->SetNumberOfComponents (1);
2348 iarr->SetNumberOfTuples (binfop->Size);
2349 if ( ex_get_entity_count_per_polyhedra ( exoid, static_cast<ex_entity_type>( otyp ), binfop->Id,
2350 iarr->GetPointer(0)) < 0 )
2351 {
2352 vtkErrorMacro( "Unable to read " << binfop->Id << " (index " << key.ObjectId <<
2353 ") entity count per polyhedra" );
2354 iarr->Delete();
2355 iarr = nullptr;
2356 }
2357 arr = iarr;
2358 }
2359 else if (
2360 key.ObjectType == vtkExodusIIReader::ELEM_BLOCK_ELEM_CONN ||
2361 key.ObjectType == vtkExodusIIReader::FACE_BLOCK_CONN ||
2362 key.ObjectType == vtkExodusIIReader::EDGE_BLOCK_CONN
2363 )
2364 {
2365 int ctypidx = this->GetConnTypeIndexFromConnType( key.ObjectType );
2366 int otypidx = conn_obj_idx_cvt[ctypidx];
2367 int otyp = obj_types[ otypidx ];
2368 BlockInfoType* binfop = (BlockInfoType*) this->GetObjectInfo( otypidx, key.ObjectId );
2369
2370 auto* iarr = vtkIdTypeArray::New();
2371 if (binfop->CellType == VTK_POLYGON)
2372 {
2373 iarr->SetNumberOfValues (binfop->BdsPerEntry[0]);
2374 }
2375 else if (binfop->CellType == VTK_POLYHEDRON)
2376 {
2377 iarr->SetNumberOfValues (binfop->BdsPerEntry[2]);
2378 }
2379 else
2380 {
2381 iarr->SetNumberOfComponents( binfop->BdsPerEntry[0] );
2382 iarr->SetNumberOfTuples( binfop->Size );
2383 }
2384
2385 if ( ex_get_conn( exoid, static_cast<ex_entity_type>( otyp ), binfop->Id, iarr->GetPointer(0), nullptr, nullptr ) < 0 )
2386 {
2387 vtkErrorMacro( "Unable to read " << objtype_names[otypidx] << " " << binfop->Id << " (index " << key.ObjectId <<
2388 ") nodal connectivity." );
2389 iarr->Delete();
2390 iarr = nullptr;
2391 }
2392
2393 vtkIdType c;
2394 auto ptr = iarr->GetPointer( 0 );
2395 if (
2396 binfop->CellType == VTK_QUADRATIC_HEXAHEDRON ||
2397 binfop->CellType == VTK_TRIQUADRATIC_HEXAHEDRON
2398 )
2399 {
2400 // Edge order for VTK is different than Exodus edge order.
2401 for ( c = 0; c < iarr->GetNumberOfTuples(); ++c )
2402 {
2403 int k;
2404 int itmp[4];
2405
2406 for ( k = 0; k < 12; ++k, ++ptr)
2407 *ptr = *ptr - 1;
2408
2409 for ( k = 0; k < 4; ++k, ++ptr)
2410 {
2411 itmp[k] = *ptr;
2412 *ptr = ptr[4] - 1;
2413 }
2414
2415 for ( k = 0; k < 4; ++k, ++ptr )
2416 *ptr = itmp[k] - 1;
2417
2418 if ( binfop->CellType == VTK_TRIQUADRATIC_HEXAHEDRON )
2419 { // Face/body order for VTK is different than Exodus (Patran) order.
2420 for ( k = 0; k < 4; ++k, ++ptr )
2421 {
2422 itmp[k] = *ptr;
2423 *ptr = ptr[3] - 1;
2424 }
2425 *(ptr++) = itmp[1] - 1;
2426 *(ptr++) = itmp[2] - 1;
2427 *(ptr++) = itmp[0] - 1;
2428 }
2429 }
2430 ptr += binfop->BdsPerEntry[0] - binfop->PointsPerCell;
2431 }
2432 else if (binfop->CellType == VTK_QUADRATIC_WEDGE)
2433 {
2434 int k;
2435 int itmp[3];
2436 for ( c = 0; c < iarr->GetNumberOfTuples(); ++c )
2437 {
2438 for (k = 0; k < 9; ++k, ++ptr)
2439 *ptr = *ptr - 1;
2440
2441 for (k = 0; k < 3; ++k, ++ptr)
2442 {
2443 itmp[k] = *ptr;
2444 *ptr = ptr[3] - 1;
2445 }
2446
2447 for (k = 0; k < 3; ++k, ++ptr)
2448 {
2449 *ptr = itmp[k] - 1;
2450 }
2451 }
2452 ptr += binfop->BdsPerEntry[0] - binfop->PointsPerCell;
2453 }
2454 else if (binfop->CellType == VTK_LAGRANGE_WEDGE && binfop->PointsPerCell == 21)
2455 {
2456 // Exodus orders edges like so:
2457 // r-dir @ -z, 1-r-s-dir @ -z, s-dir @ -z,
2458 // t-dir @ +1-r-s, t-dir @ +r, t-dir @ +s,
2459 // r-dir @ +z, 1-r-s-dir @ +z, s-dir @ +z,
2460 // VTK orders edges like so:
2461 // r-dir @ -z, 1-r-s-dir @ -z, s-dir @ -z,
2462 // r-dir @ +z, 1-r-s-dir @ +z, s-dir @ +z,
2463 // t-dir @ +1-r-s, t-dir @ +r, t-dir @ +s,
2464 int k;
2465 int itmp[3];
2466 for ( c = 0; c < iarr->GetNumberOfTuples(); ++c )
2467 {
2468 for (k = 0; k < 9; ++k, ++ptr)
2469 *ptr = *ptr - 1;
2470
2471 for (k = 0; k < 3; ++k, ++ptr)
2472 {
2473 itmp[k] = *ptr;
2474 *ptr = ptr[3] - 1;
2475 }
2476
2477 for (k = 0; k < 3; ++k, ++ptr)
2478 {
2479 *ptr = itmp[k] - 1;
2480 }
2481 // The body-centered node immediately follows the edges in the
2482 // Exodus file and is then followed by wedge face nodes,
2483 // but not in the same order as VTK or the linear Exodus side-set
2484 // ordering:
2485 int ftmp[6];
2486 static int wedgeMapping[6] = {1, 2, 5, 3, 4, 0};
2487 for (k = 0; k < 6; ++k)
2488 {
2489 ftmp[k] = ptr[wedgeMapping[k]];
2490 }
2491 for (k = 0; k < 6; ++k, ++ptr)
2492 {
2493 *ptr = ftmp[k] - 1;
2494 }
2495 }
2496 ptr += binfop->BdsPerEntry[0] - binfop->PointsPerCell;
2497 }
2498 else if (binfop->CellType == VTK_LAGRANGE_TETRAHEDRON && binfop->PointsPerCell == 15)
2499 {
2500 int k;
2501 for ( c = 0; c < iarr->GetNumberOfTuples(); ++c )
2502 {
2503 // Tet corners and edges are ordered as expected
2504 for (k = 0; k < 10; ++k, ++ptr)
2505 {
2506 *ptr = *ptr - 1;
2507 }
2508 // ... but the body-centered node is placed *before* the
2509 // tet face nodes and the faces are not in the canonical
2510 // side-set ordering.
2511 static int tetMapping[5] = { 1, 4, 2, 3, 0 };
2512 int ftmp[5];
2513 for (k = 0; k < 5; ++k)
2514 {
2515 ftmp[k] = ptr[tetMapping[k]];
2516 }
2517 for (k = 0; k < 5; ++k, ++ptr)
2518 {
2519 *ptr = ftmp[k] - 1;
2520 }
2521 }
2522 ptr += binfop->BdsPerEntry[0] - binfop->PointsPerCell;
2523 }
2524 else
2525 {
2526 for ( c = 0; c <= iarr->GetMaxId(); ++c, ++ptr )
2527 {
2528 *ptr = *ptr - 1;
2529 }
2530 }
2531
2532 arr = iarr;
2533 }
2534 else if (
2535 key.ObjectType == vtkExodusIIReader::ELEM_BLOCK_FACE_CONN ||
2536 key.ObjectType == vtkExodusIIReader::ELEM_BLOCK_EDGE_CONN )
2537 {
2538 arr = nullptr;
2539
2540 // bdsEntry will determine whether we call ex_get_conn to read edge or face connectivity:
2541 int bdsEntry = key.ObjectType == vtkExodusIIReader::ELEM_BLOCK_EDGE_CONN ? 1 : 2;
2542
2543 // Fetch the block information from the key
2544 //int ctypidx = this->GetConnTypeIndexFromConnType( key.ObjectType );
2545 int otypidx = 2; // These always refer to the element block
2546 int otyp = obj_types[ otypidx ];
2547 BlockInfoType* binfop = (BlockInfoType*) this->GetObjectInfo( otypidx, key.ObjectId );
2548
2549 // Only create the array if there's anything to put in it.
2550 if (binfop->BdsPerEntry[bdsEntry] > 0)
2551 {
2552 auto* iarr = vtkIdTypeArray::New();
2553 iarr->SetNumberOfValues (binfop->BdsPerEntry[2]);
2554
2555 if (
2556 ex_get_conn(
2557 exoid,
2558 static_cast<ex_entity_type>( otyp ),
2559 binfop->Id,
2560 nullptr,
2561 bdsEntry == 1 ? iarr->GetPointer(0) : nullptr,
2562 bdsEntry == 2 ? iarr->GetPointer(0) : nullptr ) < 0)
2563 {
2564 vtkErrorMacro(
2565 "Unable to read " << objtype_names[otypidx] << " "
2566 << binfop->Id << " (index " << key.ObjectId <<
2567 ") " << (bdsEntry == 1 ? "edge" : "face") << " connectivity." );
2568 iarr->Delete();
2569 iarr = nullptr;
2570 }
2571 else
2572 {
2573 vtkIdType c;
2574 auto ptr = iarr->GetPointer( 0 );
2575 for ( c = 0; c <= iarr->GetMaxId(); ++c, ++ptr )
2576 {
2577 *ptr = *ptr - 1;
2578 }
2579 }
2580 arr = iarr;
2581 }
2582 }
2583 else if (
2584 key.ObjectType == vtkExodusIIReader::NODE_SET_CONN ||
2585 key.ObjectType == vtkExodusIIReader::ELEM_SET_CONN
2586 )
2587 {
2588 int otyp = this->GetSetTypeFromSetConnType( key.ObjectType );
2589 int otypidx = this->GetObjectTypeIndexFromObjectType( otyp );
2590 SetInfoType* sinfop = &this->SetInfo[otyp][key.ObjectId];
2591
2592 auto* iarr = vtkIdTypeArray::New();
2593 iarr->SetNumberOfComponents( 1 );
2594 iarr->SetNumberOfTuples( sinfop->Size );
2595 auto iptr = iarr->GetPointer( 0 );
2596
2597 if ( ex_get_set( exoid, static_cast<ex_entity_type>( otyp ), sinfop->Id, iptr, nullptr ) < 0 )
2598 {
2599 vtkErrorMacro( "Unable to read " << objtype_names[otypidx] << " " << sinfop->Id << " (index " << key.ObjectId <<
2600 ") nodal connectivity." );
2601 iarr->Delete();
2602 iarr = nullptr;
2603 }
2604
2605 vtkIdType id;
2606 for ( id = 0; id < sinfop->Size; ++id, ++iptr )
2607 { // VTK uses 0-based indexing, unlike Exodus:
2608 --(*iptr);
2609 }
2610
2611 arr = iarr;
2612 }
2613 else if ( key.ObjectType == vtkExodusIIReader::EDGE_SET_CONN || key.ObjectType == vtkExodusIIReader::FACE_SET_CONN )
2614 {
2615 int otyp = this->GetSetTypeFromSetConnType( key.ObjectType );
2616 int otypidx = this->GetObjectTypeIndexFromObjectType( otyp );
2617 SetInfoType* sinfop = &this->SetInfo[otyp][key.ObjectId];
2618
2619 auto* iarr = vtkIdTypeArray::New();
2620 iarr->SetNumberOfComponents( 2 );
2621 iarr->SetNumberOfTuples( sinfop->Size );
2622 std::vector<int> tmpOrient; // hold the edge/face orientation information until we can interleave it.
2623 tmpOrient.resize( sinfop->Size );
2624
2625 if ( ex_get_set( exoid, static_cast<ex_entity_type>( otyp ), sinfop->Id, iarr->GetPointer(0), &tmpOrient[0] ) < 0 )
2626 {
2627 vtkErrorMacro( "Unable to read " << objtype_names[otypidx] << " " << sinfop->Id << " (index " << key.ObjectId <<
2628 ") nodal connectivity." );
2629 iarr->Delete();
2630 iarr = nullptr;
2631 return nullptr;
2632 }
2633
2634 auto iap = iarr->GetPointer( 0 );
2635 vtkIdType c;
2636 for ( c = sinfop->Size - 1; c >= 0; --c )
2637 {
2638 iap[2*c] = iap[c] - 1; // VTK uses 0-based indexing
2639 iap[2*c + 1] = tmpOrient[c];
2640 }
2641
2642 arr = iarr;
2643 }
2644 else if ( key.ObjectType == vtkExodusIIReader::SIDE_SET_CONN )
2645 {
2646 if(key.ArrayId <= 0)
2647 {
2648 // Stick all of side_set_node_list and side_set_node_count and side_set_nodes_per_side in one array
2649 // let InsertSetSides() figure it all out. Except for 0-based indexing
2650 SetInfoType* sinfop = &this->SetInfo[vtkExodusIIReader::SIDE_SET][key.ObjectId];
2651 vtkIdType ssnllen; // side set node list length
2652 if ( ex_get_side_set_node_list_len( exoid, sinfop->Id, &ssnllen ) < 0 )
2653 {
2654 vtkErrorMacro( "Unable to fetch side set \"" << sinfop->Name.c_str() << "\" (" << sinfop->Id << ") node list length" );
2655 arr = nullptr;
2656 return nullptr;
2657 }
2658 auto* iarr = vtkIdTypeArray::New();
2659 vtkIdType ilen = ssnllen + sinfop->Size;
2660 iarr->SetNumberOfComponents( 1 );
2661 iarr->SetNumberOfTuples( ilen );
2662 auto* dat = iarr->GetPointer( 0 );
2663 if ( ex_get_side_set_node_list( exoid, sinfop->Id, dat, dat + sinfop->Size ) < 0 )
2664 {
2665 vtkErrorMacro( "Unable to fetch side set \"" << sinfop->Name.c_str() << "\" (" << sinfop->Id << ") node list" );
2666 iarr->Delete();
2667 arr = nullptr;
2668 return nullptr;
2669 }
2670 while ( ilen > sinfop->Size )
2671 { // move to 0-based indexing on nodes, don't touch nodes/side counts at head of array
2672 --dat[--ilen];
2673 }
2674 arr = iarr;
2675 } // if(key.ArrayId <= 0)
2676 else
2677 {
2678 // return information about where the side set cells come from on the elements
2679 // the first tuple value is the element id and the second is the canonical side
2680 // sinfop->Size is the number of sides in this side set
2681 SetInfoType* sinfop = &this->SetInfo[vtkExodusIIReader::SIDE_SET][key.ObjectId];
2682 std::vector<vtkIdType> side_set_elem_list(sinfop->Size);
2683 std::vector<vtkIdType> side_set_side_list(sinfop->Size);
2684 if ( ex_get_side_set( exoid, sinfop->Id, &side_set_elem_list[0], &side_set_side_list[0]) < 0 )
2685 {
2686 vtkErrorMacro( "Unable to fetch side set \"" << sinfop->Name.c_str() << "\" (" << sinfop->Id << ") node list" );
2687 arr = nullptr;
2688 return nullptr;
2689 }
2690 vtkIdTypeArray* iarr = vtkIdTypeArray::New();
2691 iarr->SetNumberOfComponents( 2 );
2692 iarr->SetNumberOfTuples( sinfop->Size );
2693 for(int i=0;i<sinfop->Size;i++)
2694 { // we'll have to fix up the side indexing later
2695 // because Exodus and VTK have different canonical orderings for wedges and hexes.
2696 vtkIdType info[2] = {side_set_elem_list[i], side_set_side_list[i]};
2697 iarr->SetTypedTuple(i, info);
2698 }
2699 arr = iarr;
2700 }
2701 }
2702 else if ( key.ObjectType == vtkExodusIIReader::NODAL_COORDS )
2703 {
2704 // read node coords
2705 vtkDataArray* displ = nullptr;
2706 if ( this->ApplyDisplacements && key.Time >= 0 )
2707 {
2708 displ = this->FindDisplacementVectors( key.Time );
2709 }
2710
2711 std::vector<double> coordTmp;
2712 vtkDoubleArray* darr = vtkDoubleArray::New();
2713 arr = darr;
2714 arr->SetNumberOfComponents( 3 );
2715 arr->SetNumberOfTuples( this->ModelParameters.num_nodes );
2716 int dim = this->ModelParameters.num_dim;
2717 int c;
2718 vtkIdType t;
2719 double* xc = nullptr;
2720 double* yc = nullptr;
2721 double* zc = nullptr;
2722 coordTmp.resize( this->ModelParameters.num_nodes );
2723 for ( c = 0; c < dim; ++c )
2724 {
2725 switch ( c )
2726 {
2727 case 0:
2728 xc = &coordTmp[0];
2729 break;
2730 case 1:
2731 yc = xc;
2732 xc = nullptr;
2733 break;
2734 case 2:
2735 zc = yc;
2736 yc = nullptr;
2737 break;
2738 default:
2739 vtkErrorMacro( "Bad coordinate index " << c << " when reading point coordinates." );
2740 xc = yc = zc = nullptr;
2741 }
2742 if ( ex_get_coord( exoid, xc, yc, zc ) < 0 )
2743 {
2744 vtkErrorMacro( "Unable to read node coordinates for index " << c << "." );
2745 arr->Delete();
2746 arr = nullptr;
2747 break;
2748 }
2749 double* cptr = darr->GetPointer( c );
2750
2751 //
2752 // num_nodes can get big. Lets unroll the loop
2753 //
2754 for ( t = 0; t+8 < this->ModelParameters.num_nodes; t+=8 )
2755 {
2756 *(cptr+3*0) = coordTmp[t+0];
2757 *(cptr+3*1) = coordTmp[t+1];
2758 *(cptr+3*2) = coordTmp[t+2];
2759 *(cptr+3*3) = coordTmp[t+3];
2760 *(cptr+3*4) = coordTmp[t+4];
2761 *(cptr+3*5) = coordTmp[t+5];
2762 *(cptr+3*6) = coordTmp[t+6];
2763 *(cptr+3*7) = coordTmp[t+7];
2764 cptr += 3*8;
2765 }
2766
2767 for ( ; t < this->ModelParameters.num_nodes; ++t )
2768 {
2769 *cptr = coordTmp[t];
2770 cptr += 3;
2771 }
2772 }
2773 if ( dim < 3 )
2774 {
2775 double* cptr = darr->GetPointer( 2 );
2776 for ( t = 0; t < this->ModelParameters.num_nodes; ++t, cptr += 3 )
2777 {
2778 *cptr = 0.;
2779 }
2780 }
2781 //
2782 // Unrolling some of the inner loops for the most common case - dim 3.
2783 // Also moving the maxTuples from inside of the for(;;) loops
2784 // Also moving cos() calculations out of the bottom of loops.
2785 //
2786 if ( displ )
2787 {
2788 double* coords = darr->GetPointer( 0 );
2789 if ( this->HasModeShapes && this->AnimateModeShapes )
2790 {
2791 double tempDouble = this->DisplacementMagnitude * cos(2.0 * vtkMath::Pi() * this->ModeShapeTime);
2792 if ( dim == 3)
2793 {
2794 vtkIdType maxTuples = arr->GetNumberOfTuples();
2795 for ( vtkIdType idx = 0; idx < maxTuples; ++idx )
2796 {
2797 double* dispVal = displ->GetTuple( idx );
2798 coords[0] += dispVal[0] * tempDouble;
2799 coords[1] += dispVal[1] * tempDouble;
2800 coords[2] += dispVal[2] * tempDouble;
2801 coords += 3;
2802 }
2803 }
2804 else
2805 {
2806 for ( vtkIdType idx = 0; idx < displ->GetNumberOfTuples(); ++idx )
2807 {
2808 double* dispVal = displ->GetTuple( idx );
2809 for ( c = 0; c < dim; ++c )
2810 coords[c] += dispVal[c] * tempDouble;
2811
2812 coords += 3;
2813 }
2814 }
2815 }
2816 else
2817 {
2818 if ( dim == 3)
2819 {
2820 vtkIdType maxTuples = arr->GetNumberOfTuples();
2821 for ( vtkIdType idx = 0; idx < maxTuples; ++idx )
2822 {
2823 double* dispVal = displ->GetTuple( idx );
2824 coords[0] += dispVal[0] * this->DisplacementMagnitude;
2825 coords[1] += dispVal[1] * this->DisplacementMagnitude;
2826 coords[2] += dispVal[2] * this->DisplacementMagnitude;
2827
2828 coords += 3;
2829 }
2830 }
2831 else
2832 {
2833 for ( vtkIdType idx = 0; idx < displ->GetNumberOfTuples(); ++idx )
2834 {
2835 double* dispVal = displ->GetTuple( idx );
2836 for ( c = 0; c < dim; ++c )
2837 coords[c] += dispVal[c] * this->DisplacementMagnitude;
2838
2839 coords += 3;
2840 }
2841 }
2842 }
2843 }
2844 }
2845 else if ( key.ObjectType == vtkExodusIIReader::OBJECT_ID )
2846 {
2847 BlockSetInfoType* bsinfop;
2848 // Yes, the next 2 statements are an intentional misuse of key
2849 // fields reserved for the ObjectId and ArrayId (since ObjectType
2850 // is used to signal that we want IDs instead of a field value).
2851 int otypidx = this->GetObjectTypeIndexFromObjectType( key.ObjectId );
2852 int obj = key.ArrayId;
2853 bsinfop = (BlockSetInfoType*) this->GetObjectInfo( otypidx, obj );
2854
2855 arr = vtkIntArray::New();
2856 arr->SetName( this->GetObjectIdArrayName() );
2857 arr->SetNumberOfComponents( 1 );
2858 arr->SetNumberOfTuples( bsinfop->Size );
2859 arr->FillComponent( 0, bsinfop->Id );
2860
2861 }
2862 else if (
2863 key.ObjectType == vtkExodusIIReader::ELEM_BLOCK_ATTRIB ||
2864 key.ObjectType == vtkExodusIIReader::FACE_BLOCK_ATTRIB ||
2865 key.ObjectType == vtkExodusIIReader::EDGE_BLOCK_ATTRIB
2866 )
2867 {
2868 int blkType =
2869 (key.ObjectType == vtkExodusIIReader::ELEM_BLOCK_ATTRIB ? vtkExodusIIReader::ELEM_BLOCK :
2870 (key.ObjectType == vtkExodusIIReader::FACE_BLOCK_ATTRIB ? vtkExodusIIReader::FACE_BLOCK :
2871 vtkExodusIIReader::EDGE_BLOCK));
2872 BlockInfoType* binfop = &this->BlockInfo[blkType][key.ObjectId];
2873 vtkDoubleArray* darr = vtkDoubleArray::New();
2874 arr = darr;
2875 darr->SetName( binfop->AttributeNames[key.ArrayId].c_str() );
2876 darr->SetNumberOfComponents( 1 );
2877 darr->SetNumberOfTuples( binfop->Size );
2878 if ( ex_get_one_attr(
2879 exoid, static_cast<ex_entity_type>(blkType), binfop->Id, key.ArrayId + 1, darr->GetVoidPointer( 0 ) ) < 0 )
2880 { // NB: The error message references the file-order object id, not the numerically sorted index presented to users.
2881 vtkErrorMacro( "Unable to read attribute " << key.ArrayId
2882 << " for object " << key.ObjectId << " of type " << key.ObjectType << " block type " << blkType << "." );
2883 arr->Delete();
2884 arr = nullptr;
2885 }
2886 }
2887 else if ( key.ObjectType == vtkExodusIIReader::INFO_RECORDS )
2888 {
2889 // Get Exodus II INFO records. Each INFO record is a single character string.
2890 vtkIdType num_info = 0;
2891 float fdum;
2892 char* cdum = nullptr;
2893 int i;
2894
2895 vtkCharArray* carr = vtkCharArray::New();
2896 carr->SetName("Info_Records");
2897 carr->SetNumberOfComponents( MAX_LINE_LENGTH+1 );
2898
2899 if( ex_inquire( exoid, EX_INQ_INFO, &num_info, &fdum, cdum ) < 0 )
2900 {
2901 vtkErrorMacro( "Unable to get number of INFO records from ex_inquire" );
2902 carr->Delete();
2903 arr = nullptr;
2904 }
2905 else
2906 {
2907 if ( num_info > 0 )
2908 {
2909 carr->SetNumberOfTuples(num_info);
2910 char** info = (char**) calloc( num_info, sizeof(char*) );
2911
2912 for ( i = 0; i < num_info; ++i )
2913 info[i] = (char *) calloc ( ( MAX_LINE_LENGTH + 1 ), sizeof(char) );
2914
2915 if ( ex_get_info( exoid, info ) < 0 )
2916 {
2917 vtkErrorMacro( "Unable to read INFO records from ex_get_info");
2918 carr->Delete();
2919 arr = nullptr;
2920 }
2921 else
2922 {
2923 for ( i = 0; i < num_info; ++i )
2924 {
2925 carr->InsertTypedTuple( i, info[i] );
2926 }
2927 arr = carr;
2928 }
2929
2930 for ( i = 0; i < num_info; ++i )
2931 {
2932 free(info[i]);
2933 }
2934 free(info);
2935 }
2936 else
2937 {
2938 carr->Delete();
2939 arr = nullptr;
2940 }
2941 }
2942 }
2943 else if ( key.ObjectType == vtkExodusIIReader::QA_RECORDS )
2944 {
2945 // Get Exodus II QA records. Each QA record is made up of 4 character strings.
2946 vtkIdType num_qa_rec = 0;
2947 float fdum;
2948 char* cdum = nullptr;
2949 int i,j;
2950
2951 vtkCharArray* carr = vtkCharArray::New();
2952 carr->SetName( "QA_Records" );
2953 carr->SetNumberOfComponents( maxNameLength + 1 );
2954
2955 if ( ex_inquire( exoid, EX_INQ_QA, &num_qa_rec, &fdum, cdum ) < 0 )
2956 {
2957 vtkErrorMacro( "Unable to get number of QA records from ex_inquire" );
2958 carr->Delete();
2959 arr = nullptr;
2960 }
2961 else
2962 {
2963 if( num_qa_rec > 0 )
2964 {
2965 carr->SetNumberOfTuples(num_qa_rec*4);
2966 char* (*qa_record)[4] = (char* (*)[4]) calloc(num_qa_rec, sizeof(*qa_record));
2967
2968 for ( i = 0; i < num_qa_rec; ++i )
2969 {
2970 for ( j = 0; j < 4 ; ++j )
2971 { // QA record string length is different than MaxNameLength
2972 qa_record[i][j] = (char *) calloc( ( MAX_STR_LENGTH + 1 ), sizeof(char) );
2973 }
2974 }
2975
2976 if ( ex_get_qa( exoid, qa_record ) < 0 )
2977 {
2978 vtkErrorMacro( "Unable to read QA records from ex_get_qa");
2979 carr->Delete();
2980 arr = nullptr;
2981 }
2982 else
2983 {
2984 for ( i = 0; i < num_qa_rec; ++i )
2985 {
2986 for ( j = 0; j < 4 ; ++j )
2987 {
2988 carr->InsertTypedTuple( ( i * 4 ) + j, qa_record[i][j] );
2989 }
2990 }
2991 arr = carr;
2992 }
2993
2994 for ( i = 0; i < num_qa_rec; ++i )
2995 {
2996 for ( j = 0; j < 4 ; ++j )
2997 {
2998 free( qa_record[i][j] );
2999 }
3000 }
3001 free( qa_record );
3002 }
3003 else
3004 {
3005 carr->Delete();
3006 arr = nullptr;
3007 }
3008 }
3009 }
3010 else
3011 {
3012 vtkWarningMacro( "You requested an array for objects of type " << key.ObjectType <<
3013 " which I know nothing about" );
3014 arr = nullptr;
3015 }
3016
3017 // Even if the array is larger than the allowable cache size, it will keep the most recent insertion.
3018 // So, we delete our reference knowing that the Cache will keep the object "alive" until whatever
3019 // called GetCacheOrRead() references the array. But, once you get an array from GetCacheOrRead(),
3020 // you better start running!
3021 if ( arr )
3022 {
3023 this->Cache->Insert( key, arr );
3024 arr->FastDelete();
3025 }
3026 return arr;
3027 }
3028
3029 //-----------------------------------------------------------------------------
GetConnTypeIndexFromConnType(int ctyp)3030 int vtkExodusIIReaderPrivate::GetConnTypeIndexFromConnType( int ctyp )
3031 {
3032 int i;
3033 for ( i = 0; i < num_conn_types; ++i )
3034 {
3035 if ( conn_types[i] == ctyp )
3036 {
3037 return i;
3038 }
3039 }
3040 return -1;
3041 }
3042
3043 //-----------------------------------------------------------------------------
GetObjectTypeIndexFromObjectType(int otyp)3044 int vtkExodusIIReaderPrivate::GetObjectTypeIndexFromObjectType( int otyp )
3045 {
3046 int i;
3047 for ( i = 0; i < num_obj_types; ++i )
3048 {
3049 if ( obj_types[i] == otyp )
3050 {
3051 return i;
3052 }
3053 }
3054 return -1;
3055 }
3056
3057 //-----------------------------------------------------------------------------
GetNumberOfObjectsAtTypeIndex(int typeIndex)3058 int vtkExodusIIReaderPrivate::GetNumberOfObjectsAtTypeIndex( int typeIndex )
3059 {
3060 if ( typeIndex < 0 )
3061 {
3062 return 0;
3063 }
3064 else if ( typeIndex < 3 )
3065 {
3066 return (int) this->BlockInfo[obj_types[typeIndex]].size();
3067 }
3068 else if ( typeIndex < 8 )
3069 {
3070 return (int) this->SetInfo[obj_types[typeIndex]].size();
3071 }
3072 else if ( typeIndex < 12 )
3073 {
3074 return (int) this->MapInfo[obj_types[typeIndex]].size();
3075 }
3076 return 0;
3077 }
3078
3079 //-----------------------------------------------------------------------------
GetObjectInfo(int typeIndex,int objectIndex)3080 vtkExodusIIReaderPrivate::ObjectInfoType* vtkExodusIIReaderPrivate::GetObjectInfo( int typeIndex, int objectIndex )
3081 {
3082 if ( typeIndex < 0 )
3083 {
3084 return nullptr;
3085 }
3086 else if ( typeIndex < 3 )
3087 {
3088 return &this->BlockInfo[obj_types[typeIndex]][objectIndex];
3089 }
3090 else if ( typeIndex < 8 )
3091 {
3092 return &this->SetInfo[obj_types[typeIndex]][objectIndex];
3093 }
3094 else if ( typeIndex < 12 )
3095 {
3096 return &this->MapInfo[obj_types[typeIndex]][objectIndex];
3097 }
3098 return nullptr;
3099 }
3100
3101 //-----------------------------------------------------------------------------
GetSortedObjectInfo(int otyp,int k)3102 vtkExodusIIReaderPrivate::ObjectInfoType* vtkExodusIIReaderPrivate::GetSortedObjectInfo( int otyp, int k )
3103 {
3104 int i = this->GetObjectTypeIndexFromObjectType( otyp );
3105 if ( i < 0 )
3106 {
3107 vtkDebugMacro( "Could not find collection of objects with type " << otyp << "." );
3108 return nullptr;
3109 }
3110 int N = this->GetNumberOfObjectsAtTypeIndex( i );
3111 if ( k < 0 || k >= N )
3112 {
3113 const char* otname = i >= 0 ? objtype_names[i] : "object";
3114 static_cast<void>(otname); // not referenced warning
3115 vtkDebugMacro( "You requested " << otname << " " << k << " in a collection of only " << N << " objects." );
3116 return nullptr;
3117 }
3118 return this->GetObjectInfo( i, this->SortedObjectIndices[otyp][k] );
3119 }
3120
3121 //-----------------------------------------------------------------------------
GetUnsortedObjectInfo(int otyp,int k)3122 vtkExodusIIReaderPrivate::ObjectInfoType* vtkExodusIIReaderPrivate::GetUnsortedObjectInfo( int otyp, int k )
3123 {
3124 int i = this->GetObjectTypeIndexFromObjectType( otyp );
3125 if ( i < 0 )
3126 {
3127 vtkDebugMacro( "Could not find collection of objects with type " << otyp << "." );
3128 return nullptr;
3129 }
3130 int N = this->GetNumberOfObjectsAtTypeIndex( i );
3131 if ( k < 0 || k >= N )
3132 {
3133 const char* otname = i >= 0 ? objtype_names[i] : "object";
3134 static_cast<void>(otname); // not referenced warning
3135 vtkDebugMacro( "You requested " << otname << " " << k << " in a collection of only " << N << " objects." );
3136 return nullptr;
3137 }
3138 return this->GetObjectInfo( i, k );
3139 }
3140
3141
3142 //-----------------------------------------------------------------------------
GetBlockIndexFromFileGlobalId(int otyp,int refId)3143 int vtkExodusIIReaderPrivate::GetBlockIndexFromFileGlobalId( int otyp, int refId )
3144 {
3145 std::vector<BlockInfoType>::iterator bi;
3146 int i = 0;
3147 for ( bi = this->BlockInfo[otyp].begin(); bi != this->BlockInfo[otyp].end(); ++bi, ++i )
3148 {
3149 if ( refId >= bi->FileOffset && refId <= bi->FileOffset + bi->Size )
3150 return i;
3151 }
3152 return -1;
3153 }
3154
3155 //-----------------------------------------------------------------------------
GetBlockFromFileGlobalId(int otyp,int refId)3156 vtkExodusIIReaderPrivate::BlockInfoType* vtkExodusIIReaderPrivate::GetBlockFromFileGlobalId( int otyp, int refId )
3157 {
3158 int blk = this->GetBlockIndexFromFileGlobalId( otyp, refId );
3159 if ( blk >= 0 )
3160 {
3161 return &this->BlockInfo[otyp][blk];
3162 }
3163 return nullptr;
3164 }
3165
3166 //-----------------------------------------------------------------------------
GetSqueezePointId(BlockSetInfoType * bsinfop,int i)3167 vtkIdType vtkExodusIIReaderPrivate::GetSqueezePointId( BlockSetInfoType* bsinfop, int i )
3168 {
3169 if (i<0)
3170 {
3171 vtkGenericWarningMacro("Invalid point id: " << i
3172 << ". Data file may be incorrect.");
3173 i = 0;
3174 }
3175
3176 vtkIdType x;
3177 std::map<vtkIdType,vtkIdType>::iterator it = bsinfop->PointMap.find( i );
3178 if ( it == bsinfop->PointMap.end() )
3179 { // Nothing found; add a new entry to the map.
3180 x = bsinfop->NextSqueezePoint ++ ;
3181 bsinfop->PointMap[i] = x;
3182 bsinfop->ReversePointMap[x] = i;
3183 }
3184 else
3185 {
3186 x = it->second;
3187 }
3188 return x;
3189 }
3190
3191 //-----------------------------------------------------------------------------
DetermineVtkCellType(BlockInfoType & binfo)3192 void vtkExodusIIReaderPrivate::DetermineVtkCellType( BlockInfoType& binfo )
3193 {
3194 vtkStdString elemType( vtksys::SystemTools::UpperCase( binfo.TypeName ) );
3195
3196 // Check for quadratic elements
3197 if ((elemType.substr(0,3) == "TRI") && (binfo.BdsPerEntry[0] == 6))
3198 { binfo.CellType=VTK_QUADRATIC_TRIANGLE; binfo.PointsPerCell = 6; }
3199 else if ((elemType.substr(0,3) == "SHE") && (binfo.BdsPerEntry[0] == 8))
3200 { binfo.CellType=VTK_QUADRATIC_QUAD; binfo.PointsPerCell = 8; }
3201 else if ((elemType.substr(0,3) == "SHE") && (binfo.BdsPerEntry[0] == 9))
3202 { binfo.CellType=VTK_QUADRATIC_QUAD; binfo.PointsPerCell = 8; }
3203 else if ((elemType.substr(0,3) == "TET") && (binfo.BdsPerEntry[0] == 10))
3204 { binfo.CellType=VTK_QUADRATIC_TETRA; binfo.PointsPerCell = 10; }
3205 else if ((elemType.substr(0,3) == "TET") && (binfo.BdsPerEntry[0] == 11))
3206 { binfo.CellType=VTK_QUADRATIC_TETRA; binfo.PointsPerCell = 10; }
3207 else if ((elemType.substr(0,3) == "TET") && (binfo.BdsPerEntry[0] == 15))
3208 { binfo.CellType=VTK_LAGRANGE_TETRAHEDRON; binfo.PointsPerCell = 15; }
3209 else if ((elemType.substr(0,3) == "WED") && (binfo.BdsPerEntry[0] == 15))
3210 { binfo.CellType=VTK_QUADRATIC_WEDGE; binfo.PointsPerCell = 15; }
3211 else if ((elemType.substr(0,3) == "WED") && (binfo.BdsPerEntry[0] == 21))
3212 { binfo.CellType=VTK_LAGRANGE_WEDGE; binfo.PointsPerCell = 21; }
3213 else if ((elemType.substr(0,3) == "HEX") && (binfo.BdsPerEntry[0] == 20))
3214 { binfo.CellType=VTK_QUADRATIC_HEXAHEDRON; binfo.PointsPerCell = 20; }
3215 else if ((elemType.substr(0,3) == "HEX") && (binfo.BdsPerEntry[0] == 21))
3216 { binfo.CellType=VTK_QUADRATIC_HEXAHEDRON; binfo.PointsPerCell = 20; }
3217 else if ((elemType.substr(0,3) == "HEX") && (binfo.BdsPerEntry[0] == 27))
3218 { binfo.CellType=VTK_TRIQUADRATIC_HEXAHEDRON; binfo.PointsPerCell = 27; }
3219 else if ((elemType.substr(0,3) == "QUA") && (binfo.BdsPerEntry[0] == 8))
3220 { binfo.CellType=VTK_QUADRATIC_QUAD; binfo.PointsPerCell = 8; }
3221 else if ((elemType.substr(0,3) == "QUA") && (binfo.BdsPerEntry[0] == 9))
3222 { binfo.CellType=VTK_BIQUADRATIC_QUAD; binfo.PointsPerCell = 9; }
3223 else if ((elemType.substr(0,3) == "TRU") && (binfo.BdsPerEntry[0] == 3))
3224 { binfo.CellType=VTK_QUADRATIC_EDGE; binfo.PointsPerCell = 3; }
3225 else if ((elemType.substr(0,3) == "BEA") && (binfo.BdsPerEntry[0] == 3))
3226 { binfo.CellType=VTK_QUADRATIC_EDGE; binfo.PointsPerCell = 3; }
3227 else if ((elemType.substr(0,3) == "BAR") && (binfo.BdsPerEntry[0] == 3))
3228 { binfo.CellType=VTK_QUADRATIC_EDGE; binfo.PointsPerCell = 3; }
3229 else if ((elemType.substr(0,3) == "EDG") && (binfo.BdsPerEntry[0] == 3))
3230 { binfo.CellType=VTK_QUADRATIC_EDGE; binfo.PointsPerCell = 3; }
3231 else if ((elemType.substr(0,3) == "PYR") && (binfo.BdsPerEntry[0] == 13))
3232 { binfo.CellType=VTK_QUADRATIC_PYRAMID; binfo.PointsPerCell = 13; }
3233
3234 // Check for regular elements
3235 else if (elemType.substr(0,3) == "CIR") { binfo.CellType = VTK_VERTEX; binfo.PointsPerCell = 1; }
3236 else if (elemType.substr(0,3) == "SPH") { binfo.CellType = VTK_VERTEX; binfo.PointsPerCell = 1; }
3237 else if (elemType.substr(0,3) == "BAR") { binfo.CellType = VTK_LINE; binfo.PointsPerCell = 2; }
3238 else if (elemType.substr(0,3) == "TRU") { binfo.CellType = VTK_LINE; binfo.PointsPerCell = 2; }
3239 else if (elemType.substr(0,3) == "BEA") { binfo.CellType = VTK_LINE; binfo.PointsPerCell = 2; }
3240 else if (elemType.substr(0,3) == "EDG") { binfo.CellType = VTK_LINE; binfo.PointsPerCell = 2; }
3241 else if (elemType.substr(0,3) == "TRI") { binfo.CellType = VTK_TRIANGLE; binfo.PointsPerCell = 3; }
3242 else if (elemType.substr(0,3) == "QUA") { binfo.CellType = VTK_QUAD; binfo.PointsPerCell = 4; }
3243 else if (elemType.substr(0,3) == "TET") { binfo.CellType = VTK_TETRA; binfo.PointsPerCell = 4; }
3244 else if (elemType.substr(0,3) == "PYR") { binfo.CellType = VTK_PYRAMID; binfo.PointsPerCell = 5; }
3245 else if (elemType.substr(0,3) == "WED") { binfo.CellType = VTK_WEDGE; binfo.PointsPerCell = 6; }
3246 else if (elemType.substr(0,3) == "HEX") { binfo.CellType = VTK_HEXAHEDRON; binfo.PointsPerCell = 8; }
3247 else if (elemType.substr(0,3) == "NSI") { binfo.CellType = VTK_POLYGON; binfo.PointsPerCell = 0; }
3248 else if (elemType.substr(0,3) == "NFA") { binfo.CellType = VTK_POLYHEDRON; binfo.PointsPerCell = 0; }
3249 else if ((elemType.substr(0,3) == "SHE") && (binfo.BdsPerEntry[0] == 3))
3250 { binfo.CellType = VTK_TRIANGLE; binfo.PointsPerCell = 3; }
3251 else if ((elemType.substr(0,3) == "SHE") && (binfo.BdsPerEntry[0] == 4))
3252 { binfo.CellType = VTK_QUAD; binfo.PointsPerCell = 4; }
3253 else if ((elemType.substr(0,8) == "STRAIGHT") && (binfo.BdsPerEntry[0] == 2 ))
3254 { binfo.CellType = VTK_LINE; binfo.PointsPerCell = 2; }
3255 else if (elemType.substr(0,3) == "SUP")
3256 {
3257 binfo.CellType=VTK_POLY_VERTEX;
3258 binfo.PointsPerCell = binfo.BdsPerEntry[0];
3259 }
3260 else if ((elemType.substr(0,4) == "NULL") && (binfo.Size == 0))
3261 {
3262 (void)binfo; // silently ignore empty element blocks
3263 }
3264 else
3265 {
3266 vtkErrorMacro("Unsupported element type: " << elemType.c_str());
3267 }
3268
3269 //cell types not currently handled
3270 //quadratic wedge - 15,16 nodes
3271 //quadratic pyramid - 13 nodes
3272 }
3273
3274 //-----------------------------------------------------------------------------
FindArrayInfoByName(int otyp,const char * name)3275 vtkExodusIIReaderPrivate::ArrayInfoType* vtkExodusIIReaderPrivate::FindArrayInfoByName( int otyp, const char* name )
3276 {
3277 std::vector<ArrayInfoType>::iterator ai;
3278 for ( ai = this->ArrayInfo[otyp].begin(); ai != this->ArrayInfo[otyp].end(); ++ai )
3279 {
3280 if ( ai->Name == name )
3281 return &(*ai);
3282 }
3283 return nullptr;
3284 }
3285
3286 //-----------------------------------------------------------------------------
IsObjectTypeBlock(int otyp)3287 int vtkExodusIIReaderPrivate::IsObjectTypeBlock( int otyp )
3288 {
3289 return (otyp == vtkExodusIIReader::ELEM_BLOCK || otyp == vtkExodusIIReader::EDGE_BLOCK || otyp == vtkExodusIIReader::FACE_BLOCK);
3290 }
3291
3292 //-----------------------------------------------------------------------------
IsObjectTypeSet(int otyp)3293 int vtkExodusIIReaderPrivate::IsObjectTypeSet( int otyp )
3294 {
3295 return (otyp == vtkExodusIIReader::ELEM_SET || otyp == vtkExodusIIReader::EDGE_SET || otyp == vtkExodusIIReader::FACE_SET || otyp == vtkExodusIIReader::NODE_SET || otyp == vtkExodusIIReader::SIDE_SET);
3296 }
3297
3298 //-----------------------------------------------------------------------------
IsObjectTypeMap(int otyp)3299 int vtkExodusIIReaderPrivate::IsObjectTypeMap( int otyp )
3300 {
3301 return (otyp == vtkExodusIIReader::ELEM_MAP || otyp == vtkExodusIIReader::EDGE_MAP || otyp == vtkExodusIIReader::FACE_MAP || otyp == vtkExodusIIReader::NODE_MAP);
3302 }
3303
3304 //-----------------------------------------------------------------------------
GetObjectTypeFromMapType(int mtyp)3305 int vtkExodusIIReaderPrivate::GetObjectTypeFromMapType( int mtyp )
3306 {
3307 switch (mtyp)
3308 {
3309 case vtkExodusIIReader::ELEM_MAP:
3310 return vtkExodusIIReader::ELEM_BLOCK;
3311 case vtkExodusIIReader::FACE_MAP:
3312 return vtkExodusIIReader::FACE_BLOCK;
3313 case vtkExodusIIReader::EDGE_MAP:
3314 return vtkExodusIIReader::EDGE_BLOCK;
3315 case vtkExodusIIReader::NODE_MAP:
3316 return vtkExodusIIReader::NODAL;
3317 }
3318 return -1;
3319 }
3320
3321 //-----------------------------------------------------------------------------
GetMapTypeFromObjectType(int otyp)3322 int vtkExodusIIReaderPrivate::GetMapTypeFromObjectType( int otyp )
3323 {
3324 switch (otyp)
3325 {
3326 case vtkExodusIIReader::ELEM_BLOCK:
3327 return vtkExodusIIReader::ELEM_MAP;
3328 case vtkExodusIIReader::FACE_BLOCK:
3329 return vtkExodusIIReader::FACE_MAP;
3330 case vtkExodusIIReader::EDGE_BLOCK:
3331 return vtkExodusIIReader::EDGE_MAP;
3332 case vtkExodusIIReader::NODAL:
3333 return vtkExodusIIReader::NODE_MAP;
3334 }
3335 return -1;
3336 }
3337
3338 //-----------------------------------------------------------------------------
GetTemporalTypeFromObjectType(int otyp)3339 int vtkExodusIIReaderPrivate::GetTemporalTypeFromObjectType( int otyp )
3340 {
3341 switch (otyp)
3342 {
3343 case vtkExodusIIReader::ELEM_BLOCK:
3344 return vtkExodusIIReader::ELEM_BLOCK_TEMPORAL;
3345 //case vtkExodusIIReader::FACE_BLOCK:
3346 // return vtkExodusIIReader::FACE_MAP;
3347 //case vtkExodusIIReader::EDGE_BLOCK:
3348 // return vtkExodusIIReader::EDGE_MAP;
3349 case vtkExodusIIReader::NODAL:
3350 return vtkExodusIIReader::NODAL_TEMPORAL;
3351 case vtkExodusIIReader::GLOBAL:
3352 return vtkExodusIIReader::GLOBAL_TEMPORAL;
3353 }
3354 return -1;
3355 }
3356
3357 //-----------------------------------------------------------------------------
GetSetTypeFromSetConnType(int sctyp)3358 int vtkExodusIIReaderPrivate::GetSetTypeFromSetConnType( int sctyp )
3359 {
3360 switch ( sctyp )
3361 {
3362 case vtkExodusIIReader::NODE_SET_CONN:
3363 return vtkExodusIIReader::NODE_SET;
3364 case vtkExodusIIReader::EDGE_SET_CONN:
3365 return vtkExodusIIReader::EDGE_SET;
3366 case vtkExodusIIReader::FACE_SET_CONN:
3367 return vtkExodusIIReader::FACE_SET;
3368 case vtkExodusIIReader::SIDE_SET_CONN:
3369 return vtkExodusIIReader::SIDE_SET;
3370 case vtkExodusIIReader::ELEM_SET_CONN:
3371 return vtkExodusIIReader::ELEM_SET;
3372 }
3373 return -1;
3374 }
3375
3376 //-----------------------------------------------------------------------------
GetBlockConnTypeFromBlockType(int btyp)3377 int vtkExodusIIReaderPrivate::GetBlockConnTypeFromBlockType( int btyp )
3378 {
3379 switch ( btyp )
3380 {
3381 case vtkExodusIIReader::EDGE_BLOCK:
3382 return vtkExodusIIReader::EDGE_BLOCK_CONN;
3383 case vtkExodusIIReader::FACE_BLOCK:
3384 return vtkExodusIIReader::FACE_BLOCK_CONN;
3385 case vtkExodusIIReader::ELEM_BLOCK:
3386 return vtkExodusIIReader::ELEM_BLOCK_ELEM_CONN;
3387 }
3388 return -1;
3389 }
3390
3391 //-----------------------------------------------------------------------------
RemoveBeginningAndTrailingSpaces(int len,char ** names,int maxNameLength)3392 void vtkExodusIIReaderPrivate::RemoveBeginningAndTrailingSpaces(
3393 int len, char **names, int maxNameLength )
3394 {
3395 for (int i=0; i<len; i++)
3396 {
3397 char *c = names[i];
3398 int nmlen = (int)strlen(c);
3399
3400 char *cbegin = c;
3401 char *cend = c + nmlen - 1;
3402
3403 // remove spaces or non-printing character from start and end
3404
3405 for (int j=0; j<nmlen; j++)
3406 {
3407 if (!isgraph(*cbegin)) cbegin++;
3408 else break;
3409 }
3410
3411 for (int j=0; j<nmlen; j++)
3412 {
3413 if (!isgraph(*cend)) cend--;
3414 else break;
3415 }
3416
3417 if (cend < cbegin)
3418 {
3419 snprintf(names[i], maxNameLength + 1, "null_%d", i);
3420 continue;
3421 }
3422
3423 int newlen = cend - cbegin + 1;
3424
3425 if (newlen < nmlen)
3426 {
3427 for (int j=0; j<newlen; j++)
3428 {
3429 *c++ = *cbegin++;
3430 }
3431 *c = '\0';
3432 }
3433 }
3434 }
3435
3436 //-----------------------------------------------------------------------------
ClearConnectivityCaches()3437 void vtkExodusIIReaderPrivate::ClearConnectivityCaches()
3438 {
3439 std::map<int,std::vector<BlockInfoType> >::iterator blksit;
3440 for ( blksit = this->BlockInfo.begin(); blksit != this->BlockInfo.end(); ++ blksit )
3441 {
3442 std::vector<BlockInfoType>::iterator blkit;
3443 for ( blkit = blksit->second.begin(); blkit != blksit->second.end(); ++ blkit )
3444 {
3445 if ( blkit->CachedConnectivity )
3446 {
3447 blkit->CachedConnectivity->Delete();
3448 blkit->CachedConnectivity = nullptr;
3449 }
3450 }
3451 }
3452 std::map<int,std::vector<SetInfoType> >::iterator setsit;
3453 for ( setsit = this->SetInfo.begin(); setsit != this->SetInfo.end(); ++ setsit )
3454 {
3455 std::vector<SetInfoType>::iterator setit;
3456 for ( setit = setsit->second.begin(); setit != setsit->second.end(); ++ setit )
3457 {
3458 if ( setit->CachedConnectivity )
3459 {
3460 setit->CachedConnectivity->Delete();
3461 setit->CachedConnectivity = nullptr;
3462 }
3463 }
3464 }
3465 }
3466
3467 //-----------------------------------------------------------------------------
SetParser(vtkExodusIIReaderParser * parser)3468 void vtkExodusIIReaderPrivate::SetParser(vtkExodusIIReaderParser *parser)
3469 {
3470 // Properly sets the parser object but does not call Modified. The parser
3471 // represents the state of the data in files, not the state of this object.
3472 if (this->Parser != parser)
3473 {
3474 vtkExodusIIReaderParser *oldParser = this->Parser;
3475 this->Parser = parser;
3476 if (this->Parser) this->Parser->Register(this);
3477 if (oldParser) oldParser->UnRegister(this);
3478 }
3479 }
3480
3481 //-----------------------------------------------------------------------------
GetNumberOfParts()3482 int vtkExodusIIReaderPrivate::GetNumberOfParts()
3483 {
3484 return static_cast<int>( this->PartInfo.size() );
3485 }
3486
3487 //-----------------------------------------------------------------------------
GetPartName(int idx)3488 const char* vtkExodusIIReaderPrivate::GetPartName(int idx)
3489 {
3490 return this->PartInfo[idx].Name.c_str();
3491 }
3492
3493 //-----------------------------------------------------------------------------
GetPartBlockInfo(int idx)3494 const char* vtkExodusIIReaderPrivate::GetPartBlockInfo(int idx)
3495 {
3496 char buffer[80];
3497 vtkStdString blocks;
3498 std::vector<int> blkIndices = this->PartInfo[idx].BlockIndices;
3499 for (unsigned int i=0;i<blkIndices.size();i++)
3500 {
3501 snprintf(buffer,sizeof(buffer),"%d, ",blkIndices[i]);
3502 blocks += buffer;
3503 }
3504
3505 blocks.erase(blocks.size()-2,blocks.size()-1);
3506
3507 return blocks.c_str();
3508 }
3509
3510 //-----------------------------------------------------------------------------
GetPartStatus(int idx)3511 int vtkExodusIIReaderPrivate::GetPartStatus(int idx)
3512 {
3513 //a part is only active if all its blocks are active
3514 std::vector<int> blkIndices = this->PartInfo[idx].BlockIndices;
3515 for (unsigned int i=0;i<blkIndices.size();i++)
3516 {
3517 if (!this->GetUnsortedObjectStatus(vtkExodusIIReader::ELEM_BLOCK,blkIndices[i]))
3518 {
3519 return 0;
3520 }
3521 }
3522 return 1;
3523 }
3524
3525 //-----------------------------------------------------------------------------
GetPartStatus(const vtkStdString & name)3526 int vtkExodusIIReaderPrivate::GetPartStatus(const vtkStdString& name)
3527 {
3528 for (unsigned int i=0;i<this->PartInfo.size();i++)
3529 {
3530 if (this->PartInfo[i].Name==name)
3531 {
3532 return this->GetPartStatus(i);
3533 }
3534 }
3535 return -1;
3536 }
3537
3538 //-----------------------------------------------------------------------------
SetPartStatus(int idx,int on)3539 void vtkExodusIIReaderPrivate::SetPartStatus(int idx, int on)
3540 {
3541 //update the block status for all the blocks in this part
3542 std::vector<int> blkIndices = this->PartInfo[idx].BlockIndices;
3543 for (unsigned int i=0;i<blkIndices.size();i++)
3544 {
3545 this->SetUnsortedObjectStatus(vtkExodusIIReader::ELEM_BLOCK, blkIndices[i], on);
3546 }
3547 }
3548
3549 //-----------------------------------------------------------------------------
SetPartStatus(const vtkStdString & name,int flag)3550 void vtkExodusIIReaderPrivate::SetPartStatus(const vtkStdString& name, int flag)
3551 {
3552 for(unsigned int idx=0; idx<this->PartInfo.size(); ++idx)
3553 {
3554 if ( name == this->PartInfo[idx].Name )
3555 {
3556 this->SetPartStatus(idx,flag);
3557 return;
3558 }
3559 }
3560 }
3561
3562 //-----------------------------------------------------------------------------
GetNumberOfMaterials()3563 int vtkExodusIIReaderPrivate::GetNumberOfMaterials()
3564 {
3565 return static_cast<int>( this->MaterialInfo.size() );
3566 }
3567
3568 //-----------------------------------------------------------------------------
GetMaterialName(int idx)3569 const char* vtkExodusIIReaderPrivate::GetMaterialName(int idx)
3570 {
3571 return this->MaterialInfo[idx].Name.c_str();
3572 }
3573
3574 //-----------------------------------------------------------------------------
GetMaterialStatus(int idx)3575 int vtkExodusIIReaderPrivate::GetMaterialStatus(int idx)
3576 {
3577 std::vector<int> blkIndices = this->MaterialInfo[idx].BlockIndices;
3578
3579 for (unsigned int i=0;i<blkIndices.size();i++)
3580 {
3581 if (!this->GetUnsortedObjectStatus(vtkExodusIIReader::ELEM_BLOCK,blkIndices[i]))
3582 {
3583 return 0;
3584 }
3585 }
3586 return 1;
3587 }
3588
3589 //-----------------------------------------------------------------------------
GetMaterialStatus(const vtkStdString & name)3590 int vtkExodusIIReaderPrivate::GetMaterialStatus(const vtkStdString& name)
3591 {
3592 for (unsigned int i=0;i<this->MaterialInfo.size();i++)
3593 {
3594 if (this->MaterialInfo[i].Name==name)
3595 {
3596 return this->GetMaterialStatus(i);
3597 }
3598 }
3599 return -1;
3600 }
3601
3602 //-----------------------------------------------------------------------------
SetMaterialStatus(int idx,int on)3603 void vtkExodusIIReaderPrivate::SetMaterialStatus(int idx, int on)
3604 {
3605 //update the block status for all the blocks in this material
3606 std::vector<int> blkIndices = this->MaterialInfo[idx].BlockIndices;
3607
3608 for (unsigned int i=0;i<blkIndices.size();i++)
3609 {
3610 this->SetUnsortedObjectStatus(vtkExodusIIReader::ELEM_BLOCK,blkIndices[i],on);
3611 }
3612 }
3613
3614 //-----------------------------------------------------------------------------
SetMaterialStatus(const vtkStdString & name,int flag)3615 void vtkExodusIIReaderPrivate::SetMaterialStatus(const vtkStdString& name, int flag)
3616 {
3617 for(unsigned int idx=0; idx<this->MaterialInfo.size(); ++idx)
3618 {
3619 if ( name == this->MaterialInfo[idx].Name )
3620 {
3621 this->SetMaterialStatus(idx,flag);
3622 return;
3623 }
3624 }
3625 }
3626
3627 //-----------------------------------------------------------------------------
GetNumberOfAssemblies()3628 int vtkExodusIIReaderPrivate::GetNumberOfAssemblies()
3629 {
3630 return static_cast<int>( this->AssemblyInfo.size() );
3631 }
3632
3633 //-----------------------------------------------------------------------------
GetAssemblyName(int idx)3634 const char* vtkExodusIIReaderPrivate::GetAssemblyName(int idx)
3635 {
3636 return this->AssemblyInfo[idx].Name.c_str();
3637 }
3638
3639 //-----------------------------------------------------------------------------
GetAssemblyStatus(int idx)3640 int vtkExodusIIReaderPrivate::GetAssemblyStatus(int idx)
3641 {
3642 std::vector<int> blkIndices = this->AssemblyInfo[idx].BlockIndices;
3643
3644 for (unsigned int i=0;i<blkIndices.size();i++)
3645 {
3646 if (!this->GetUnsortedObjectStatus(vtkExodusIIReader::ELEM_BLOCK,blkIndices[i]))
3647 {
3648 return 0;
3649 }
3650 }
3651 return 1;
3652 }
3653
3654 //-----------------------------------------------------------------------------
GetAssemblyStatus(const vtkStdString & name)3655 int vtkExodusIIReaderPrivate::GetAssemblyStatus(const vtkStdString& name)
3656 {
3657 for (unsigned int i=0;i<this->AssemblyInfo.size();i++)
3658 {
3659 if (this->AssemblyInfo[i].Name==name)
3660 {
3661 return this->GetAssemblyStatus(i);
3662 }
3663 }
3664 return -1;
3665 }
3666
3667 //-----------------------------------------------------------------------------
SetAssemblyStatus(int idx,int on)3668 void vtkExodusIIReaderPrivate::SetAssemblyStatus(int idx, int on)
3669 {
3670 std::vector<int> blkIndices = this->AssemblyInfo[idx].BlockIndices;
3671
3672 //update the block status for all the blocks in this material
3673 for (unsigned int i=0;i<blkIndices.size();i++)
3674 {
3675 this->SetUnsortedObjectStatus(vtkExodusIIReader::ELEM_BLOCK,blkIndices[i],on);
3676 }
3677 }
3678
3679 //-----------------------------------------------------------------------------
SetAssemblyStatus(const vtkStdString & name,int flag)3680 void vtkExodusIIReaderPrivate::SetAssemblyStatus(const vtkStdString& name, int flag)
3681 {
3682 for(unsigned int idx=0; idx<this->AssemblyInfo.size(); ++idx)
3683 {
3684 if ( name == this->AssemblyInfo[idx].Name )
3685 {
3686 this->SetAssemblyStatus(idx,flag);
3687 return;
3688 }
3689 }
3690 }
3691
3692 //-----------------------------------------------------------------------------
3693 // Normally, this would be below with all the other vtkExodusIIReader member definitions,
3694 // but the PrintSelf test script is really lame.
PrintSelf(ostream & os,vtkIndent indent)3695 void vtkExodusIIReader::PrintSelf( ostream& os, vtkIndent indent )
3696 {
3697 this->Superclass::PrintSelf( os, indent );
3698 os << indent << "FileName: " << ( this->FileName ? this->FileName : "(null)" ) << "\n";
3699 os << indent << "XMLFileName: " << ( this->XMLFileName ? this->XMLFileName : "(null)" ) << "\n";
3700 os << indent << "DisplayType: " << this->DisplayType << "\n";
3701 os << indent << "TimeStep: " << this->TimeStep << "\n";
3702 os << indent << "TimeStepRange: [" << this->TimeStepRange[0] << ", " << this->TimeStepRange[1] << "]\n";
3703 os << indent << "ModeShapesRange: [ "
3704 << this->GetModeShapesRange()[0] << ", " << this->GetModeShapesRange()[1] << "]\n";
3705 os << indent << "IgnoreFileTime: " << this->GetIgnoreFileTime() << "\n";
3706 os << indent << "SILUpdateStamp: " << this->SILUpdateStamp << "\n";
3707 if ( this->Metadata )
3708 {
3709 os << indent << "Metadata:\n";
3710 this->Metadata->PrintData( os, indent.GetNextIndent() );
3711 }
3712 else
3713 {
3714 os << indent << "Metadata: (null)\n";
3715 }
3716 }
3717
3718
PrintData(ostream & os,vtkIndent indent)3719 void vtkExodusIIReaderPrivate::PrintData( ostream& os, vtkIndent indent )
3720 {
3721 //this->Superclass::Print Self( os, indent );
3722 os << indent << "Exoid: " << this->Exoid << "\n";
3723 os << indent << "AppWordSize: " << this->AppWordSize << "\n";
3724 os << indent << "DiskWordSize: " << this->DiskWordSize << "\n";
3725 os << indent << "ExodusVersion: " << this->ExodusVersion << "\n";
3726 os << indent << "ModelParameters:\n";
3727
3728 vtkIndent inden2 = indent.GetNextIndent();
3729 os << inden2 << "Title: " << this->ModelParameters.title << "\n";
3730 os << inden2 << "Dimension: " << this->ModelParameters.num_dim << "\n";
3731 os << inden2 << "Nodes: " << this->ModelParameters.num_nodes << "\n";
3732 os << inden2 << "Edges: " << this->ModelParameters.num_edge << "\n";
3733 os << inden2 << "Faces: " << this->ModelParameters.num_face << "\n";
3734 os << inden2 << "Elements: " << this->ModelParameters.num_elem << "\n";
3735 os << inden2 << "Edge Blocks: " << this->ModelParameters.num_edge_blk << "\n";
3736 os << inden2 << "Face Blocks: " << this->ModelParameters.num_face_blk << "\n";
3737 os << inden2 << "Element Blocks: " << this->ModelParameters.num_elem_blk << "\n";
3738 os << inden2 << "Node Sets: " << this->ModelParameters.num_node_sets << "\n";
3739 os << inden2 << "Edge Sets: " << this->ModelParameters.num_edge_sets << "\n";
3740 os << inden2 << "Face Sets: " << this->ModelParameters.num_face_sets << "\n";
3741 os << inden2 << "Side Sets: " << this->ModelParameters.num_side_sets << "\n";
3742 os << inden2 << "Element Sets: " << this->ModelParameters.num_elem_sets << "\n";
3743 os << inden2 << "Node Maps: " << this->ModelParameters.num_node_maps << "\n";
3744 os << inden2 << "Edge Maps: " << this->ModelParameters.num_edge_maps << "\n";
3745 os << inden2 << "Face Maps: " << this->ModelParameters.num_face_maps << "\n";
3746 os << inden2 << "Element Maps: " << this->ModelParameters.num_elem_maps << "\n";
3747
3748 os << indent << "Time steps (" << this->Times.size() << "):";
3749 int i;
3750 for ( i = 0; i < (int)this->Times.size(); ++i )
3751 {
3752 os << " " << this->Times[i];
3753 }
3754 os << "\n";
3755 os << indent << "HasModeShapes: " << this->HasModeShapes << "\n";
3756 os << indent << "ModeShapeTime: " << this->ModeShapeTime << "\n";
3757 os << indent << "AnimateModeShapes: " << this->AnimateModeShapes << "\n";
3758
3759 // Print nodal variables
3760 if ( !this->ArrayInfo[ vtkExodusIIReader::NODAL ].empty() )
3761 {
3762 os << indent << "Nodal Arrays:\n";
3763 std::vector<ArrayInfoType>::iterator ai;
3764 for ( ai = this->ArrayInfo[ vtkExodusIIReader::NODAL ].begin(); ai != this->ArrayInfo[ vtkExodusIIReader::NODAL ].end(); ++ai )
3765 {
3766 printArray( os, indent, vtkExodusIIReader::NODAL, *ai );
3767 }
3768 }
3769
3770 // Print blocks
3771 os << indent << "Blocks:\n";
3772 std::map<int,std::vector<BlockInfoType> >::iterator bti;
3773 for ( bti = this->BlockInfo.begin(); bti != this->BlockInfo.end(); ++bti )
3774 {
3775 std::vector<BlockInfoType>::iterator bi;
3776 for ( bi = bti->second.begin(); bi != bti->second.end(); ++bi )
3777 {
3778 printBlock( os, indent.GetNextIndent(), bti->first, *bi );
3779 }
3780 if ( !this->ArrayInfo[ bti->first ].empty() )
3781 {
3782 os << indent << " Results variables:\n";
3783 std::vector<ArrayInfoType>::iterator ai;
3784 for ( ai = this->ArrayInfo[ bti->first ].begin(); ai != this->ArrayInfo[ bti->first ].end(); ++ai )
3785 {
3786 printArray( os, indent.GetNextIndent(), bti->first, *ai );
3787 }
3788 }
3789 }
3790
3791 // Print sets
3792 os << indent << "Sets:\n";
3793 std::map<int,std::vector<SetInfoType> >::iterator sti;
3794 for ( sti = this->SetInfo.begin(); sti != this->SetInfo.end(); ++sti )
3795 {
3796 std::vector<SetInfoType>::iterator si;
3797 for ( si = sti->second.begin(); si != sti->second.end(); ++si )
3798 {
3799 printSet( os, indent.GetNextIndent(), sti->first, *si );
3800 }
3801 if ( !this->ArrayInfo[ sti->first ].empty() )
3802 {
3803 os << indent << " Results variables:\n";
3804 std::vector<ArrayInfoType>::iterator ai;
3805 for ( ai = this->ArrayInfo[ sti->first ].begin(); ai != this->ArrayInfo[ sti->first ].end(); ++ai )
3806 {
3807 printArray( os, indent.GetNextIndent(), sti->first, *ai );
3808 }
3809 }
3810 }
3811
3812 // Print maps
3813 os << indent << "Maps:\n";
3814 std::map<int,std::vector<MapInfoType> >::iterator mti;
3815 for ( mti = this->MapInfo.begin(); mti != this->MapInfo.end(); ++mti )
3816 {
3817 std::vector<MapInfoType>::iterator mi;
3818 for ( mi = mti->second.begin(); mi != mti->second.end(); ++mi )
3819 {
3820 printMap( os, indent.GetNextIndent(), mti->first, *mi );
3821 }
3822 }
3823
3824 os << indent << "Array Cache:\n";
3825 this->Cache->PrintSelf( os, inden2 );
3826
3827 os << indent << "SqueezePoints: " << this->SqueezePoints << "\n";
3828 os << indent << "ApplyDisplacements: " << this->ApplyDisplacements << "\n";
3829 os << indent << "DisplacementMagnitude: " << this->DisplacementMagnitude << "\n";
3830 os << indent << "GenerateObjectIdArray: " << this->GenerateObjectIdArray << "\n";
3831 os << indent << "GenerateFileIdArray: " << this->GenerateFileIdArray << "\n";
3832 os << indent << "FileId: " << this->FileId << "\n";
3833 }
3834
OpenFile(const char * filename)3835 int vtkExodusIIReaderPrivate::OpenFile( const char* filename )
3836 {
3837 if ( ! filename || ! strlen( filename ) )
3838 {
3839 vtkErrorMacro( "Exodus filename pointer was nullptr or pointed to an empty string." );
3840 return 0;
3841 }
3842
3843 if ( this->Exoid >= 0 )
3844 {
3845 this->CloseFile();
3846 }
3847
3848 this->Exoid = ex_open( filename, EX_READ,
3849 &this->AppWordSize, &this->DiskWordSize, &this->ExodusVersion );
3850 if ( this->Exoid <= 0 )
3851 {
3852 vtkErrorMacro( "Unable to open \"" << filename << "\" for reading" );
3853 return 0;
3854 }
3855
3856 #ifdef VTK_USE_64BIT_IDS
3857 // Set the exodus API to always return integer types as 64-bit
3858 // without this call, large exodus files are not supported (which
3859 // is ok in 32 bit ids mode since VTK's ids can't fit the data).
3860 ex_set_int64_status(this->Exoid, EX_ALL_INT64_API);
3861 #endif
3862 // figure out the longest string name we have and then set that to be the
3863 // maximum length for the variable names. This is called every time that the reader
3864 // is updated so we don't have to worry about setting the global max_name_length variable.
3865 // this is because in our current version of the ExodusII libraries the exo Id isn't used
3866 // in the ex_set_max_name_length() function.
3867 ex_set_max_name_length(this->Exoid, this->Parent->GetMaxNameLength());
3868
3869 vtkIdType numNodesInFile;
3870 char dummyChar;
3871 float dummyFloat;
3872 ex_inquire(this->Exoid, EX_INQ_NODES, &numNodesInFile, &dummyFloat, &dummyChar);
3873
3874 return 1;
3875 }
3876
CloseFile()3877 int vtkExodusIIReaderPrivate::CloseFile()
3878 {
3879 if ( this->Exoid >= 0 )
3880 {
3881 VTK_EXO_FUNC( ex_close( this->Exoid ), "Could not close an open file (" << this->Exoid << ")" );
3882 this->Exoid = -1;
3883 }
3884 return 0;
3885 }
3886
UpdateTimeInformation()3887 int vtkExodusIIReaderPrivate::UpdateTimeInformation()
3888 {
3889 // BUG #15632: For files with spatial partitions, vtkPExodusIIReader uses vtkExodusIIReader
3890 // to read each of the files. Since time information between those files doesn't change and
3891 // it can be quite time consuming to collect the time information, vtkPExodusIIReader forcibly passes
3892 // time information from the first reader to all others. SkipUpdateTimeInformation helps us get that
3893 // going without significant changes to the reader.
3894 if (this->SkipUpdateTimeInformation)
3895 {
3896 return 0;
3897 }
3898
3899 int exoid = this->Exoid;
3900 vtkIdType itmp[5];
3901 int num_timesteps;
3902 int i;
3903
3904 VTK_EXO_FUNC( ex_inquire( exoid, EX_INQ_TIME, itmp, nullptr, nullptr ), "Inquire for EX_INQ_TIME failed" );
3905 num_timesteps = itmp[0];
3906
3907 this->Times.clear();
3908 if ( num_timesteps > 0 )
3909 {
3910 this->Times.resize( num_timesteps );
3911
3912 int exo_err = ex_get_all_times( this->Exoid, &this->Times[0] );
3913 if ( exo_err < 0 || this->IgnoreFileTime)
3914 {
3915 for ( i = 0; i < num_timesteps; ++i )
3916 {
3917 this->Times[i] = i;
3918 }
3919 //vtkWarningMacro("Could not retrieve time values, assuming times equal to timesteps");
3920 }
3921 }
3922 return 0;
3923 }
3924
3925 //-----------------------------------------------------------------------------
BuildSIL()3926 void vtkExodusIIReaderPrivate::BuildSIL()
3927 {
3928 // Initialize the SIL, dump all previous information.
3929 this->SIL->Initialize();
3930 if (this->Parser)
3931 {
3932 // The parser has built the SIL for us,
3933 // use that.
3934 this->SIL->ShallowCopy(this->Parser->GetSIL());
3935 return;
3936 }
3937
3938 // Else build a minimal SIL with only the blocks.
3939 vtkSmartPointer<vtkVariantArray> childEdge =
3940 vtkSmartPointer<vtkVariantArray>::New();
3941 childEdge->InsertNextValue(0);
3942
3943 vtkSmartPointer<vtkVariantArray> crossEdge =
3944 vtkSmartPointer<vtkVariantArray>::New();
3945 crossEdge->InsertNextValue(0);
3946
3947 // CrossEdge is an edge linking hierarchies.
3948 vtkUnsignedCharArray* crossEdgesArray = vtkUnsignedCharArray::New();
3949 crossEdgesArray->SetName("CrossEdges");
3950 this->SIL->GetEdgeData()->AddArray(crossEdgesArray);
3951 crossEdgesArray->Delete();
3952
3953 std::deque<std::string> names;
3954 int cc;
3955
3956 // Now build the hierarchy.
3957 vtkIdType rootId = this->SIL->AddVertex();
3958 names.push_back("SIL");
3959
3960 // Add the ELEM_BLOCK subtree.
3961 vtkIdType blocksRoot = this->SIL->AddChild(rootId, childEdge);
3962 names.push_back("Blocks");
3963
3964 // Add the assembly subtree
3965 this->SIL->AddChild(rootId, childEdge);
3966 names.push_back("Assemblies");
3967
3968 // Add the materials subtree
3969 this->SIL->AddChild(rootId, childEdge);
3970 names.push_back("Materials");
3971
3972 // This is the map of block names to node ids.
3973 std::map<std::string, vtkIdType> blockids;
3974 int numBlocks = this->GetNumberOfObjectsOfType(vtkExodusIIReader::ELEM_BLOCK);
3975 for (cc=0; cc < numBlocks; cc++)
3976 {
3977 vtkIdType child = this->SIL->AddChild(blocksRoot, childEdge);
3978 std::string block_name =
3979 this->GetObjectName(vtkExodusIIReader::ELEM_BLOCK, cc);
3980 names.push_back(block_name);
3981 blockids[block_name] = child;
3982 }
3983
3984 // This array is used to assign names to nodes.
3985 vtkStringArray* namesArray = vtkStringArray::New();
3986 namesArray->SetName("Names");
3987 namesArray->SetNumberOfTuples(this->SIL->GetNumberOfVertices());
3988 this->SIL->GetVertexData()->AddArray(namesArray);
3989 namesArray->Delete();
3990
3991 std::deque<std::string>::iterator iter;
3992 for (cc=0, iter = names.begin(); iter != names.end(); ++iter, ++cc)
3993 {
3994 namesArray->SetValue(cc, (*iter).c_str());
3995 }
3996 }
3997
3998 //-----------------------------------------------------------------------------
RequestInformation()3999 int vtkExodusIIReaderPrivate::RequestInformation()
4000 {
4001 int exoid = this->Exoid;
4002 //int itmp[5];
4003 vtkIdType* ids;
4004 vtkIdType nids;
4005 int obj;
4006 int i, j;
4007 int num_timesteps;
4008 char** obj_names;
4009 char** obj_typenames = nullptr;
4010 char** var_names = nullptr;
4011 int have_var_names;
4012 int num_vars = 0; /* number of variables per object */
4013 char tmpName[256];
4014 tmpName[255] = '\0';
4015 int maxNameLength = this->Parent->GetMaxNameLength();
4016
4017 this->InformationTimeStamp.Modified(); // Update MTime so that it will be newer than parent's FileNameMTime
4018
4019 VTK_EXO_FUNC( ex_get_init_ext( exoid, &this->ModelParameters ),
4020 "Unable to read database parameters." );
4021
4022 VTK_EXO_FUNC( this->UpdateTimeInformation(), "" );
4023
4024 //VTK_EXO_FUNC( ex_inquire( exoid, EX_INQ_TIME, itmp, 0, 0 ), "Inquire for EX_INQ_TIME failed" );
4025 //num_timesteps = itmp[0];
4026
4027 num_timesteps = static_cast<int>( this->Times.size() );
4028 /*
4029 this->Times.clear();
4030 if ( num_timesteps > 0 )
4031 {
4032 this->Times.resize( num_timesteps );
4033 VTK_EXO_FUNC( ex_get_all_times( this->Exoid, &this->Times[0] ), "Could not retrieve time values." );
4034 }
4035 */
4036 for ( i = 0; i < num_obj_types; ++i )
4037 {
4038 if(OBJTYPE_IS_NODAL(i))
4039 {
4040 continue;
4041 }
4042
4043 vtkIdType blockEntryFileOffset = 1;
4044 vtkIdType setEntryFileOffset = 1;
4045
4046 std::map<int,int> sortedObjects;
4047
4048 int* truth_tab = nullptr;
4049 have_var_names = 0;
4050
4051 VTK_EXO_FUNC( ex_inquire( exoid, obj_sizes[i], &nids, nullptr, nullptr ), "Object ID list size could not be determined." );
4052
4053 if ( nids )
4054 {
4055 ids = (vtkIdType*) malloc ( nids * sizeof(vtkIdType) );
4056 obj_names = (char**) malloc( nids * sizeof(char*) );
4057 for ( obj = 0; obj < nids; ++obj )
4058 {
4059 obj_names[obj] = (char*) malloc( (maxNameLength + 1) * sizeof(char) );
4060 }
4061 if ( OBJTYPE_IS_BLOCK(i) )
4062 {
4063 obj_typenames = (char**) malloc( nids * sizeof(char*) );
4064 for ( obj = 0; obj < nids; ++obj )
4065 {
4066 obj_typenames[obj] = (char*) malloc( (maxNameLength + 1) * sizeof(char) );
4067 obj_typenames[obj][0] = '\0';
4068 }
4069 }
4070 }
4071 else
4072 {
4073 ids = nullptr;
4074 obj_names = nullptr;
4075 obj_typenames = nullptr;
4076 }
4077
4078 if ( nids == 0 && ! OBJTYPE_IS_MAP(i) )
4079 continue;
4080
4081 if ( nids )
4082 {
4083 VTK_EXO_FUNC( ex_get_ids( exoid, static_cast<ex_entity_type>( obj_types[i] ), ids ),
4084 "Could not read object ids for i=" << i << " and otyp=" << obj_types[i] << "." );
4085 VTK_EXO_FUNC( ex_get_names( exoid, static_cast<ex_entity_type>( obj_types[i] ), obj_names ),
4086 "Could not read object names." );
4087 }
4088
4089 BlockInfoType binfo;
4090 SetInfoType sinfo;
4091 MapInfoType minfo;
4092
4093 if ( OBJTYPE_IS_BLOCK(i) )
4094 {
4095 this->BlockInfo[obj_types[i]].clear();
4096 this->BlockInfo[obj_types[i]].reserve( nids );
4097 }
4098 else if ( OBJTYPE_IS_SET(i) )
4099 {
4100 this->SetInfo[obj_types[i]].clear();
4101 this->SetInfo[obj_types[i]].reserve( nids );
4102 }
4103 else
4104 {
4105 this->MapInfo[obj_types[i]].clear();
4106 this->MapInfo[obj_types[i]].reserve( nids );
4107 }
4108
4109 if ( (OBJTYPE_IS_BLOCK(i)) || (OBJTYPE_IS_SET(i)))
4110 {
4111 VTK_EXO_FUNC( ex_get_var_param( exoid, obj_typestr[i], &num_vars ), "Could not read number of variables." );
4112
4113 if (num_vars && num_timesteps > 0)
4114 {
4115 truth_tab = (int*) malloc(num_vars * nids * sizeof(int));
4116 VTK_EXO_FUNC( ex_get_var_tab( exoid, obj_typestr[i], nids, num_vars, truth_tab ), "Could not read truth table." );
4117
4118 var_names = (char**) malloc(num_vars * sizeof(char*));
4119 for (j = 0; j < num_vars; ++j)
4120 var_names[j] = (char*) malloc( (maxNameLength + 1) * sizeof(char));
4121
4122 VTK_EXO_FUNC( ex_get_var_names( exoid, obj_typestr[i], num_vars, var_names ), "Could not read variable names." );
4123 this->RemoveBeginningAndTrailingSpaces(num_vars, var_names, maxNameLength);
4124 have_var_names = 1;
4125 }
4126 }
4127
4128 if ( !have_var_names)
4129 var_names = nullptr;
4130
4131 for (obj = 0; obj < nids; ++obj)
4132 {
4133
4134 if ( OBJTYPE_IS_BLOCK(i))
4135 {
4136
4137 binfo.Name = obj_names[obj];
4138 binfo.Id = ids[obj];
4139 binfo.CachedConnectivity = nullptr;
4140 binfo.NextSqueezePoint = 0;
4141 if (obj_types[i] == vtkExodusIIReader::ELEM_BLOCK)
4142 {
4143 VTK_EXO_FUNC( ex_get_block( exoid, static_cast<ex_entity_type>( obj_types[i] ), ids[obj], obj_typenames[obj],
4144 &binfo.Size, &binfo.BdsPerEntry[0], &binfo.BdsPerEntry[1], &binfo.BdsPerEntry[2], &binfo.AttributesPerEntry ),
4145 "Could not read block params." );
4146 binfo.Status = 1; // load element blocks by default
4147 binfo.TypeName = obj_typenames[obj];
4148 }
4149 else
4150 {
4151 VTK_EXO_FUNC( ex_get_block( exoid, static_cast<ex_entity_type>( obj_types[i] ), ids[obj], obj_typenames[obj],
4152 &binfo.Size, &binfo.BdsPerEntry[0], &binfo.BdsPerEntry[1], &binfo.BdsPerEntry[2], &binfo.AttributesPerEntry ),
4153 "Could not read block params." );
4154 binfo.Status = 0; // don't load edge/face blocks by default
4155 binfo.TypeName = obj_typenames[obj];
4156 binfo.BdsPerEntry[1] = binfo.BdsPerEntry[2] = 0;
4157 }
4158 this->GetInitialObjectStatus(obj_types[i], &binfo);
4159 //num_entries = binfo.Size;
4160 binfo.FileOffset = blockEntryFileOffset;
4161 blockEntryFileOffset += binfo.Size;
4162 if (binfo.Name.length() == 0)
4163 {
4164 snprintf( tmpName, sizeof(tmpName),
4165 #ifdef VTK_USE_64BIT_IDS
4166 "Unnamed block ID: %lld Type: %s",
4167 #else
4168 "Unnamed block ID: %d Type: %s",
4169 #endif
4170 ids[obj], binfo.TypeName.length() ? binfo.TypeName.c_str() : "nullptr");
4171 binfo.Name = tmpName;
4172 }
4173 binfo.OriginalName = binfo.Name;
4174 this->DetermineVtkCellType(binfo);
4175
4176 if (binfo.AttributesPerEntry)
4177 {
4178 char** attr_names;
4179 attr_names
4180 = (char**) malloc(binfo.AttributesPerEntry * sizeof(char*));
4181 for (j = 0; j < binfo.AttributesPerEntry; ++j)
4182 attr_names[j]
4183 = (char*) malloc( (maxNameLength + 1) * sizeof(char));
4184
4185 VTK_EXO_FUNC( ex_get_attr_names( exoid, static_cast<ex_entity_type>( obj_types[i] ), ids[obj], attr_names ),
4186 "Could not read attributes names." );
4187
4188 for (j = 0; j < binfo.AttributesPerEntry; ++j)
4189 {
4190 binfo.AttributeNames.push_back(attr_names[j]);
4191 binfo.AttributeStatus.push_back( 0); // don't load attributes by default
4192 }
4193
4194 for (j = 0; j < binfo.AttributesPerEntry; ++j)
4195 free(attr_names[j]);
4196 free(attr_names);
4197 }
4198
4199 // Check to see if there is metadata that defines what part, material,
4200 // and assembly(ies) this block belongs to.
4201
4202 if (this->Parser && this->Parser->HasInformationAboutBlock(binfo.Id))
4203 {
4204 // Update the block name using the XML.
4205 binfo.Name = this->Parser->GetBlockName(binfo.Id);
4206
4207 // int blockIdx = static_cast<int>( this->BlockInfo[obj_types[i]].size() );
4208 //// Add this block to our parts, materials, and assemblies collections
4209 //unsigned int k;
4210 //int found = 0;
4211
4212 //// Look to see if this part has already been created
4213 //for (k=0;k<this->PartInfo.size();k++)
4214 // {
4215 // if (this->PartInfo[k].Name==partName)
4216 // {
4217 // //binfo.PartId = k;
4218 // this->PartInfo[k].BlockIndices.push_back(blockIdx);
4219 // found=1;
4220 // }
4221 // }
4222
4223 //if (!found)
4224 // {
4225 // PartInfoType pinfo;
4226 // pinfo.Name = partName;
4227 // pinfo.Id = static_cast<int>( this->PartInfo.size() );
4228 // //binfo.PartId = k;
4229 // pinfo.BlockIndices.push_back(blockIdx);
4230 // this->PartInfo.push_back(pinfo);
4231 // }
4232 //
4233 //found=0;
4234 //for (k=0;k<this->MaterialInfo.size();k++)
4235 // {
4236 // if (this->MaterialInfo[k].Name==materialName)
4237 // {
4238 // //binfo.MaterialId = k;
4239 // this->MaterialInfo[k].BlockIndices.push_back(blockIdx);
4240 // found=1;
4241 // }
4242 // }
4243 //if (!found)
4244 // {
4245 // MaterialInfoType matinfo;
4246 // matinfo.Name = materialName;
4247 // matinfo.Id = static_cast<int>( this->MaterialInfo.size() );
4248 // //binfo.MaterialId = k;
4249 // matinfo.BlockIndices.push_back(blockIdx);
4250 // this->MaterialInfo.push_back(matinfo);
4251 // }
4252 //
4253 //for (k=0;k<localAssemblyNames.size();k++)
4254 // {
4255 // vtkStdString assemblyName=localAssemblyNames[k];
4256 // found=0;
4257 // for (unsigned int n=0;n<this->AssemblyInfo.size();n++)
4258 // {
4259 // if (this->AssemblyInfo[n].Name==assemblyName){
4260 // //binfo.AssemblyIds.push_back(j);
4261 // this->AssemblyInfo[n].BlockIndices.push_back(blockIdx);
4262 // found=1;
4263 // }
4264 // }
4265 // if (!found)
4266 // {
4267 // AssemblyInfoType ainfo;
4268 // ainfo.Name = assemblyName;
4269 // ainfo.Id = static_cast<int>( this->AssemblyInfo.size() );
4270 // //binfo.AssemblyIds.push_back(k);
4271 // ainfo.BlockIndices.push_back(blockIdx);
4272 // this->AssemblyInfo.push_back(ainfo);
4273 // }
4274 // }
4275 }
4276
4277 sortedObjects[binfo.Id]
4278 = static_cast<int>(this->BlockInfo[obj_types[i]].size());
4279 this->BlockInfo[obj_types[i]].push_back(binfo);
4280
4281 }
4282 else if ( OBJTYPE_IS_SET(i))
4283 {
4284
4285 sinfo.Name = obj_names[obj];
4286 sinfo.Status = 0;
4287 sinfo.Id = ids[obj];
4288 sinfo.CachedConnectivity = nullptr;
4289 sinfo.NextSqueezePoint = 0;
4290
4291 VTK_EXO_FUNC( ex_get_set_param( exoid, static_cast<ex_entity_type>( obj_types[i] ), ids[obj], &sinfo.Size, &sinfo.DistFact),
4292 "Could not read set parameters." );
4293 //num_entries = sinfo.Size;
4294 sinfo.FileOffset = setEntryFileOffset;
4295 setEntryFileOffset += sinfo.Size;
4296 this->GetInitialObjectStatus(obj_types[i], &sinfo);
4297 if (sinfo.Name.length() == 0)
4298 {
4299 snprintf( tmpName, sizeof(tmpName),
4300 #ifdef VTK_USE_64BIT_IDS
4301 "Unnamed set ID: %lld",
4302 #else
4303 "Unnamed set ID: %d",
4304 #endif
4305 ids[obj]);
4306 sinfo.Name = tmpName;
4307 }
4308 sortedObjects[sinfo.Id] = (int) this->SetInfo[obj_types[i]].size();
4309 this->SetInfo[obj_types[i]].push_back(sinfo);
4310
4311 }
4312 else
4313 { /* object is map */
4314
4315 minfo.Id = ids[obj];
4316 minfo.Status = obj == 0 ? 1 : 0; // only load the first map by default
4317 switch (obj_types[i])
4318 {
4319 case vtkExodusIIReader::NODE_MAP:
4320 minfo.Size = this->ModelParameters.num_nodes;
4321 break;
4322 case vtkExodusIIReader::EDGE_MAP:
4323 minfo.Size = this->ModelParameters.num_edge;
4324 break;
4325 case vtkExodusIIReader::FACE_MAP:
4326 minfo.Size = this->ModelParameters.num_face;
4327 break;
4328 case vtkExodusIIReader::ELEM_MAP:
4329 minfo.Size = this->ModelParameters.num_elem;
4330 break;
4331 default:
4332 minfo.Size = 0;
4333 }
4334 minfo.Name = obj_names[obj];
4335 if (minfo.Name.length() == 0)
4336 {
4337 snprintf( tmpName, sizeof(tmpName),
4338 #ifdef VTK_USE_64BIT_IDS
4339 "Unnamed map ID: %lld",
4340 #else
4341 "Unnamed map ID: %d",
4342 #endif
4343 ids[obj] );
4344 minfo.Name = tmpName;
4345 }
4346 sortedObjects[minfo.Id] = (int) this->MapInfo[obj_types[i]].size();
4347 this->MapInfo[obj_types[i]].push_back(minfo);
4348
4349 }
4350
4351 } // end of loop over all object ids
4352
4353 // Now that we have all objects of that type in the sortedObjects, we can
4354 // iterate over it to fill in the SortedObjectIndices (the map is a *sorted*
4355 // associative container)
4356 std::map<int,int>::iterator soit;
4357 for ( soit = sortedObjects.begin(); soit != sortedObjects.end(); ++soit )
4358 {
4359 this->SortedObjectIndices[obj_types[i]].push_back( soit->second );
4360 }
4361
4362 if ( ((OBJTYPE_IS_BLOCK(i)) || (OBJTYPE_IS_SET(i))) && num_vars && num_timesteps > 0 )
4363 {
4364 this->ArrayInfo[obj_types[i]].clear();
4365 // Fill in ArrayInfo entries, combining array names into vectors/tensors where appropriate:
4366 this->GlomArrayNames( obj_types[i], nids, num_vars, var_names, truth_tab );
4367 }
4368
4369 if ( var_names )
4370 {
4371 for ( j = 0; j < num_vars; ++j )
4372 free( var_names[j] );
4373 free( var_names );
4374 }
4375 if ( truth_tab )
4376 free( truth_tab );
4377
4378 if ( nids )
4379 {
4380 free( ids );
4381
4382 for ( obj = 0; obj < nids; ++obj )
4383 free( obj_names[obj] );
4384 free( obj_names );
4385
4386 if ( OBJTYPE_IS_BLOCK(i) )
4387 {
4388 for ( obj = 0; obj < nids; ++obj )
4389 free( obj_typenames[obj] );
4390 free( obj_typenames );
4391 }
4392 }
4393
4394 } // end of loop over all object types
4395 //this->ComputeGridOffsets();
4396
4397 // Now read information for nodal arrays
4398 VTK_EXO_FUNC( ex_get_var_param( exoid, "n", &num_vars ), "Unable to read number of nodal variables." );
4399 if ( num_vars > 0 )
4400 {
4401 var_names = (char**) malloc( num_vars * sizeof(char*) );
4402 for ( j = 0; j < num_vars; ++j )
4403 {
4404 var_names[j] = (char*) malloc( (maxNameLength + 1) * sizeof(char) );
4405 }
4406
4407 VTK_EXO_FUNC( ex_get_var_names( exoid, "n", num_vars, var_names ), "Could not read nodal variable names." );
4408 this->RemoveBeginningAndTrailingSpaces( num_vars, var_names, maxNameLength );
4409
4410 nids = 1;
4411 std::vector<int> dummy_truth;
4412 dummy_truth.reserve( num_vars );
4413 for ( j = 0; j < num_vars; ++j )
4414 {
4415 dummy_truth.push_back( 1 );
4416 }
4417
4418 this->GlomArrayNames( vtkExodusIIReader::NODAL, nids, num_vars, var_names, &dummy_truth[0] );
4419
4420 for ( j = 0; j < num_vars; ++j )
4421 {
4422 free( var_names[j] );
4423 }
4424 free( var_names );
4425 var_names = nullptr;
4426 }
4427
4428 // Now read information for global variables
4429 VTK_EXO_FUNC( ex_get_var_param( exoid, "g", &num_vars ), "Unable to read number of global variables." );
4430 if ( num_vars > 0 )
4431 {
4432 var_names = (char**) malloc( num_vars * sizeof(char*) );
4433 for ( j = 0; j < num_vars; ++j )
4434 {
4435 var_names[j] = (char*) malloc( (maxNameLength + 1) * sizeof(char) );
4436 }
4437
4438 VTK_EXO_FUNC( ex_get_var_names( exoid, "g", num_vars, var_names ), "Could not read global variable names." );
4439 this->RemoveBeginningAndTrailingSpaces( num_vars, var_names, maxNameLength );
4440
4441 nids = 1;
4442 std::vector<int> dummy_truth;
4443 dummy_truth.reserve( num_vars );
4444 for ( j = 0; j < num_vars; ++j )
4445 {
4446 dummy_truth.push_back( 1 );
4447 }
4448
4449 this->GlomArrayNames( vtkExodusIIReader::GLOBAL, nids, num_vars, var_names, &dummy_truth[0] );
4450
4451 for ( j = 0; j < num_vars; ++j )
4452 {
4453 free( var_names[j] );
4454 }
4455 free( var_names );
4456 var_names = nullptr;
4457 }
4458
4459 return 0;
4460 }
4461
RequestData(vtkIdType timeStep,vtkMultiBlockDataSet * output)4462 int vtkExodusIIReaderPrivate::RequestData( vtkIdType timeStep, vtkMultiBlockDataSet* output )
4463 {
4464 // The work done here depends on several conditions:
4465 // - Has connectivity changed (i.e., has block/set status changed)?
4466 // - If so, AND if point "squeeze" turned on, must reload points and re-squeeze.
4467 // - If so, must re-assemble all arrays
4468 // - Must recreate block/set id array.
4469 // - Has requested time changed?
4470 // - If so, AND if "deflect mesh" turned on, must load new deflections and compute new points.
4471 // - If so, must assemble all time-varying arrays for new time.
4472 // - Has array status changed?
4473 // - If so, must delete old and/or load new arrays.
4474 // Obviously, many of these tasks overlap. For instance, it would be
4475 // foolish to re-assemble all the arrays when the connectivity has
4476 // changed and then toss them out in order to load arrays for a
4477 // different time step.
4478
4479 // Caching strategy: use GLOBAL "object type" for assembled arrays.
4480 // If connectivity hasn't changed, then these arrays can be used;
4481 // otherwise, "raw" arrays must be used.
4482 // Pro:
4483 // - single cache == easier bookkeeping (two caches would require us to decide how to equitably split avail mem between them)
4484 // - many different operations are accelerated:
4485 // - just changing which variables are loaded
4486 // - changing which blocks are in output (doesn't require disk access if cache hit)
4487 // - possible extension to single-node/cell over time
4488 // Con:
4489 // - higher memory consumption for caching the same set of arrays (or, holding cache size fixed: fewer arrays fit)
4490
4491 if ( ! output )
4492 {
4493 vtkErrorMacro( "You must specify an output mesh" );
4494 }
4495
4496 // Iterate over all block and set types, creating a
4497 // multiblock dataset to hold objects of each type.
4498 int conntypidx;
4499 int nbl = 0;
4500 output->SetNumberOfBlocks( num_conn_types );
4501 for ( conntypidx = 0; conntypidx < num_conn_types; ++conntypidx )
4502 {
4503 int otypidx = conn_obj_idx_cvt[conntypidx];
4504 int otyp = obj_types[otypidx];
4505 // Loop over all blocks/sets of this type
4506 int numObj = this->GetNumberOfObjectsOfType( otyp );
4507 vtkMultiBlockDataSet* mbds;
4508 mbds = vtkMultiBlockDataSet::New();
4509 mbds->SetNumberOfBlocks( numObj );
4510 output->SetBlock( conntypidx, mbds );
4511 output->GetMetaData(conntypidx)->Set(vtkCompositeDataSet::NAME(),
4512 conn_types_names[conntypidx]);
4513 mbds->FastDelete();
4514 //cout << "++ Block: " << mbds << " ObjectType: " << otyp << "\n";
4515 int obj;
4516 int sortIdx;
4517 for ( sortIdx = 0; sortIdx < numObj; ++sortIdx )
4518 {
4519 const char* object_name = this->GetObjectName(otyp, sortIdx);
4520
4521 // Preserve the "sorted" order when concatenating
4522 obj = this->SortedObjectIndices[otyp][sortIdx];
4523 BlockSetInfoType* bsinfop = static_cast<BlockSetInfoType*>( this->GetObjectInfo( otypidx, obj ) );
4524 //cout << ( bsinfop->Status ? "++" : "--" ) << " ObjectId: " << bsinfop->Id;
4525 if ( ! bsinfop->Status )
4526 {
4527 mbds->SetBlock( sortIdx, nullptr );
4528 if (object_name)
4529 {
4530 mbds->GetMetaData(sortIdx)->Set(vtkCompositeDataSet::NAME(), object_name);
4531 }
4532 continue;
4533 }
4534 vtkUnstructuredGrid* ug = vtkUnstructuredGrid::New();
4535 mbds->SetBlock( sortIdx, ug );
4536 if (object_name)
4537 {
4538 mbds->GetMetaData(sortIdx)->Set(vtkCompositeDataSet::NAME(), object_name);
4539 }
4540 ug->FastDelete();
4541 //cout << " Grid: " << ug << "\n";
4542
4543 // Connectivity first. Either from the cache in bsinfop or read from disk.
4544 // Connectivity isn't allowed to change with time.
4545 this->AssembleOutputConnectivity( timeStep, otyp, obj, conntypidx, bsinfop, ug );
4546
4547 // Now prepare points.
4548 // These shouldn't change unless the connectivity has changed.
4549 this->AssembleOutputPoints( timeStep, bsinfop, ug );
4550
4551 // Then, add the desired arrays from cache (or disk)
4552 // Point and cell arrays are handled differently because they
4553 // have different problems to solve.
4554 // Point arrays must use the PointMap index to subset values.
4555 // Cell arrays may be used as-is.
4556 this->AssembleOutputPointArrays( timeStep, bsinfop, ug );
4557 this->AssembleOutputCellArrays( timeStep, otyp, obj, bsinfop, ug );
4558
4559 // Some arrays may be procedurally generated (e.g., the ObjectId
4560 // array, global element and node number arrays). This constructs
4561 // them as required.
4562 this->AssembleOutputProceduralArrays( timeStep, otyp, obj, ug );
4563
4564 // QA and informational records in the ExodusII file are appended
4565 // to each and every output unstructured grid.
4566 this->AssembleOutputGlobalArrays( timeStep, otyp, obj, bsinfop, ug );
4567
4568 // Maps (as distinct from the global element and node arrays above)
4569 // are per-cell or per-node integers. As with point arrays, the
4570 // PointMap is used to subset node maps. Cell arrays are stored in
4571 // ExodusII files for all elements (across all blocks of a given type)
4572 // and thus must be subset for the unstructured grid of interest.
4573 this->AssembleOutputPointMaps( timeStep, bsinfop, ug );
4574 this->AssembleOutputCellMaps( timeStep, otyp, obj, bsinfop, ug );
4575 ++nbl;
4576 }
4577 }
4578
4579 this->CloseFile();
4580
4581 return 0;
4582 }
4583
SetUpEmptyGrid(vtkMultiBlockDataSet * output)4584 int vtkExodusIIReaderPrivate::SetUpEmptyGrid( vtkMultiBlockDataSet* output )
4585 {
4586 if ( ! output )
4587 {
4588 vtkErrorMacro( "You must specify an output mesh" );
4589 }
4590
4591 // Iterate over all block and set types, creating a
4592 // multiblock dataset to hold objects of each type.
4593 int conntypidx;
4594 int nbl = 0;
4595 output->SetNumberOfBlocks( num_conn_types );
4596 for ( conntypidx = 0; conntypidx < num_conn_types; ++conntypidx )
4597 {
4598 int otypidx = conn_obj_idx_cvt[conntypidx];
4599 int otyp = obj_types[otypidx];
4600 // Loop over all blocks/sets of this type
4601 int numObj = this->GetNumberOfObjectsOfType( otyp );
4602 vtkMultiBlockDataSet* mbds;
4603 mbds = vtkMultiBlockDataSet::New();
4604 mbds->SetNumberOfBlocks( numObj );
4605 output->SetBlock( conntypidx, mbds );
4606 output->GetMetaData(conntypidx)->Set(vtkCompositeDataSet::NAME(),
4607 conn_types_names[conntypidx]);
4608 mbds->FastDelete();
4609 int obj;
4610 int sortIdx;
4611 for ( sortIdx = 0; sortIdx < numObj; ++sortIdx )
4612 {
4613 // Preserve the "sorted" order when concatenating
4614 obj = this->SortedObjectIndices[otyp][sortIdx];
4615 BlockSetInfoType* bsinfop = static_cast<BlockSetInfoType*>( this->GetObjectInfo( otypidx, obj ) );
4616 //cout << ( bsinfop->Status ? "++" : "--" ) << " ObjectId: " << bsinfop->Id;
4617 if ( ! bsinfop->Status )
4618 {
4619 //cout << "\n";
4620 mbds->SetBlock( sortIdx, nullptr );
4621 continue;
4622 }
4623 vtkUnstructuredGrid* ug = vtkUnstructuredGrid::New();
4624 mbds->SetBlock( sortIdx, ug );
4625 ug->FastDelete();
4626 ++nbl;
4627 }
4628 }
4629 #if 0
4630 int idx;
4631 vtkUnstructuredGrid* leaf;
4632
4633 // Set up an empty unstructured grid
4634 leaf->Allocate(0);
4635
4636 // Create new points
4637 vtkPoints* newPoints = vtkPoints::New();
4638 newPoints->SetNumberOfPoints( 0 );
4639 leaf->SetPoints( newPoints );
4640 newPoints->Delete();
4641 newPoints = nullptr;
4642
4643 // Create point and cell arrays
4644 int typ;
4645 for ( typ = 0; typ < numObjResultTypes; ++typ )
4646 {
4647 int otyp = objResultTypes[typ];
4648 int nObjArr = this->GetNumberOfObjectArrays( otyp );
4649 for ( idx = 0; idx < nObjArr; ++idx )
4650 {
4651 vtkDoubleArray* da = vtkDoubleArray::New();
4652 da->SetName( this->GetObjectArrayName( otyp, idx ) );
4653 da->SetNumberOfComponents( this->GetNumberOfObjectArrayComponents( otyp, idx ) );
4654 if ( otyp == vtkExodusIIReader::NODAL )
4655 {
4656 leaf->GetPointData()->AddArray( da );
4657 }
4658 else
4659 {
4660 leaf->GetCellData()->AddArray( da );
4661 }
4662 da->FastDelete();
4663 }
4664 }
4665
4666 for ( typ = 0; typ < numObjAttribTypes; ++typ )
4667 {
4668 int otyp = objAttribTypes[typ];
4669 int nObj = this->GetNumberOfObjects( otyp );
4670 for ( idx = 0; idx < nObj; ++ idx )
4671 {
4672 // Attributes are defined per block, not per block type.
4673 int nObjAtt = this->GetNumberOfObjectAttributes( otyp, idx );
4674 for ( int aidx = 0; aidx < nObjAtt; ++ aidx )
4675 {
4676 vtkDoubleArray* da = vtkDoubleArray::New();
4677 da->SetName( this->GetObjectAttributeName( otyp, idx, aidx ) );
4678 da->SetNumberOfComponents( 1 );
4679 // All attributes are cell data
4680 leaf->GetCellData()->AddArray( da );
4681 da->FastDelete();
4682 }
4683 }
4684 }
4685
4686 if ( this->GetGenerateObjectIdCellArray() )
4687 {
4688 vtkIntArray* ia = vtkIntArray::New();
4689 ia->SetName( this->GetObjectIdArrayName() );
4690 ia->SetNumberOfComponents( 1 );
4691 leaf->GetCellData()->AddArray( ia );
4692 ia->FastDelete();
4693 }
4694
4695 if ( this->GetGenerateGlobalNodeIdArray() )
4696 {
4697 vtkIntArray* ia = vtkIntArray::New();
4698 ia->SetName( this->GetGlobalNodeIdArrayName() );
4699 ia->SetNumberOfComponents( 1 );
4700 leaf->GetPointData()->AddArray( ia );
4701 ia->FastDelete();
4702 }
4703
4704 if ( this->GetGenerateGlobalElementIdArray() )
4705 {
4706 vtkIntArray* ia = vtkIntArray::New();
4707 ia->SetName( this->GetGlobalElementIdArrayName() );
4708 ia->SetNumberOfComponents( 1 );
4709 leaf->GetCellData()->AddArray( ia );
4710 ia->FastDelete();
4711 }
4712 #endif // 0
4713 return 1;
4714 }
4715
Reset()4716 void vtkExodusIIReaderPrivate::Reset()
4717 {
4718 this->CloseFile();
4719 this->ResetCache(); // must come before BlockInfo and SetInfo are cleared.
4720 this->BlockInfo.clear();
4721 this->SetInfo.clear();
4722 this->MapInfo.clear();
4723 this->PartInfo.clear();
4724 this->MaterialInfo.clear();
4725 this->AssemblyInfo.clear();
4726 this->SortedObjectIndices.clear();
4727 this->ArrayInfo.clear();
4728 this->ExodusVersion = -1.;
4729 this->Times.clear();
4730 memset( (void*)&this->ModelParameters, 0, sizeof(this->ModelParameters) );
4731
4732 // Don't clear file id since it's not part of meta-data that's read from the
4733 // file, it's set externally (by vtkPExodusIIReader).
4734 // Refer to BUG #7633.
4735 //this->FileId = 0;
4736
4737 this->Modified();
4738 }
4739
ResetSettings()4740 void vtkExodusIIReaderPrivate::ResetSettings()
4741 {
4742 this->GenerateGlobalElementIdArray = 0;
4743 this->GenerateGlobalNodeIdArray = 0;
4744 this->GenerateImplicitElementIdArray = 0;
4745 this->GenerateImplicitNodeIdArray = 0;
4746 this->GenerateGlobalIdArray = 0;
4747 this->GenerateObjectIdArray = 1;
4748 this->GenerateFileIdArray = 0;
4749
4750 this->ApplyDisplacements = 1;
4751 this->DisplacementMagnitude = 1.;
4752
4753 this->HasModeShapes = 0;
4754 this->ModeShapeTime = -1.;
4755 this->AnimateModeShapes = 1;
4756
4757 this->SqueezePoints = 1;
4758
4759 this->InitialArrayInfo.clear();
4760 this->InitialObjectInfo.clear();
4761 }
4762
ResetCache()4763 void vtkExodusIIReaderPrivate::ResetCache()
4764 {
4765 this->Cache->Clear();
4766 this->Cache->SetCacheCapacity(this->CacheSize); // FIXME: Perhaps Cache should have a Reset and a Clear method?
4767 this->ClearConnectivityCaches();
4768 }
4769
SetCacheSize(double size)4770 void vtkExodusIIReaderPrivate::SetCacheSize( double size )
4771 {
4772 if (this->CacheSize != size)
4773 {
4774 this->CacheSize = size;
4775 this->Cache->SetCacheCapacity(this->CacheSize);
4776 this->Modified();
4777 }
4778 }
4779
IsXMLMetadataValid()4780 bool vtkExodusIIReaderPrivate::IsXMLMetadataValid()
4781 {
4782 // Make sure that each block id referred to in the metadata arrays exist
4783 // in the data
4784
4785 std::set<int> blockIdsFromXml;
4786 this->Parser->GetBlockIds(blockIdsFromXml);
4787 std::vector<BlockInfoType> blocksFromData = this->BlockInfo[vtkExodusIIReader::ELEM_BLOCK];
4788 std::vector<BlockInfoType>::iterator iter2;
4789 std::set<int>::iterator iter;
4790 bool isBlockValid = false;
4791 for(iter = blockIdsFromXml.begin(); iter!=blockIdsFromXml.end(); ++iter)
4792 {
4793 isBlockValid = false;
4794 for(iter2 = blocksFromData.begin(); iter2!=blocksFromData.end(); ++iter2)
4795 {
4796 if(*iter == (*iter2).Id)
4797 {
4798 isBlockValid = true;
4799 break;
4800 }
4801 }
4802 if(!isBlockValid)
4803 {
4804 break;
4805 }
4806 }
4807
4808 return isBlockValid;
4809 }
4810
SetSqueezePoints(int sp)4811 void vtkExodusIIReaderPrivate::SetSqueezePoints( int sp )
4812 {
4813 if ( this->SqueezePoints == sp )
4814 return;
4815
4816 this->SqueezePoints = sp;
4817 this->Modified();
4818
4819 // Invalidate global "topology" cache
4820 // The point maps should be invalidated
4821 // FIXME: bsinfop->NextSqueezePoint = 0 for all bsinfop
4822 // FIXME: bsinfop->CachedConnectivity = 0 for all bsinfop
4823 // FIXME: bsinfop->PointMap.clear() for all bsinfop
4824 // FIXME: bsinfop->ReversePointMap.clear() for all bsinfop
4825 }
4826
GetNumberOfNodes()4827 int vtkExodusIIReaderPrivate::GetNumberOfNodes()
4828 {
4829 return this->ModelParameters.num_nodes;
4830 }
4831
GetNumberOfObjectsOfType(int otyp)4832 int vtkExodusIIReaderPrivate::GetNumberOfObjectsOfType( int otyp )
4833 {
4834 int i = this->GetObjectTypeIndexFromObjectType( otyp );
4835 if ( i < 0 )
4836 {
4837 // Could signal warning here, but might not want it if file simply doesn't have objects of some obscure type (e.g., edge sets)
4838 return 0;
4839 }
4840 return this->GetNumberOfObjectsAtTypeIndex( i );
4841 }
4842
GetNumberOfObjectArraysOfType(int otyp)4843 int vtkExodusIIReaderPrivate::GetNumberOfObjectArraysOfType( int otyp )
4844 {
4845 std::map<int,std::vector<ArrayInfoType> >::iterator it = this->ArrayInfo.find( otyp );
4846 if ( it != this->ArrayInfo.end() )
4847 {
4848 return (int) it->second.size();
4849 }
4850 // Could signal warning here, but might not want it if file simply doesn't have objects of some obscure type (e.g., edge sets)
4851 return 0;
4852 }
4853
GetObjectName(int otyp,int k)4854 const char* vtkExodusIIReaderPrivate::GetObjectName( int otyp, int k )
4855 {
4856 ObjectInfoType* oinfop = this->GetSortedObjectInfo( otyp, k );
4857 return oinfop ? oinfop->Name.c_str() : nullptr;
4858 }
4859
GetObjectId(int otyp,int k)4860 int vtkExodusIIReaderPrivate::GetObjectId( int otyp, int k )
4861 {
4862 ObjectInfoType* oinfop = this->GetSortedObjectInfo( otyp, k );
4863 return oinfop ? oinfop->Id : -1;
4864 }
4865
GetObjectSize(int otyp,int k)4866 int vtkExodusIIReaderPrivate::GetObjectSize( int otyp, int k )
4867 {
4868 ObjectInfoType* oinfop = this->GetSortedObjectInfo( otyp, k );
4869 return oinfop ? oinfop->Size : 0;
4870 }
4871
GetObjectStatus(int otyp,int k)4872 int vtkExodusIIReaderPrivate::GetObjectStatus( int otyp, int k )
4873 {
4874 ObjectInfoType* oinfop = this->GetSortedObjectInfo( otyp, k );
4875 return oinfop ? oinfop->Status : 0;
4876 }
4877
GetUnsortedObjectStatus(int otyp,int k)4878 int vtkExodusIIReaderPrivate::GetUnsortedObjectStatus( int otyp, int k )
4879 {
4880 ObjectInfoType* oinfop = this->GetUnsortedObjectInfo( otyp, k );
4881 return oinfop ? oinfop->Status : 0;
4882 }
4883
GetInitialObjectStatus(int otyp,ObjectInfoType * objType)4884 void vtkExodusIIReaderPrivate::GetInitialObjectStatus( int otyp, ObjectInfoType *objType )
4885 {
4886 for(unsigned int oidx=0; oidx<this->InitialObjectInfo[otyp].size(); oidx++)
4887 {
4888 if( (!this->InitialObjectInfo[otyp][oidx].Name.empty() &&
4889 objType->Name == this->InitialObjectInfo[otyp][oidx].Name) ||
4890 (this->InitialObjectInfo[otyp][oidx].Id != -1 &&
4891 objType->Id == this->InitialObjectInfo[otyp][oidx].Id) )
4892 {
4893 objType->Status = this->InitialObjectInfo[otyp][oidx].Status;
4894 break;
4895 }
4896 }
4897 }
4898
SetObjectStatus(int otyp,int k,int stat)4899 void vtkExodusIIReaderPrivate::SetObjectStatus( int otyp, int k, int stat )
4900 {
4901 stat = (stat != 0); // Force stat to be either 0 or 1
4902 // OK, found the object
4903 ObjectInfoType* oinfop = this->GetSortedObjectInfo( otyp, k );
4904 if ( ! oinfop )
4905 { // error message will have been generated by GetSortedObjectInfo()
4906 return;
4907 }
4908
4909 if ( oinfop->Status == stat )
4910 { // no change => do nothing
4911 return;
4912 }
4913 oinfop->Status = stat;
4914
4915 this->Modified();
4916 }
4917
SetUnsortedObjectStatus(int otyp,int k,int stat)4918 void vtkExodusIIReaderPrivate::SetUnsortedObjectStatus( int otyp, int k, int stat )
4919 {
4920 stat = (stat != 0); // Force stat to be either 0 or 1
4921 // OK, found the object
4922 ObjectInfoType* oinfop = this->GetUnsortedObjectInfo( otyp, k );
4923 if ( ! oinfop )
4924 { // error message will have been generated by GetSortedObjectInfo()
4925 return;
4926 }
4927
4928 if ( oinfop->Status == stat )
4929 { // no change => do nothing
4930 return;
4931 }
4932 oinfop->Status = stat;
4933
4934 this->Modified();
4935 }
4936
SetInitialObjectStatus(int objectType,const char * objName,int status)4937 void vtkExodusIIReaderPrivate::SetInitialObjectStatus( int objectType, const char* objName, int status )
4938 {
4939 ObjectInfoType info;
4940 vtkStdString nm = objName;
4941 int idx = 0;
4942 int idlen = 0;
4943 int id = -1;
4944
4945 // When no name is found for an object, it is given one of a certain format.
4946 // Parse the id out of that string and use it to identify the object later.
4947 if ( ( idx = static_cast<int>( nm.find( "ID: " ) ) ) != (int) vtkStdString::npos )
4948 {
4949 idx += 4;
4950 idlen = 0;
4951 while(idx+idlen < static_cast<int>(nm.length()) && nm.at(idx+idlen) != ' ' )
4952 {
4953 idlen++;
4954 }
4955 id = atoi(nm.substr(idx,idlen).c_str());
4956 }
4957 else
4958 {
4959 info.Name = objName;
4960 }
4961 info.Id = id;
4962 info.Status = status;
4963 this->InitialObjectInfo[objectType].push_back(info);
4964 }
4965
GetObjectArrayName(int otyp,int i)4966 const char* vtkExodusIIReaderPrivate::GetObjectArrayName( int otyp, int i )
4967 {
4968 std::map<int,std::vector<ArrayInfoType> >::iterator it = this->ArrayInfo.find( otyp );
4969 if ( it != this->ArrayInfo.end() )
4970 {
4971 int N = (int) it->second.size();
4972 if ( i < 0 || i >= N )
4973 {
4974 vtkDebugMacro( "You requested array " << i << " in a collection of only " << N << " arrays." );
4975 return nullptr;
4976 }
4977 return it->second[i].Name.c_str();
4978 }
4979 vtkDebugMacro( "Could not find collection of arrays for objects of type " << otyp <<
4980 " (" << objtype_names[this->GetObjectTypeIndexFromObjectType(otyp)] << ")." );
4981 return nullptr;
4982 }
4983
GetNumberOfObjectArrayComponents(int otyp,int i)4984 int vtkExodusIIReaderPrivate::GetNumberOfObjectArrayComponents( int otyp, int i )
4985 {
4986 std::map<int,std::vector<ArrayInfoType> >::iterator it = this->ArrayInfo.find( otyp );
4987 if ( it != this->ArrayInfo.end() )
4988 {
4989 int N = (int) it->second.size();
4990 if ( i < 0 || i >= N )
4991 {
4992 vtkDebugMacro( "You requested array " << i << " in a collection of only " << N << " arrays." );
4993 return 0;
4994 }
4995 return it->second[i].Components;
4996 }
4997 vtkDebugMacro( "Could not find collection of arrays for objects of type " << otyp <<
4998 " (" << objtype_names[this->GetObjectTypeIndexFromObjectType(otyp)] << ")." );
4999 return 0;
5000 }
5001
GetObjectArrayStatus(int otyp,int i)5002 int vtkExodusIIReaderPrivate::GetObjectArrayStatus( int otyp, int i )
5003 {
5004 std::map<int,std::vector<ArrayInfoType> >::iterator it = this->ArrayInfo.find( otyp );
5005 if ( it != this->ArrayInfo.end() )
5006 {
5007 int N = (int) it->second.size();
5008 if ( i < 0 || i >= N )
5009 {
5010 vtkDebugMacro( "You requested array " << i << " in a collection of only " << N << " arrays." );
5011 return 0;
5012 }
5013 return it->second[i].Status;
5014 }
5015 vtkDebugMacro( "Could not find collection of arrays for objects of type " << otyp <<
5016 " (" << objtype_names[this->GetObjectTypeIndexFromObjectType(otyp)] << ")." );
5017 return 0;
5018 }
5019
5020
GetInitialObjectArrayStatus(int otyp,ArrayInfoType * objType)5021 void vtkExodusIIReaderPrivate::GetInitialObjectArrayStatus( int otyp, ArrayInfoType *objType )
5022 {
5023 for(unsigned int oidx=0; oidx<this->InitialArrayInfo[otyp].size(); oidx++)
5024 {
5025 if(objType->Name == this->InitialArrayInfo[otyp][oidx].Name)
5026 {
5027 objType->Status = this->InitialArrayInfo[otyp][oidx].Status;
5028 break;
5029 }
5030 }
5031 }
5032
SetObjectArrayStatus(int otyp,int i,int stat)5033 void vtkExodusIIReaderPrivate::SetObjectArrayStatus( int otyp, int i, int stat )
5034 {
5035 stat = ( stat != 0 ); // Force stat to be either 0 or 1
5036 std::map<int,std::vector<ArrayInfoType> >::iterator it = this->ArrayInfo.find( otyp );
5037 if ( it != this->ArrayInfo.end() )
5038 {
5039 int N = (int) it->second.size();
5040 if ( i < 0 || i >= N )
5041 {
5042 vtkDebugMacro( "You requested array " << i << " in a collection of only " << N << " arrays." );
5043 return;
5044 }
5045 if ( it->second[i].Status == stat )
5046 {
5047 // no change => do nothing
5048 return;
5049 }
5050 it->second[i].Status = stat;
5051 this->Modified();
5052 // FIXME: Mark something so we know what's changed since the last RequestData?!
5053 // For the "global" (assembled) array, this is tricky because we really only want
5054 // to invalidate a range of the total array... For now, we'll just force the "global"
5055 // array to be reassembled even if it does mean a lot more copying -- it's not like
5056 // it was any faster before.
5057 //vtkExodusIICacheKey key( 0, GLOBAL, 0, i );
5058 //vtkExodusIICacheKey pattern( 0, 1, 0, 1 );
5059 this->Cache->Invalidate(
5060 vtkExodusIICacheKey( 0, vtkExodusIIReader::GLOBAL, otyp, i ),
5061 vtkExodusIICacheKey( 0, 1, 1, 1 ) );
5062 }
5063 else
5064 {
5065 vtkDebugMacro( "Could not find collection of arrays for objects of type " << otyp <<
5066 " (" << objtype_names[this->GetObjectTypeIndexFromObjectType(otyp)] << ")." );
5067 }
5068 }
5069
SetInitialObjectArrayStatus(int objectType,const char * arrayName,int status)5070 void vtkExodusIIReaderPrivate::SetInitialObjectArrayStatus( int objectType, const char* arrayName, int status )
5071 {
5072 ArrayInfoType ainfo;
5073 ainfo.Name = arrayName;
5074 ainfo.Status = status;
5075 this->InitialArrayInfo[objectType].push_back(ainfo);
5076 }
5077
GetNumberOfObjectAttributes(int otyp,int oi)5078 int vtkExodusIIReaderPrivate::GetNumberOfObjectAttributes( int otyp, int oi )
5079 {
5080 std::map<int,std::vector<BlockInfoType> >::iterator it = this->BlockInfo.find( otyp );
5081 if ( it != this->BlockInfo.end() )
5082 {
5083 int N = (int) it->second.size();
5084 if ( oi < 0 || oi >= N )
5085 {
5086 int otypIdx = this->GetObjectTypeIndexFromObjectType(otyp);
5087 const char* btname = otypIdx >= 0 ? objtype_names[otypIdx] : "block";
5088 static_cast<void>(btname); // not referenced warning
5089 vtkDebugMacro( "You requested " << btname << " " << oi << " in a collection of only " << N << " blocks." );
5090 return 0;
5091 }
5092 oi = this->SortedObjectIndices[otyp][oi]; // index into sorted list of objects (block order, not file order)
5093 return (int) it->second[oi].AttributeNames.size();
5094 }
5095 return 0;
5096 }
5097
GetObjectAttributeName(int otyp,int oi,int ai)5098 const char* vtkExodusIIReaderPrivate::GetObjectAttributeName( int otyp, int oi, int ai )
5099 {
5100 std::map<int,std::vector<BlockInfoType> >::iterator it = this->BlockInfo.find( otyp );
5101 if ( it != this->BlockInfo.end() )
5102 {
5103 int N = (int) it->second.size();
5104 if ( oi < 0 || oi >= N )
5105 {
5106 vtkDebugMacro( "You requested block " << oi << " in a collection of only " << N << " blocks." );
5107 return nullptr;
5108 }
5109 oi = this->SortedObjectIndices[otyp][oi]; // index into sorted list of objects (block order, not file order)
5110 N = (int) it->second[oi].AttributeNames.size();
5111 if ( ai < 0 || ai >= N )
5112 {
5113 vtkDebugMacro( "You requested attribute " << ai << " in a collection of only " << N << " attributes." );
5114 return nullptr;
5115 }
5116 else
5117 {
5118 return it->second[oi].AttributeNames[ai].c_str();
5119 }
5120 }
5121 vtkDebugMacro( "Could not find collection of blocks of type " << otyp <<
5122 " (" << objtype_names[this->GetObjectTypeIndexFromObjectType(otyp)] << ")." );
5123 return nullptr;
5124 }
5125
GetObjectAttributeIndex(int otyp,int oi,const char * attribName)5126 int vtkExodusIIReaderPrivate::GetObjectAttributeIndex( int otyp, int oi, const char* attribName )
5127 {
5128 std::map<int,std::vector<BlockInfoType> >::iterator it = this->BlockInfo.find( otyp );
5129 if ( it != this->BlockInfo.end() )
5130 {
5131 int N = (int) it->second.size();
5132 if ( oi < 0 || oi >= N )
5133 {
5134 vtkDebugMacro( "You requested block " << oi << " in a collection of only " << N << " blocks." );
5135 return -1;
5136 }
5137 oi = this->SortedObjectIndices[otyp][oi]; // index into sorted list of objects (block order, not file order)
5138 N = (int) it->second[oi].AttributeNames.size();
5139 int ai;
5140 for ( ai = 0; ai < N; ++ai )
5141 {
5142 if ( it->second[oi].AttributeNames[ai] == attribName )
5143 {
5144 return ai;
5145 }
5146 }
5147 return -1;
5148 }
5149 vtkDebugMacro( "Could not find collection of blocks of type " << otyp <<
5150 " (" << objtype_names[this->GetObjectTypeIndexFromObjectType(otyp)] << ")." );
5151 return -1;
5152 }
5153
GetObjectAttributeStatus(int otyp,int oi,int ai)5154 int vtkExodusIIReaderPrivate::GetObjectAttributeStatus( int otyp, int oi, int ai )
5155 {
5156 std::map<int,std::vector<BlockInfoType> >::iterator it = this->BlockInfo.find( otyp );
5157 if ( it != this->BlockInfo.end() )
5158 {
5159 int N = (int) it->second.size();
5160 if ( oi < 0 || oi >= N )
5161 {
5162 vtkDebugMacro( "You requested block " << oi << " in a collection of only " << N << " blocks." );
5163 return 0;
5164 }
5165 oi = this->SortedObjectIndices[otyp][oi]; // index into sorted list of objects (block order, not file order)
5166 N = (int) it->second[oi].AttributeStatus.size();
5167 if ( ai < 0 || ai >= N )
5168 {
5169 vtkDebugMacro( "You requested attribute " << ai << " in a collection of only " << N << " attributes." );
5170 return 0;
5171 }
5172 else
5173 {
5174 return it->second[oi].AttributeStatus[ai];
5175 }
5176 }
5177 vtkDebugMacro( "Could not find collection of blocks of type " << otyp <<
5178 " (" << objtype_names[this->GetObjectTypeIndexFromObjectType(otyp)] << ")." );
5179 return 0;
5180 }
5181
SetObjectAttributeStatus(int otyp,int oi,int ai,int status)5182 void vtkExodusIIReaderPrivate::SetObjectAttributeStatus( int otyp, int oi, int ai, int status )
5183 {
5184 status = status ? 1 : 0;
5185 std::map<int,std::vector<BlockInfoType> >::iterator it = this->BlockInfo.find( otyp );
5186 if ( it != this->BlockInfo.end() )
5187 {
5188 int N = (int) it->second.size();
5189 if ( oi < 0 || oi >= N )
5190 {
5191 vtkDebugMacro( "You requested block " << oi << " in a collection of only " << N << " blocks." );
5192 return;
5193 }
5194 oi = this->SortedObjectIndices[otyp][oi]; // index into sorted list of objects (block order, not file order)
5195 N = (int) it->second[oi].AttributeStatus.size();
5196 if ( ai < 0 || ai >= N )
5197 {
5198 vtkDebugMacro( "You requested attribute " << ai << " in a collection of only " << N << " attribute." );
5199 return;
5200 }
5201 else
5202 {
5203 if ( it->second[oi].AttributeStatus[ai] == status )
5204 {
5205 return;
5206 }
5207 it->second[oi].AttributeStatus[ai] = status;
5208 this->Modified();
5209 }
5210 }
5211 vtkDebugMacro( "Could not find collection of blocks of type " << otyp <<
5212 " (" << objtype_names[this->GetObjectTypeIndexFromObjectType(otyp)] << ")." );
5213 }
5214
SetApplyDisplacements(vtkTypeBool d)5215 void vtkExodusIIReaderPrivate::SetApplyDisplacements( vtkTypeBool d )
5216 {
5217 if ( this->ApplyDisplacements == d )
5218 return;
5219
5220 this->ApplyDisplacements = d;
5221 this->Modified();
5222
5223 // Require the coordinates to be recomputed:
5224 this->Cache->Invalidate(
5225 vtkExodusIICacheKey( 0, vtkExodusIIReader::NODAL_COORDS, 0, 0 ),
5226 vtkExodusIICacheKey( 0, 1, 0, 0 ) );
5227 }
5228
SetDisplacementMagnitude(double s)5229 void vtkExodusIIReaderPrivate::SetDisplacementMagnitude( double s )
5230 {
5231 if ( this->DisplacementMagnitude == s )
5232 return;
5233
5234 this->DisplacementMagnitude = s;
5235 this->Modified();
5236
5237 // Require the coordinates to be recomputed:
5238 this->Cache->Invalidate(
5239 vtkExodusIICacheKey( 0, vtkExodusIIReader::NODAL_COORDS, 0, 0 ),
5240 vtkExodusIICacheKey( 0, 1, 0, 0 ) );
5241 }
5242
FindDisplacementVectors(int timeStep)5243 vtkDataArray* vtkExodusIIReaderPrivate::FindDisplacementVectors( int timeStep )
5244 {
5245 std::map<int,std::vector<ArrayInfoType> >::iterator it = this->ArrayInfo.find( vtkExodusIIReader::NODAL );
5246 if ( it != this->ArrayInfo.end() )
5247 {
5248 int N = (int) it->second.size();
5249 for ( int i = 0; i < N; ++i )
5250 {
5251 std::string upperName = vtksys::SystemTools::UpperCase( it->second[i].Name.substr( 0, 3 ) );
5252 if ( upperName == "DIS" && it->second[i].Components == this->ModelParameters.num_dim )
5253 {
5254 return this->GetCacheOrRead( vtkExodusIICacheKey( timeStep, vtkExodusIIReader::NODAL, 0, i ) );
5255 }
5256 }
5257 }
5258 return nullptr;
5259 }
5260
5261
5262 // -------------------------------------------------------- PUBLIC CLASS MEMBERS
5263
5264 vtkStandardNewMacro(vtkExodusIIReader);
5265 vtkCxxSetObjectMacro(vtkExodusIIReader,Metadata,vtkExodusIIReaderPrivate);
5266
vtkExodusIIReader()5267 vtkExodusIIReader::vtkExodusIIReader()
5268 {
5269 this->FileName = nullptr;
5270 this->XMLFileName = nullptr;
5271 this->Metadata = vtkExodusIIReaderPrivate::New();
5272 this->Metadata->Parent = this;
5273 this->Metadata->SetCacheSize(0.0);
5274 this->TimeStep = 0;
5275 this->TimeStepRange[0] = 0;
5276 this->TimeStepRange[1] = 0;
5277 this->ModeShapesRange[0] = 0;
5278 this->ModeShapesRange[1] = 0;
5279 this->DisplayType = 0;
5280 this->DisplayType = 0;
5281 this->SILUpdateStamp = -1;
5282
5283 this->SetNumberOfInputPorts( 0 );
5284 }
5285
~vtkExodusIIReader()5286 vtkExodusIIReader::~vtkExodusIIReader()
5287 {
5288 this->SetXMLFileName( nullptr );
5289 this->SetFileName( nullptr );
5290
5291 this->SetMetadata( nullptr );
5292 //this->SetExodusModel( 0 );
5293 }
5294
5295 // Normally, vtkExodusIIReader::PrintSelf would be here.
5296 // But it's above to prevent PrintSelf-Hybrid from failing because it assumes
5297 // the first PrintSelf method is the one for the class declared in the header file.
5298
CanReadFile(const char * fname)5299 int vtkExodusIIReader::CanReadFile( const char* fname )
5300 {
5301 int exoid;
5302 int appWordSize = 8;
5303 int diskWordSize = 8;
5304 float version;
5305
5306 if ( (exoid = ex_open( fname, EX_READ, &appWordSize, &diskWordSize, &version )) < 0 )
5307 {
5308 return 0;
5309 }
5310 if ( ex_close( exoid ) != 0 )
5311 {
5312 vtkWarningMacro( "Unable to close \"" << fname << "\" opened for testing." );
5313 return 0;
5314 }
5315 return 1;
5316 }
5317
5318 #if 0
5319 void vtkExodusIIReaderPrivate::Modified()
5320 {
5321 cout << "E2RP modified\n"; this->Superclass::Modified();
5322 }
5323
5324 void vtkExodusIIReader::Modified()
5325 {
5326 cout << "E2R modified\n"; this->Superclass::Modified();
5327 }
5328 #endif // 0
5329
GetMTime()5330 vtkMTimeType vtkExodusIIReader::GetMTime()
5331 {
5332 //return this->MTime.GetMTime();
5333 /*
5334 vtkMTimeType mtime1, mtime2;
5335 vtkMTimeType readerMTime = this->MTime.GetMTime();
5336 vtkMTimeType privateMTime = this->Metadata->GetMTime();
5337 vtkMTimeType fileNameMTime = this->FileNameMTime.GetMTime();
5338 vtkMTimeType xmlFileNameMTime = this->XMLFileNameMTime.GetMTime();
5339 mtime1 = privateMTime > readerMTime ? privateMTime : readerMTime;
5340 mtime2 = fileNameMTime > xmlFileNameMTime ? fileNameMTime : xmlFileNameMTime;
5341 return mtime1 > mtime2 ? mtime1 : mtime2;
5342 */
5343 vtkMTimeType readerMTime = this->MTime.GetMTime();
5344 vtkMTimeType privateMTime = this->Metadata->GetMTime();
5345 return privateMTime > readerMTime ? privateMTime : readerMTime;
5346 }
5347
GetMetadataMTime()5348 vtkMTimeType vtkExodusIIReader::GetMetadataMTime()
5349 {
5350 return this->Metadata->InformationTimeStamp < this->Metadata->GetMTime() ?
5351 this->Metadata->InformationTimeStamp : this->Metadata->GetMTime();
5352 }
5353
5354 #define vtkSetStringMacroBody(propName,fname) \
5355 int modified = 0; \
5356 if ( fname == this->propName ) \
5357 return; \
5358 if ( fname && this->propName && !strcmp( fname, this->propName ) ) \
5359 return; \
5360 modified = 1; \
5361 delete [] this->propName; \
5362 if ( fname ) \
5363 { \
5364 size_t fnl = strlen( fname ) + 1; \
5365 char* dst = new char[fnl]; \
5366 const char* src = fname; \
5367 this->propName = dst; \
5368 do { *dst++ = *src++; } while ( --fnl ); \
5369 } \
5370 else \
5371 { \
5372 this->propName = 0; \
5373 }
5374
SetFileName(const char * fname)5375 void vtkExodusIIReader::SetFileName( const char* fname )
5376 {
5377 vtkSetStringMacroBody(FileName,fname);
5378 if ( modified )
5379 {
5380 this->Metadata->Reset();
5381 this->FileNameMTime.Modified();
5382 }
5383 }
5384
SetXMLFileName(const char * fname)5385 void vtkExodusIIReader::SetXMLFileName( const char* fname )
5386 {
5387 vtkSetStringMacroBody(XMLFileName,fname);
5388 if ( modified )
5389 {
5390 this->XMLFileNameMTime.Modified();
5391 this->Modified();
5392 }
5393 }
5394
5395
5396
5397 //----------------------------------------------------------------------------
ProcessRequest(vtkInformation * request,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)5398 int vtkExodusIIReader::ProcessRequest(vtkInformation* request,
5399 vtkInformationVector** inputVector,
5400 vtkInformationVector* outputVector)
5401 {
5402 if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
5403 {
5404 return this->RequestData(request, inputVector, outputVector);
5405 }
5406
5407 // execute information
5408 if(request->Has(vtkDemandDrivenPipeline::REQUEST_INFORMATION()))
5409 {
5410 return this->RequestInformation(request, inputVector, outputVector);
5411 }
5412
5413 return this->Superclass::ProcessRequest(request, inputVector, outputVector);
5414 }
5415
5416
5417 //----------------------------------------------------------------------------
RequestInformation(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)5418 int vtkExodusIIReader::RequestInformation(
5419 vtkInformation* vtkNotUsed(request),
5420 vtkInformationVector** vtkNotUsed(inputVector),
5421 vtkInformationVector* outputVector )
5422 {
5423 int newMetadata = 0;
5424 vtkInformation* outInfo = outputVector->GetInformationObject(0);
5425
5426 // If the metadata is older than the filename
5427 if ( this->GetMetadataMTime() < this->FileNameMTime )
5428 {
5429 if ( this->Metadata->OpenFile( this->FileName ) )
5430 {
5431 // We need to initialize the XML parser before calling RequestInformation
5432 // on the metadata
5433 if ( this->FindXMLFile() )
5434 {
5435 vtkExodusIIReaderParser *parser = vtkExodusIIReaderParser::New();
5436 this->Metadata->SetParser(parser);
5437 // Now overwrite any names in the exodus file with names from XML file.
5438 parser->Go(this->XMLFileName);
5439 parser->Delete();
5440 }
5441
5442 this->Metadata->RequestInformation();
5443
5444 // Now check to see if the DART metadata is valid
5445 if(this->Metadata->Parser && !this->Metadata->IsXMLMetadataValid())
5446 {
5447 this->Metadata->Parser->Delete();
5448 this->Metadata->Parser = nullptr;
5449
5450 // Reset block names.
5451 int numBlocks = this->Metadata->GetNumberOfObjectsOfType(vtkExodusIIReader::ELEM_BLOCK);
5452 for (int cc=0; cc < numBlocks; cc++)
5453 {
5454 vtkExodusIIReaderPrivate::BlockInfoType* binfop =
5455 static_cast<vtkExodusIIReaderPrivate::BlockInfoType*>(
5456 this->Metadata->GetSortedObjectInfo(vtkExodusIIReader::ELEM_BLOCK, cc));
5457 binfop->Name = binfop->OriginalName;
5458 }
5459 }
5460
5461 // Once meta-data has been refreshed we update the SIL.
5462 this->Metadata->BuildSIL();
5463 this->SILUpdateStamp++; // update the timestamp.
5464
5465 this->Metadata->CloseFile();
5466 newMetadata = 1;
5467 }
5468 else
5469 {
5470 vtkErrorMacro( "Unable to open file \"" << (this->FileName ? this->FileName : "(null)") << "\" to read metadata" );
5471 return 0;
5472 }
5473 }
5474
5475 this->AdvertiseTimeSteps( outInfo );
5476
5477 // Advertize the SIL.
5478 outInfo->Set(vtkDataObject::SIL(), this->Metadata->GetSIL());
5479
5480 if ( newMetadata )
5481 {
5482 // update ExodusModelMetadata
5483 }
5484
5485 return 1;
5486 }
5487
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)5488 int vtkExodusIIReader::RequestData(
5489 vtkInformation* vtkNotUsed(request),
5490 vtkInformationVector** vtkNotUsed(inputVector),
5491 vtkInformationVector* outputVector )
5492 {
5493 if ( ! this->FileName || ! this->Metadata->OpenFile( this->FileName ) )
5494 {
5495 vtkErrorMacro( "Unable to open file \"" << (this->FileName ? this->FileName : "(null)") << "\" to read data" );
5496 return 0;
5497 }
5498
5499 vtkInformation* outInfo = outputVector->GetInformationObject(0);
5500 vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::SafeDownCast( outInfo->Get( vtkDataObject::DATA_OBJECT() ) );
5501
5502 // Check if a particular time was requested.
5503 if ( outInfo->Has( vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP() ) )
5504 { // Get the requested time step. We only support requests of a single time step in this reader right now
5505 double requestedTimeStep = outInfo->Get( vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP());
5506
5507 // Save the time value in the output data information.
5508 int length = outInfo->Length( vtkStreamingDemandDrivenPipeline::TIME_STEPS() );
5509 double* steps = outInfo->Get( vtkStreamingDemandDrivenPipeline::TIME_STEPS() );
5510
5511 if ( ! this->GetHasModeShapes() )
5512 {
5513 // find the highest time step with a time value that is smaller than the requested time.
5514 //timeStep = 0;
5515 //while (timeStep < length - 1 && steps[timeStep] < requestedTimeStep)
5516 // {
5517 // timeStep++;
5518 // }
5519 //this->TimeStep = timeStep;
5520
5521 //find the timestep with the closest value
5522 int cnt=0;
5523 int closestStep=0;
5524 double minDist=-1;
5525 for (cnt=0;cnt<length;cnt++)
5526 {
5527 double tdist=(steps[cnt]-requestedTimeStep>requestedTimeStep-steps[cnt])?
5528 steps[cnt]-requestedTimeStep:
5529 requestedTimeStep-steps[cnt];
5530 if (minDist<0 || tdist<minDist)
5531 {
5532 minDist=tdist;
5533 closestStep=cnt;
5534 }
5535 }
5536 this->TimeStep=closestStep;
5537 //cout << "Requested value: " << requestedTimeStep << " Step: " << this->TimeStep << endl;
5538 output->GetInformation()->Set( vtkDataObject::DATA_TIME_STEP(), steps[this->TimeStep] );
5539 }
5540 else if (this->GetAnimateModeShapes())
5541 {
5542 // Let the metadata know the time value so that the Metadata->RequestData call below will generate
5543 // the animated mode shape properly.
5544 this->Metadata->ModeShapeTime = requestedTimeStep;
5545 output->GetInformation()->Set( vtkDataObject::DATA_TIME_STEP(), this->Metadata->ModeShapeTime );
5546 //output->GetInformation()->Remove( vtkDataObject::DATA_TIME_STEP() );
5547 }
5548 }
5549
5550 this->Metadata->RequestData( this->TimeStep, output );
5551
5552 return 1;
5553 }
5554
GetMaxNameLength()5555 int vtkExodusIIReader::GetMaxNameLength()
5556 {
5557 return ex_inquire_int(this->Metadata->Exoid, EX_INQ_DB_MAX_USED_NAME_LENGTH);
5558 }
5559
SetGenerateObjectIdCellArray(vtkTypeBool x)5560 void vtkExodusIIReader::SetGenerateObjectIdCellArray( vtkTypeBool x ) { this->Metadata->SetGenerateObjectIdArray( x ); }
GetGenerateObjectIdCellArray()5561 vtkTypeBool vtkExodusIIReader::GetGenerateObjectIdCellArray() { return this->Metadata->GetGenerateObjectIdArray(); }
5562
SetGenerateGlobalElementIdArray(vtkTypeBool x)5563 void vtkExodusIIReader::SetGenerateGlobalElementIdArray( vtkTypeBool x ) { this->Metadata->SetGenerateGlobalElementIdArray( x ); }
GetGenerateGlobalElementIdArray()5564 vtkTypeBool vtkExodusIIReader::GetGenerateGlobalElementIdArray() { return this->Metadata->GetGenerateGlobalElementIdArray(); }
5565
SetGenerateGlobalNodeIdArray(vtkTypeBool x)5566 void vtkExodusIIReader::SetGenerateGlobalNodeIdArray( vtkTypeBool x ) { this->Metadata->SetGenerateGlobalNodeIdArray( x ); }
GetGenerateGlobalNodeIdArray()5567 vtkTypeBool vtkExodusIIReader::GetGenerateGlobalNodeIdArray() { return this->Metadata->GetGenerateGlobalNodeIdArray(); }
5568
SetGenerateImplicitElementIdArray(vtkTypeBool x)5569 void vtkExodusIIReader::SetGenerateImplicitElementIdArray( vtkTypeBool x ) { this->Metadata->SetGenerateImplicitElementIdArray( x ); }
GetGenerateImplicitElementIdArray()5570 vtkTypeBool vtkExodusIIReader::GetGenerateImplicitElementIdArray() { return this->Metadata->GetGenerateImplicitElementIdArray(); }
5571
SetGenerateImplicitNodeIdArray(vtkTypeBool x)5572 void vtkExodusIIReader::SetGenerateImplicitNodeIdArray( vtkTypeBool x ) { this->Metadata->SetGenerateImplicitNodeIdArray( x ); }
GetGenerateImplicitNodeIdArray()5573 vtkTypeBool vtkExodusIIReader::GetGenerateImplicitNodeIdArray() { return this->Metadata->GetGenerateImplicitNodeIdArray(); }
5574
SetGenerateFileIdArray(vtkTypeBool x)5575 void vtkExodusIIReader::SetGenerateFileIdArray( vtkTypeBool x ) { this->Metadata->SetGenerateFileIdArray( x ); }
GetGenerateFileIdArray()5576 vtkTypeBool vtkExodusIIReader::GetGenerateFileIdArray() { return this->Metadata->GetGenerateFileIdArray(); }
5577
SetFileId(int x)5578 void vtkExodusIIReader::SetFileId( int x ) { this->Metadata->SetFileId( x ); }
GetFileId()5579 int vtkExodusIIReader::GetFileId() { return this->Metadata->GetFileId(); }
5580
5581 // FIXME: Implement the four functions that return ID_NOT_FOUND below.
GetGlobalElementID(vtkDataSet * data,int localID)5582 int vtkExodusIIReader::GetGlobalElementID( vtkDataSet* data, int localID )
5583 { return GetGlobalElementID( data, localID, SEARCH_TYPE_ELEMENT_THEN_NODE ); }
GetGlobalElementID(vtkDataSet * data,int localID,int searchType)5584 int vtkExodusIIReader::GetGlobalElementID ( vtkDataSet* data, int localID, int searchType )
5585 { (void)data; (void)localID; (void)searchType; return ID_NOT_FOUND; }
5586
GetGlobalFaceID(vtkDataSet * data,int localID)5587 int vtkExodusIIReader::GetGlobalFaceID( vtkDataSet* data, int localID )
5588 { return GetGlobalFaceID( data, localID, SEARCH_TYPE_ELEMENT_THEN_NODE ); }
GetGlobalFaceID(vtkDataSet * data,int localID,int searchType)5589 int vtkExodusIIReader::GetGlobalFaceID ( vtkDataSet* data, int localID, int searchType )
5590 { (void)data; (void)localID; (void)searchType; return ID_NOT_FOUND; }
5591
GetGlobalEdgeID(vtkDataSet * data,int localID)5592 int vtkExodusIIReader::GetGlobalEdgeID( vtkDataSet* data, int localID )
5593 { return GetGlobalEdgeID( data, localID, SEARCH_TYPE_ELEMENT_THEN_NODE ); }
GetGlobalEdgeID(vtkDataSet * data,int localID,int searchType)5594 int vtkExodusIIReader::GetGlobalEdgeID ( vtkDataSet* data, int localID, int searchType )
5595 { (void)data; (void)localID; (void)searchType; return ID_NOT_FOUND; }
5596
GetGlobalNodeID(vtkDataSet * data,int localID)5597 int vtkExodusIIReader::GetGlobalNodeID( vtkDataSet* data, int localID )
5598 { return GetGlobalNodeID( data, localID, SEARCH_TYPE_NODE_THEN_ELEMENT ); }
GetGlobalNodeID(vtkDataSet * data,int localID,int searchType)5599 int vtkExodusIIReader::GetGlobalNodeID( vtkDataSet* data, int localID, int searchType )
5600 { (void)data; (void)localID; (void)searchType; return ID_NOT_FOUND; }
5601
SetApplyDisplacements(vtkTypeBool d)5602 void vtkExodusIIReader::SetApplyDisplacements( vtkTypeBool d )
5603 {
5604 this->Metadata->SetApplyDisplacements( d );
5605 }
GetApplyDisplacements()5606 vtkTypeBool vtkExodusIIReader::GetApplyDisplacements()
5607 {
5608 return this->Metadata->GetApplyDisplacements();
5609 }
5610
SetDisplacementMagnitude(float s)5611 void vtkExodusIIReader::SetDisplacementMagnitude( float s )
5612 {
5613 this->Metadata->SetDisplacementMagnitude( s );
5614 }
GetDisplacementMagnitude()5615 float vtkExodusIIReader::GetDisplacementMagnitude()
5616 {
5617 return this->Metadata->GetDisplacementMagnitude();
5618 }
5619
SetHasModeShapes(vtkTypeBool ms)5620 void vtkExodusIIReader::SetHasModeShapes( vtkTypeBool ms )
5621 {
5622 this->Metadata->SetHasModeShapes(ms);
5623 }
5624
GetHasModeShapes()5625 vtkTypeBool vtkExodusIIReader::GetHasModeShapes()
5626 {
5627 return this->Metadata->GetHasModeShapes();
5628 }
5629
SetModeShapeTime(double phase)5630 void vtkExodusIIReader::SetModeShapeTime( double phase )
5631 {
5632 // Phase should repeat outside the bounds [0,1]. For example, 0.25 is
5633 // equivalent to 1.25, 2.25, -0.75, and -1.75.
5634 double x = phase - floor(phase);
5635 this->Metadata->SetModeShapeTime( x );
5636 }
5637
GetModeShapeTime()5638 double vtkExodusIIReader::GetModeShapeTime()
5639 {
5640 return this->Metadata->GetModeShapeTime();
5641 }
5642
SetAnimateModeShapes(vtkTypeBool flag)5643 void vtkExodusIIReader::SetAnimateModeShapes(vtkTypeBool flag)
5644 {
5645 this->Metadata->SetAnimateModeShapes(flag);
5646 }
5647
GetAnimateModeShapes()5648 vtkTypeBool vtkExodusIIReader::GetAnimateModeShapes()
5649 {
5650 return this->Metadata->GetAnimateModeShapes();
5651 }
5652
SetIgnoreFileTime(bool value)5653 void vtkExodusIIReader::SetIgnoreFileTime(bool value)
5654 {
5655 if (this->Metadata->GetIgnoreFileTime() == value)
5656 {
5657 return;
5658 }
5659
5660 this->Metadata->SetIgnoreFileTime(value);
5661 this->Modified();
5662 }
5663
GetIgnoreFileTime()5664 bool vtkExodusIIReader::GetIgnoreFileTime()
5665 {
5666 return this->Metadata->GetIgnoreFileTime();
5667 }
5668
GetTitle()5669 const char* vtkExodusIIReader::GetTitle() { return this->Metadata->ModelParameters.title; }
GetDimensionality()5670 int vtkExodusIIReader::GetDimensionality() { return this->Metadata->ModelParameters.num_dim; }
GetNumberOfTimeSteps()5671 int vtkExodusIIReader::GetNumberOfTimeSteps() { return (int) this->Metadata->Times.size(); }
5672
GetNumberOfNodesInFile()5673 int vtkExodusIIReader::GetNumberOfNodesInFile() { return this->Metadata->ModelParameters.num_nodes; }
GetNumberOfEdgesInFile()5674 int vtkExodusIIReader::GetNumberOfEdgesInFile() { return this->Metadata->ModelParameters.num_edge; }
GetNumberOfFacesInFile()5675 int vtkExodusIIReader::GetNumberOfFacesInFile() { return this->Metadata->ModelParameters.num_face; }
GetNumberOfElementsInFile()5676 int vtkExodusIIReader::GetNumberOfElementsInFile() { return this->Metadata->ModelParameters.num_elem; }
5677
GetNumberOfObjects(int objectType)5678 int vtkExodusIIReader::GetNumberOfObjects( int objectType )
5679 {
5680 return this->Metadata->GetNumberOfObjectsOfType( objectType );
5681 }
5682
GetObjectTypeFromName(const char * name)5683 int vtkExodusIIReader::GetObjectTypeFromName( const char* name )
5684 {
5685 vtkStdString tname( name );
5686 if ( tname == "edge" ) return EDGE_BLOCK;
5687 else if ( tname == "face" ) return FACE_BLOCK;
5688 else if ( tname == "element" ) return ELEM_BLOCK;
5689 else if ( tname == "node set" ) return NODE_SET;
5690 else if ( tname == "edge set" ) return EDGE_SET;
5691 else if ( tname == "face set" ) return FACE_SET;
5692 else if ( tname == "side set" ) return SIDE_SET;
5693 else if ( tname == "element set" ) return ELEM_SET;
5694 else if ( tname == "node map" ) return NODE_MAP;
5695 else if ( tname == "edge map" ) return EDGE_MAP;
5696 else if ( tname == "face map" ) return FACE_MAP;
5697 else if ( tname == "element map" ) return ELEM_MAP;
5698 else if ( tname == "grid" ) return GLOBAL;
5699 else if ( tname == "node" ) return NODAL;
5700 else if ( tname == "assembly" ) return ASSEMBLY;
5701 else if ( tname == "part" ) return PART;
5702 else if ( tname == "material" ) return MATERIAL;
5703 else if ( tname == "hierarchy" ) return HIERARCHY;
5704 else if ( tname == "cell" ) return GLOBAL_CONN;
5705 else if ( tname == "element block cell" ) return ELEM_BLOCK_ELEM_CONN;
5706 else if ( tname == "element block face" ) return ELEM_BLOCK_FACE_CONN;
5707 else if ( tname == "element block edge" ) return ELEM_BLOCK_EDGE_CONN;
5708 else if ( tname == "face block cell" ) return FACE_BLOCK_CONN;
5709 else if ( tname == "edge block cell" ) return EDGE_BLOCK_CONN;
5710 else if ( tname == "element set cell" ) return ELEM_SET_CONN;
5711 else if ( tname == "side set cell" ) return SIDE_SET_CONN;
5712 else if ( tname == "face set cell" ) return FACE_SET_CONN;
5713 else if ( tname == "edge set cell" ) return EDGE_SET_CONN;
5714 else if ( tname == "node set cell" ) return NODE_SET_CONN;
5715 else if ( tname == "nodal coordinates" ) return NODAL_COORDS;
5716 else if ( tname == "object id" ) return OBJECT_ID;
5717 else if ( tname == "implicit element id" ) return IMPLICIT_ELEMENT_ID;
5718 else if ( tname == "implicit node id" ) return IMPLICIT_NODE_ID;
5719 else if ( tname == "global element id" ) return GLOBAL_ELEMENT_ID;
5720 else if ( tname == "global node id" ) return GLOBAL_NODE_ID;
5721 else if ( tname == "element id" ) return ELEMENT_ID;
5722 else if ( tname == "node id" ) return NODE_ID;
5723 else if ( tname == "pointmap" ) return NODAL_SQUEEZEMAP;
5724 return -1;
5725 }
5726
GetObjectTypeName(int otyp)5727 const char* vtkExodusIIReader::GetObjectTypeName( int otyp )
5728 {
5729 switch ( otyp )
5730 {
5731 case EDGE_BLOCK: return "edge";
5732 case FACE_BLOCK: return "face";
5733 case ELEM_BLOCK: return "element";
5734 case NODE_SET: return "node set";
5735 case EDGE_SET: return "edge set";
5736 case FACE_SET: return "face set";
5737 case SIDE_SET: return "side set";
5738 case ELEM_SET: return "element set";
5739 case NODE_MAP: return "node map";
5740 case EDGE_MAP: return "edge map";
5741 case FACE_MAP: return "face map";
5742 case ELEM_MAP: return "element map";
5743 case GLOBAL: return "grid";
5744 case NODAL: return "node";
5745 case ASSEMBLY: return "assembly";
5746 case PART: return "part";
5747 case MATERIAL: return "material";
5748 case HIERARCHY: return "hierarchy";
5749 case GLOBAL_CONN: return "cell";
5750 case ELEM_BLOCK_ELEM_CONN: return "element block cell";
5751 case ELEM_BLOCK_FACE_CONN: return "element block face";
5752 case ELEM_BLOCK_EDGE_CONN: return "element block edge";
5753 case FACE_BLOCK_CONN: return "face block cell";
5754 case EDGE_BLOCK_CONN: return "edge block cell";
5755 case ELEM_SET_CONN: return "element set cell";
5756 case SIDE_SET_CONN: return "side set cell";
5757 case FACE_SET_CONN: return "face set cell";
5758 case EDGE_SET_CONN: return "edge set cell";
5759 case NODE_SET_CONN: return "node set cell";
5760 case NODAL_COORDS: return "nodal coordinates";
5761 case OBJECT_ID: return "object id";
5762 case IMPLICIT_ELEMENT_ID: return "implicit element id";
5763 case IMPLICIT_NODE_ID: return "implicit node id";
5764 case GLOBAL_ELEMENT_ID: return "global element id";
5765 case GLOBAL_NODE_ID: return "global node id";
5766 case ELEMENT_ID: return "element id";
5767 case NODE_ID: return "node id";
5768 case NODAL_SQUEEZEMAP: return "pointmap";
5769 }
5770 return nullptr;
5771 }
5772
GetNumberOfNodes()5773 int vtkExodusIIReader::GetNumberOfNodes() { return this->Metadata->GetNumberOfNodes(); }
5774
GetNumberOfEntriesInObject(int objectType,int objectIndex)5775 int vtkExodusIIReader::GetNumberOfEntriesInObject( int objectType, int objectIndex )
5776 {
5777 return this->Metadata->GetObjectSize( objectType, objectIndex );
5778 }
5779
GetObjectId(int objectType,int objectIndex)5780 int vtkExodusIIReader::GetObjectId( int objectType, int objectIndex )
5781 {
5782 return this->Metadata->GetObjectId( objectType, objectIndex );
5783 }
5784
GetObjectStatus(int objectType,int objectIndex)5785 int vtkExodusIIReader::GetObjectStatus( int objectType, int objectIndex )
5786 {
5787 return this->Metadata->GetObjectStatus( objectType, objectIndex );
5788 }
5789
SetObjectStatus(int objectType,int objectIndex,int status)5790 void vtkExodusIIReader::SetObjectStatus( int objectType, int objectIndex, int status )
5791 {
5792 this->Metadata->SetObjectStatus( objectType, objectIndex, status );
5793 }
5794
SetObjectStatus(int objectType,const char * objectName,int status)5795 void vtkExodusIIReader::SetObjectStatus( int objectType, const char* objectName, int status )
5796 {
5797 if(objectName && strlen(objectName)>0)
5798 {
5799 if(this->GetNumberOfObjects(objectType) == 0)
5800 {
5801 // The object status is being set before the meta data has been finalized
5802 // so cache this value for later and use as the initial value
5803 // If the number of objects really is zero then this doesn't do any harm.
5804 this->Metadata->SetInitialObjectStatus(objectType, objectName, status);
5805 return;
5806 }
5807 this->SetObjectStatus( objectType, this->GetObjectIndex( objectType, objectName ), status );
5808 }
5809 }
5810
GetObjectName(int objectType,int objectIndex)5811 const char* vtkExodusIIReader::GetObjectName( int objectType, int objectIndex )
5812 {
5813 return this->Metadata->GetObjectName( objectType, objectIndex );
5814 }
5815
GetObjectIndex(int objectType,const char * objectName)5816 int vtkExodusIIReader::GetObjectIndex( int objectType, const char* objectName )
5817 {
5818 if ( ! objectName )
5819 {
5820 vtkErrorMacro( "You must specify a non-nullptr name" );
5821 return -1;
5822 }
5823 int nObj = this->GetNumberOfObjects( objectType );
5824 if ( nObj == 0 )
5825 {
5826 vtkDebugMacro( "No objects of that type (" << objectType << ") to find index for given name " << objectName << "." );
5827 return -1;
5828 }
5829 vtkStdString objectRealName(objectName);
5830 size_t i = objectRealName.find(" Size: ");
5831 if(i!= vtkStdString::npos)
5832 {
5833 objectRealName.erase(i);
5834 }
5835 for ( int obj = 0; obj < nObj; ++obj )
5836 {
5837 const char* storedObjName = this->GetObjectName( objectType, obj );
5838 if(objectRealName == vtkStdString(storedObjName))
5839 {
5840 return obj;
5841 }
5842 }
5843 vtkDebugMacro( "No objects named \"" << objectName << "\" of the specified type (" << objectType << ")." );
5844 return -1;
5845 }
5846
GetObjectIndex(int objectType,int id)5847 int vtkExodusIIReader::GetObjectIndex( int objectType, int id )
5848 {
5849 int nObj = this->GetNumberOfObjects( objectType );
5850 if ( nObj == 0 )
5851 {
5852 vtkDebugMacro( "No objects of that type (" << objectType << ") to find index for given id " << id << "." );
5853 return -1;
5854 }
5855 for ( int obj = 0; obj < nObj; ++obj )
5856 {
5857 if ( this->GetObjectId( objectType, obj ) == id)
5858 {
5859 return obj;
5860 }
5861 }
5862 vtkDebugMacro( "No objects with id \"" << id << "\" of the specified type (" << objectType << ")." );
5863 return -1;
5864 }
5865
GetNumberOfObjectArrays(int objectType)5866 int vtkExodusIIReader::GetNumberOfObjectArrays( int objectType )
5867 {
5868 return this->Metadata->GetNumberOfObjectArraysOfType( objectType );
5869 }
5870
GetObjectArrayName(int objectType,int arrayIndex)5871 const char* vtkExodusIIReader::GetObjectArrayName( int objectType, int arrayIndex )
5872 {
5873 return this->Metadata->GetObjectArrayName( objectType, arrayIndex );
5874 }
5875
GetNumberOfObjectArrayComponents(int objectType,int arrayIndex)5876 int vtkExodusIIReader::GetNumberOfObjectArrayComponents( int objectType, int arrayIndex )
5877 {
5878 return this->Metadata->GetNumberOfObjectArrayComponents( objectType, arrayIndex );
5879 }
5880
GetObjectArrayStatus(int objectType,int arrayIndex)5881 int vtkExodusIIReader::GetObjectArrayStatus( int objectType, int arrayIndex )
5882 {
5883 return this->Metadata->GetObjectArrayStatus( objectType, arrayIndex );
5884 }
5885
SetObjectArrayStatus(int objectType,int arrayIndex,int status)5886 void vtkExodusIIReader::SetObjectArrayStatus( int objectType, int arrayIndex, int status )
5887 {
5888 this->Metadata->SetObjectArrayStatus( objectType, arrayIndex, status );
5889 }
5890
SetObjectArrayStatus(int objectType,const char * arrayName,int status)5891 void vtkExodusIIReader::SetObjectArrayStatus( int objectType, const char* arrayName, int status )
5892 {
5893 if(arrayName && strlen(arrayName)>0)
5894 {
5895 if(this->GetNumberOfObjectArrays( objectType ) == 0)
5896 {
5897 // The array status is being set before the meta data has been finalized
5898 // so cache this value for later and use as the initial value
5899 // If the number of arrays really is zero then this doesn't do any harm.
5900 this->Metadata->SetInitialObjectArrayStatus(objectType, arrayName, status);
5901 return;
5902 }
5903 this->SetObjectArrayStatus( objectType, this->GetObjectArrayIndex( objectType, arrayName ), status );
5904 }
5905 }
5906
GetNumberOfObjectAttributes(int objectType,int objectIndex)5907 int vtkExodusIIReader::GetNumberOfObjectAttributes( int objectType, int objectIndex )
5908 {
5909 return this->Metadata->GetNumberOfObjectAttributes( objectType, objectIndex );
5910 }
5911
GetObjectAttributeName(int objectType,int objectIndex,int attribIndex)5912 const char* vtkExodusIIReader::GetObjectAttributeName( int objectType, int objectIndex, int attribIndex )
5913 {
5914 return this->Metadata->GetObjectAttributeName( objectType, objectIndex, attribIndex );
5915 }
5916
GetObjectAttributeIndex(int objectType,int objectIndex,const char * attribName)5917 int vtkExodusIIReader::GetObjectAttributeIndex( int objectType, int objectIndex, const char* attribName )
5918 {
5919 return this->Metadata->GetObjectAttributeIndex( objectType, objectIndex, attribName );
5920 }
5921
GetObjectAttributeStatus(int objectType,int objectIndex,int attribIndex)5922 int vtkExodusIIReader::GetObjectAttributeStatus( int objectType, int objectIndex, int attribIndex )
5923 {
5924 return this->Metadata->GetObjectAttributeStatus( objectType, objectIndex, attribIndex );
5925 }
5926
SetObjectAttributeStatus(int objectType,int objectIndex,int attribIndex,int status)5927 void vtkExodusIIReader::SetObjectAttributeStatus( int objectType, int objectIndex, int attribIndex, int status )
5928 {
5929 this->Metadata->SetObjectAttributeStatus( objectType, objectIndex, attribIndex, status );
5930 }
5931
GetObjectArrayIndex(int objectType,const char * arrayName)5932 int vtkExodusIIReader::GetObjectArrayIndex( int objectType, const char* arrayName )
5933 {
5934 if ( ! arrayName )
5935 {
5936 vtkErrorMacro( "You must specify a non-nullptr name" );
5937 return -1;
5938 }
5939 int nObj = this->GetNumberOfObjectArrays( objectType );
5940 if ( nObj == 0 )
5941 {
5942 vtkDebugMacro( "No objects of that type (" << objectType << ") to find index for given array " << arrayName << "." );
5943 return -1;
5944 }
5945 for ( int obj = 0; obj < nObj; ++obj )
5946 {
5947 if ( !strcmp( arrayName, this->GetObjectArrayName( objectType, obj ) ) )
5948 {
5949 return obj;
5950 }
5951 }
5952 vtkDebugMacro( "No arrays named \"" << arrayName << "\" of the specified type (" << objectType << ")." );
5953 return -1;
5954 }
5955
GetTotalNumberOfNodes()5956 vtkIdType vtkExodusIIReader::GetTotalNumberOfNodes() { return this->Metadata->GetModelParams()->num_nodes; }
GetTotalNumberOfEdges()5957 vtkIdType vtkExodusIIReader::GetTotalNumberOfEdges() { return this->Metadata->GetModelParams()->num_edge; }
GetTotalNumberOfFaces()5958 vtkIdType vtkExodusIIReader::GetTotalNumberOfFaces() { return this->Metadata->GetModelParams()->num_face; }
GetTotalNumberOfElements()5959 vtkIdType vtkExodusIIReader::GetTotalNumberOfElements() { return this->Metadata->GetModelParams()->num_elem; }
5960
5961 // %---------------------------------------------------------------------------
GetNumberOfPartArrays()5962 int vtkExodusIIReader::GetNumberOfPartArrays()
5963 {
5964 return this->Metadata->GetNumberOfParts();
5965 }
5966
GetPartArrayName(int arrayIdx)5967 const char* vtkExodusIIReader::GetPartArrayName( int arrayIdx )
5968 {
5969 return this->Metadata->GetPartName(arrayIdx);
5970 }
5971
GetPartArrayID(const char * name)5972 int vtkExodusIIReader::GetPartArrayID( const char *name )
5973 {
5974 int numArrays = this->GetNumberOfPartArrays();
5975 for ( int i=0;i<numArrays;i++ )
5976 {
5977 if ( strcmp( name, this->GetPartArrayName( i ) ) == 0 )
5978 {
5979 return i;
5980 }
5981 }
5982 return -1;
5983 }
5984
GetPartBlockInfo(int arrayIdx)5985 const char* vtkExodusIIReader::GetPartBlockInfo( int arrayIdx )
5986 {
5987 return this->Metadata->GetPartBlockInfo(arrayIdx);
5988 }
5989
SetPartArrayStatus(int index,int flag)5990 void vtkExodusIIReader::SetPartArrayStatus( int index, int flag )
5991 {
5992 // Only modify if we are 'out of sync'
5993 if (this->Metadata->GetPartStatus(index) != flag)
5994 {
5995 this->Metadata->SetPartStatus(index, flag);
5996
5997 // Because which parts are on/off affects the
5998 // geometry we need to remake the mesh cache
5999 //this->RemakeDataCacheFlag = 1;
6000 this->Modified();
6001 }
6002 }
6003
SetPartArrayStatus(const char * name,int flag)6004 void vtkExodusIIReader::SetPartArrayStatus( const char* name, int flag )
6005 {
6006 // Only modify if we are 'out of sync'
6007 if (this->Metadata->GetPartStatus(name) != flag)
6008 {
6009 this->Metadata->SetPartStatus(name, flag);
6010
6011 // Because which parts are on/off affects the
6012 // geometry we need to remake the mesh cache
6013 //this->RemakeDataCacheFlag = 1;
6014 this->Modified();
6015 }
6016 }
6017
GetPartArrayStatus(int index)6018 int vtkExodusIIReader::GetPartArrayStatus( int index )
6019 {
6020 return this->Metadata->GetPartStatus(index);
6021 }
6022
GetPartArrayStatus(const char * part)6023 int vtkExodusIIReader::GetPartArrayStatus( const char* part )
6024 {
6025 return this->Metadata->GetPartStatus(part);
6026 }
6027
GetNumberOfMaterialArrays()6028 int vtkExodusIIReader::GetNumberOfMaterialArrays()
6029 {
6030 return this->Metadata->GetNumberOfMaterials();
6031 }
6032
GetMaterialArrayName(int arrayIdx)6033 const char* vtkExodusIIReader::GetMaterialArrayName( int arrayIdx )
6034 {
6035 return this->Metadata->GetMaterialName(arrayIdx);
6036 }
6037
GetMaterialArrayID(const char * matl)6038 int vtkExodusIIReader::GetMaterialArrayID( const char* matl )
6039 {
6040 (void)matl;
6041 return 0;
6042 }
6043
SetMaterialArrayStatus(int index,int flag)6044 void vtkExodusIIReader::SetMaterialArrayStatus( int index, int flag )
6045 {
6046 // Only modify if we are 'out of sync'
6047 if (this->Metadata->GetMaterialStatus(index) != flag)
6048 {
6049 this->Metadata->SetMaterialStatus(index, flag);
6050
6051 // Because which materials are on/off affects the
6052 // geometry we need to remake the mesh cache
6053 //this->RemakeDataCacheFlag = 1;
6054 this->Modified();
6055 }
6056 }
6057
SetMaterialArrayStatus(const char * matl,int flag)6058 void vtkExodusIIReader::SetMaterialArrayStatus( const char* matl, int flag )
6059 {
6060 // Only modify if we are 'out of sync'
6061 if (this->Metadata->GetMaterialStatus(matl) != flag)
6062 {
6063 this->Metadata->SetMaterialStatus(matl, flag);
6064
6065 // Because which materials are on/off affects the
6066 // geometry we need to remake the mesh cache
6067 //this->RemakeDataCacheFlag = 1;
6068 this->Modified();
6069 }
6070 }
6071
GetMaterialArrayStatus(int index)6072 int vtkExodusIIReader::GetMaterialArrayStatus( int index )
6073 {
6074 return this->Metadata->GetMaterialStatus(index);
6075 }
6076
GetMaterialArrayStatus(const char * matl)6077 int vtkExodusIIReader::GetMaterialArrayStatus( const char* matl )
6078 {
6079 return this->Metadata->GetMaterialStatus(matl);
6080 }
6081
GetNumberOfAssemblyArrays()6082 int vtkExodusIIReader::GetNumberOfAssemblyArrays()
6083 {
6084 return this->Metadata->GetNumberOfAssemblies();
6085 }
6086
GetAssemblyArrayName(int arrayIdx)6087 const char* vtkExodusIIReader::GetAssemblyArrayName( int arrayIdx )
6088 {
6089 return this->Metadata->GetAssemblyName(arrayIdx);
6090 }
6091
GetAssemblyArrayID(const char * name)6092 int vtkExodusIIReader::GetAssemblyArrayID( const char* name )
6093 {
6094 int numArrays = this->GetNumberOfAssemblyArrays();
6095 for ( int i=0;i<numArrays;i++ )
6096 {
6097 if ( strcmp( name, this->GetAssemblyArrayName( i ) ) == 0 )
6098 {
6099 return i;
6100 }
6101 }
6102 return -1;
6103 }
6104
6105
SetAssemblyArrayStatus(int index,int flag)6106 void vtkExodusIIReader::SetAssemblyArrayStatus(int index, int flag)
6107 {
6108 // Only modify if we are 'out of sync'
6109 if (this->Metadata->GetAssemblyStatus(index) != flag)
6110 {
6111 this->Metadata->SetAssemblyStatus(index, flag);
6112
6113 // Because which materials are on/off affects the
6114 // geometry we need to remake the mesh cache
6115 //this->RemakeDataCacheFlag = 1;
6116 this->Modified();
6117 }
6118 }
6119
SetAssemblyArrayStatus(const char * name,int flag)6120 void vtkExodusIIReader::SetAssemblyArrayStatus(const char* name, int flag)
6121 {
6122 // Only modify if we are 'out of sync'
6123 if (this->Metadata->GetAssemblyStatus(name) != flag)
6124 {
6125 this->Metadata->SetAssemblyStatus(name, flag);
6126
6127 // Because which materials are on/off affects the
6128 // geometry we need to remake the mesh cache
6129 //this->RemakeDataCacheFlag = 1;
6130 this->Modified();
6131 }
6132 }
6133
6134
GetAssemblyArrayStatus(int index)6135 int vtkExodusIIReader::GetAssemblyArrayStatus(int index)
6136 {
6137 return this->Metadata->GetAssemblyStatus(index);
6138 }
6139
GetAssemblyArrayStatus(const char * name)6140 int vtkExodusIIReader::GetAssemblyArrayStatus(const char* name)
6141 {
6142 return this->Metadata->GetAssemblyStatus(name);
6143 }
6144
GetNumberOfHierarchyArrays()6145 int vtkExodusIIReader::GetNumberOfHierarchyArrays()
6146 {
6147 //if (this->Metadata->Parser)
6148 // {
6149 // return this->Metadata->Parser->GetNumberOfHierarchyEntries();
6150 // }
6151 return 0;
6152 }
6153
6154
GetHierarchyArrayName(int vtkNotUsed (arrayIdx))6155 const char* vtkExodusIIReader::GetHierarchyArrayName(int vtkNotUsed(arrayIdx))
6156 {
6157 //if (this->Metadata->Parser)
6158 // {
6159 // this->Metadata->Parser->SetCurrentHierarchyEntry(arrayIdx);
6160 // return this->Metadata->Parser->GetCurrentHierarchyEntry();
6161 // }
6162 return "Should not see this";
6163 }
6164
SetHierarchyArrayStatus(int vtkNotUsed (index),int vtkNotUsed (flag))6165 void vtkExodusIIReader::SetHierarchyArrayStatus(int vtkNotUsed(index), int vtkNotUsed(flag))
6166 {
6167 //// Only modify if we are 'out of sync'
6168 ////if (this->GetHierarchyArrayStatus(index) != flag)
6169 //// {
6170 //if (this->Metadata->Parser)
6171 // {
6172 // std::vector<int> blocksIds = this->Metadata->Parser->GetBlocksForEntry(index);
6173 // for (std::vector<int>::size_type i=0;i<blocksIds.size();i++)
6174 // {
6175 // this->Metadata->SetObjectStatus(vtkExodusIIReader::ELEM_BLOCK,
6176 // this->GetObjectIndex(ELEM_BLOCK,blocksIds[i]),flag);
6177 // }
6178 //
6179 // // Because which materials are on/off affects the
6180 // // geometry we need to remake the mesh cache
6181 // //this->RemakeDataCacheFlag = 1;
6182 // this->Modified();
6183 // }
6184 }
6185
SetHierarchyArrayStatus(const char * vtkNotUsed (name),int vtkNotUsed (flag))6186 void vtkExodusIIReader::SetHierarchyArrayStatus(const char* vtkNotUsed(name), int vtkNotUsed(flag))
6187 {
6188 //// Only modify if we are 'out of sync'
6189 ////if (this->GetHierarchyArrayStatus(name) != flag)
6190 ////{
6191 //if (this->Metadata->Parser)
6192 // {
6193 // std::vector<int> blocksIds=this->Metadata->Parser->GetBlocksForEntry
6194 // (vtkStdString(name));
6195 // for (std::vector<int>::size_type i=0;i<blocksIds.size();i++)
6196 // {
6197 // //cout << "turning block " << blocks[i] << " " << flag << endl;
6198 // this->Metadata->SetObjectStatus(vtkExodusIIReader::ELEM_BLOCK,
6199 // this->GetObjectIndex(ELEM_BLOCK,blocksIds[i]),flag);
6200 // }
6201 //
6202 // // Because which materials are on/off affects the
6203 // // geometry we need to remake the mesh cache
6204 // //this->RemakeDataCacheFlag = 1;
6205 // this->Modified();
6206 // }
6207 }
6208
6209 //-----------------------------------------------------------------------------
GetHierarchyArrayStatus(int vtkNotUsed (index))6210 int vtkExodusIIReader::GetHierarchyArrayStatus(int vtkNotUsed(index))
6211 {
6212 //if (this->Metadata->Parser)
6213 // {
6214 // std::vector<int> blocksIds=this->Metadata->Parser->GetBlocksForEntry(index);
6215 // for (std::vector<int>::size_type i=0;i<blocksIds.size();i++)
6216 // {
6217 // if (this->Metadata->GetObjectStatus(vtkExodusIIReader::ELEM_BLOCK,
6218 // this->GetObjectIndex(ELEM_BLOCK,blocksIds[i]))==0)
6219 // return 0;
6220 // }
6221 // }
6222 return 1;
6223 }
6224
6225 //-----------------------------------------------------------------------------
GetHierarchyArrayStatus(const char * vtkNotUsed (name))6226 int vtkExodusIIReader::GetHierarchyArrayStatus(const char* vtkNotUsed(name))
6227 {
6228 //if (this->Metadata->Parser)
6229 // {
6230 // std::vector<int> blocksIds=this->Metadata->Parser->GetBlocksForEntry(name);
6231 // for (std::vector<int>::size_type i=0;i<blocksIds.size();i++)
6232 // {
6233 // if (this->Metadata->GetObjectStatus(vtkExodusIIReader::ELEM_BLOCK,
6234 // this->GetObjectIndex(ELEM_BLOCK,blocksIds[i]))==0)
6235 // return 0;
6236 // }
6237 // }
6238 return 1;
6239 }
6240
6241 //-----------------------------------------------------------------------------
GetSIL()6242 vtkGraph* vtkExodusIIReader::GetSIL()
6243 {
6244 return this->Metadata->GetSIL();
6245 }
6246
6247 //-----------------------------------------------------------------------------
SetDisplayType(int typ)6248 void vtkExodusIIReader::SetDisplayType( int typ )
6249 {
6250 if ( typ == this->DisplayType || typ < 0 || typ > 2 )
6251 return;
6252
6253 this->DisplayType = typ;
6254 this->Modified();
6255 }
6256
6257 //-----------------------------------------------------------------------------
IsValidVariable(const char * type,const char * name)6258 int vtkExodusIIReader::IsValidVariable( const char *type, const char *name )
6259 {
6260 return (this->GetVariableID( type, name ) >= 0);
6261 }
6262
6263 //-----------------------------------------------------------------------------
GetVariableID(const char * type,const char * name)6264 int vtkExodusIIReader::GetVariableID( const char *type, const char *name )
6265 {
6266 int otyp = this->GetObjectTypeFromName( type );
6267 if ( otyp < 0 )
6268 {
6269 return 0;
6270 }
6271 switch ( otyp )
6272 {
6273 case NODAL:
6274 case EDGE_BLOCK:
6275 case FACE_BLOCK:
6276 case ELEM_BLOCK:
6277 case NODE_SET:
6278 case EDGE_SET:
6279 case FACE_SET:
6280 case SIDE_SET:
6281 case ELEM_SET:
6282 return this->GetObjectArrayIndex( otyp, name );
6283 case ASSEMBLY:
6284 return this->GetAssemblyArrayID( name );
6285 case HIERARCHY:
6286 return -1; // FIXME: There is no this->GetHierarchyArrayID( name ) and it's not clear there should be.
6287 case MATERIAL:
6288 return this->GetMaterialArrayID( name );
6289 case PART:
6290 return this->GetPartArrayID( name );
6291 default:
6292 return -1;
6293 }
6294 }
6295
GetTimeSeriesData(int ID,const char * vName,const char * vType,vtkFloatArray * result)6296 int vtkExodusIIReader::GetTimeSeriesData( int ID, const char* vName, const char* vType, vtkFloatArray* result )
6297 {
6298 (void)ID;
6299 (void)vName;
6300 (void)vType;
6301 (void)result;
6302 return -1;
6303 }
6304
SetAllArrayStatus(int otyp,int status)6305 void vtkExodusIIReader::SetAllArrayStatus( int otyp, int status )
6306 {
6307 int numObj;
6308 int i;
6309 switch ( otyp )
6310 {
6311 case EDGE_BLOCK_CONN:
6312 case FACE_BLOCK_CONN:
6313 case ELEM_BLOCK_ELEM_CONN:
6314 case NODE_SET_CONN:
6315 case EDGE_SET_CONN:
6316 case FACE_SET_CONN:
6317 case SIDE_SET_CONN:
6318 case ELEM_SET_CONN:
6319 { // Convert the "connectivity" type into an "object" type:
6320 int ctypidx = this->Metadata->GetConnTypeIndexFromConnType(otyp);
6321 int otypidx = conn_obj_idx_cvt[ctypidx];
6322 otyp = obj_types[otypidx];
6323 // Now set the status
6324 numObj = this->GetNumberOfObjects( otyp );
6325 for ( i = 0; i < numObj; ++i )
6326 {
6327 this->SetObjectStatus( otyp, i, status );
6328 }
6329 }
6330 break;
6331 case NODAL:
6332 case GLOBAL:
6333 case EDGE_BLOCK:
6334 case FACE_BLOCK:
6335 case ELEM_BLOCK:
6336 case NODE_SET:
6337 case EDGE_SET:
6338 case FACE_SET:
6339 case SIDE_SET:
6340 case ELEM_SET:
6341 numObj = this->GetNumberOfObjectArrays( otyp );
6342 for ( i = 0; i < numObj; ++i )
6343 {
6344 this->SetObjectArrayStatus( otyp, i, status );
6345 }
6346 break;
6347 // ---------------------
6348 case ASSEMBLY:
6349 numObj = this->GetNumberOfAssemblyArrays();
6350 for ( i = 0; i < numObj; ++i )
6351 {
6352 this->SetAssemblyArrayStatus( i, status );
6353 }
6354 VTK_FALLTHROUGH;
6355 case PART:
6356 numObj = this->GetNumberOfPartArrays();
6357 for ( i = 0; i < numObj; ++i )
6358 {
6359 this->SetPartArrayStatus( i, status );
6360 }
6361 VTK_FALLTHROUGH;
6362 case MATERIAL:
6363 numObj = this->GetNumberOfMaterialArrays();
6364 for ( i = 0; i < numObj; ++i )
6365 {
6366 this->SetMaterialArrayStatus( i, status );
6367 }
6368 VTK_FALLTHROUGH;
6369 case HIERARCHY:
6370 numObj = this->GetNumberOfHierarchyArrays();
6371 for ( i = 0; i < numObj; ++i )
6372 {
6373 this->SetHierarchyArrayStatus( i, status );
6374 }
6375 break;
6376 default:
6377 break;
6378 }
6379 }
6380
Dump()6381 void vtkExodusIIReader::Dump()
6382 {
6383 vtkIndent indent;
6384 this->PrintSelf( cout, indent );
6385 }
6386
6387
FindXMLFile()6388 bool vtkExodusIIReader::FindXMLFile()
6389 {
6390 // If the XML filename exists and is newer than any existing parser (or there is no parser), reread XML file.
6391 if (
6392 ( this->Metadata->Parser && this->Metadata->Parser->GetMTime() < this->XMLFileNameMTime && this->XMLFileName ) ||
6393 ( ! Metadata->Parser ) )
6394 {
6395 if ( Metadata->Parser )
6396 {
6397 Metadata->Parser->Delete();
6398 Metadata->Parser = nullptr;
6399 }
6400
6401 if ( ! this->XMLFileName || ! vtksys::SystemTools::FileExists( this->XMLFileName ) )
6402 {
6403 if ( this->FileName )
6404 {
6405 // Catch the case where filename was non-nullptr but didn't exist.
6406 this->SetXMLFileName( nullptr );
6407 }
6408 }
6409 else
6410 {
6411 return true;
6412 }
6413 }
6414
6415 return false;
6416 }
6417
AdvertiseTimeSteps(vtkInformation * outInfo)6418 void vtkExodusIIReader::AdvertiseTimeSteps( vtkInformation* outInfo )
6419 {
6420 // This method is called in vtkExodusIIReader::RequestInformation() to update
6421 // information about timesteps. Since this gets called after this->Metadata
6422 // has processed the file meta-data it's a good place to update iVars that
6423 // reflect the meta-data read from the file about timesteps/mode shapes.
6424
6425 int nTimes = static_cast<int>(this->Metadata->Times.size());
6426 this->TimeStepRange[0] = 0;
6427 this->TimeStepRange[1] = (nTimes > 0)? (nTimes-1) : 0;
6428
6429 // Since modeshape range is 1 indexed.
6430 this->ModeShapesRange[0] = this->TimeStepRange[0] + 1;
6431 this->ModeShapesRange[1] = this->TimeStepRange[1] + 1;
6432
6433 if ( ! this->GetHasModeShapes() )
6434 {
6435 if (this->GetIgnoreFileTime())
6436 {
6437 std::vector<double> times(nTimes);
6438 for (size_t i = 0; i < times.size(); ++i)
6439 {
6440 times[i] = i;
6441 }
6442 double timeRange[2];
6443 timeRange[0] = 0;
6444 timeRange[1] = nTimes - 1;
6445 outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_STEPS(), ×[0], nTimes);
6446 outInfo->Set(vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2);
6447 }
6448 else
6449 {
6450 if ( nTimes )
6451 {
6452 double timeRange[2];
6453 timeRange[0] = this->Metadata->Times[0];
6454 timeRange[1] = this->Metadata->Times[nTimes - 1];
6455 outInfo->Set( vtkStreamingDemandDrivenPipeline::TIME_STEPS(), &this->Metadata->Times[0], nTimes );
6456 outInfo->Set( vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2 );
6457 }
6458 }
6459 }
6460 else if (this->GetAnimateModeShapes())
6461 {
6462 outInfo->Remove( vtkStreamingDemandDrivenPipeline::TIME_STEPS() );
6463 static double timeRange[] = { 0, 1 };
6464 outInfo->Set( vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2 );
6465 }
6466 else
6467 {
6468 outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
6469 outInfo->Remove(vtkStreamingDemandDrivenPipeline::TIME_RANGE());
6470 }
6471 }
6472
Reset()6473 void vtkExodusIIReader::Reset()
6474 {
6475 this->Metadata->Reset();
6476 this->Metadata->ResetSettings();
6477 }
6478
ResetSettings()6479 void vtkExodusIIReader::ResetSettings()
6480 {
6481 this->Metadata->ResetSettings();
6482 }
6483
SetCacheSize(double CacheSize)6484 void vtkExodusIIReader::SetCacheSize(double CacheSize)
6485 {
6486 this->Metadata->SetCacheSize(CacheSize);
6487 }
6488
GetCacheSize()6489 double vtkExodusIIReader::GetCacheSize()
6490 {
6491 return this->Metadata->GetCacheSize();
6492 }
6493
SetSqueezePoints(bool sp)6494 void vtkExodusIIReader::SetSqueezePoints(bool sp)
6495 {
6496 this->Metadata->SetSqueezePoints(sp ? 1 : 0);
6497 }
6498
GetSqueezePoints()6499 bool vtkExodusIIReader::GetSqueezePoints()
6500 {
6501 return this->Metadata->GetSqueezePoints() != 0;
6502 }
6503
ResetCache()6504 void vtkExodusIIReader::ResetCache()
6505 {
6506 this->Metadata->ResetCache();
6507 }
6508