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