1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPExodusIIReader.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 /*----------------------------------------------------------------------------
17 Copyright (c) Sandia Corporation
18 See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
19 ----------------------------------------------------------------------------*/
20
21 #include "vtkPExodusIIReader.h"
22
23 #include "vtkAppendCompositeDataLeaves.h"
24 #include "vtkCellData.h"
25 #include "vtkCommand.h"
26 #include "vtkDoubleArray.h"
27 #include "vtkExodusIIReaderPrivate.h"
28 #include "vtkFloatArray.h"
29 #include "vtkInformation.h"
30 #include "vtkInformationVector.h"
31 #include "vtkIntArray.h"
32 #include "vtkPointData.h"
33 #include "vtkMultiBlockDataSet.h"
34 #include "vtkMultiProcessController.h"
35 #include "vtkObjectFactory.h"
36 #include "vtkSmartPointer.h"
37 #include "vtkStreamingDemandDrivenPipeline.h"
38 #include "vtkUnstructuredGrid.h"
39
40 #include "vtk_netcdf.h"
41 #include "vtk_exodusII.h"
42
43 #include "vtksys/SystemTools.hxx"
44
45 #include <vector>
46
47 #include <vtksys/RegularExpression.hxx>
48
49 #include <cctype>
50
51 #undef DBG_PEXOIIRDR
52 #define vtkPExodusIIReaderMAXPATHLEN 2048
53
54 static const int objTypes[] = {
55 vtkExodusIIReader::EDGE_BLOCK,
56 vtkExodusIIReader::FACE_BLOCK,
57 vtkExodusIIReader::ELEM_BLOCK,
58 vtkExodusIIReader::NODE_SET,
59 vtkExodusIIReader::EDGE_SET,
60 vtkExodusIIReader::FACE_SET,
61 vtkExodusIIReader::SIDE_SET,
62 vtkExodusIIReader::ELEM_SET,
63 vtkExodusIIReader::NODE_MAP,
64 vtkExodusIIReader::EDGE_MAP,
65 vtkExodusIIReader::FACE_MAP,
66 vtkExodusIIReader::ELEM_MAP
67 };
68 static const int numObjTypes = sizeof(objTypes)/sizeof(objTypes[0]);
69
70 static const int objResultTypes[] = {
71 vtkExodusIIReader::NODAL,
72 vtkExodusIIReader::EDGE_BLOCK,
73 vtkExodusIIReader::FACE_BLOCK,
74 vtkExodusIIReader::ELEM_BLOCK,
75 vtkExodusIIReader::NODE_SET,
76 vtkExodusIIReader::EDGE_SET,
77 vtkExodusIIReader::FACE_SET,
78 vtkExodusIIReader::SIDE_SET,
79 vtkExodusIIReader::ELEM_SET,
80 vtkExodusIIReader::GLOBAL
81 };
82 static const int numObjResultTypes = sizeof(objResultTypes)/sizeof(objResultTypes[0]);
83
84 static const int objAttribTypes[] = {
85 vtkExodusIIReader::EDGE_BLOCK,
86 vtkExodusIIReader::FACE_BLOCK,
87 vtkExodusIIReader::ELEM_BLOCK
88 };
89 static const int numObjAttribTypes = sizeof(objAttribTypes)/sizeof(objAttribTypes[0]);
90
91
92 vtkStandardNewMacro(vtkPExodusIIReader);
93
94 class vtkPExodusIIReaderUpdateProgress : public vtkCommand
95 {
96 public:
vtkTypeMacro(vtkPExodusIIReaderUpdateProgress,vtkCommand)97 vtkTypeMacro(vtkPExodusIIReaderUpdateProgress, vtkCommand)
98 static vtkPExodusIIReaderUpdateProgress* New()
99 {
100 return new vtkPExodusIIReaderUpdateProgress;
101 }
SetReader(vtkPExodusIIReader * r)102 void SetReader(vtkPExodusIIReader* r)
103 {
104 Reader = r;
105 }
SetIndex(int i)106 void SetIndex(int i)
107 {
108 Index = i;
109 }
110 protected:
111
vtkPExodusIIReaderUpdateProgress()112 vtkPExodusIIReaderUpdateProgress()
113 {
114 Reader = nullptr;
115 Index = 0;
116 }
~vtkPExodusIIReaderUpdateProgress()117 ~vtkPExodusIIReaderUpdateProgress() override{}
118
Execute(vtkObject *,unsigned long event,void * callData)119 void Execute(vtkObject*, unsigned long event, void* callData) override
120 {
121 if(event == vtkCommand::ProgressEvent)
122 {
123 double num = Reader->GetNumberOfFileNames();
124 if (num <= 1)
125 {
126 num = Reader->GetNumberOfFiles();
127 }
128 double* progress = static_cast<double*>(callData);
129 double newProgress = *progress/num + Index/num;
130 Reader->UpdateProgress(newProgress);
131 }
132 }
133
134 vtkPExodusIIReader* Reader;
135 int Index;
136 };
137
138
139 //----------------------------------------------------------------------------
140 // Description:
141 // Instantiate object with nullptr filename.
vtkPExodusIIReader()142 vtkPExodusIIReader::vtkPExodusIIReader()
143 {
144 this->ProcRank = 0;
145 this->ProcSize = 1;
146 // NB. SetController will initialize ProcSize and ProcRank
147 this->Controller = 0;
148 this->SetController( vtkMultiProcessController::GetGlobalController() );
149 this->FilePattern = 0;
150 this->CurrentFilePattern = 0;
151 this->FilePrefix = 0;
152 this->CurrentFilePrefix = 0;
153 this->FileRange[0] = -1;
154 this->FileRange[1] = -1;
155 this->CurrentFileRange[0] = 0;
156 this->CurrentFileRange[1] = 0;
157 this->NumberOfFiles = 1;
158 this->FileNames = nullptr;
159 this->NumberOfFileNames = 0;
160 this->MultiFileName = new char[vtkPExodusIIReaderMAXPATHLEN];
161 this->XMLFileName=nullptr;
162 this->LastCommonTimeStep = -1;
163 this->VariableCacheSize = 100;
164 }
165
166 //----------------------------------------------------------------------------
~vtkPExodusIIReader()167 vtkPExodusIIReader::~vtkPExodusIIReader()
168 {
169 this->SetController( 0 );
170 this->SetFilePattern( 0 );
171 this->SetFilePrefix( 0 );
172
173 // If we've allocated filenames then delete them
174 if ( this->FileNames )
175 {
176 for (int i=0; i<this->NumberOfFileNames; i++)
177 {
178 delete [] this->FileNames[i];
179 }
180 delete [] this->FileNames;
181 }
182
183 // Delete all the readers we may have
184 std::vector<vtkExodusIIReader*>::iterator it;
185 for ( it = this->ReaderList.begin(); it != this->ReaderList.end(); ++ it )
186 {
187 (*it)->Delete();
188 }
189
190 if ( this->CurrentFilePrefix )
191 {
192 delete [] this->CurrentFilePrefix;
193 delete [] this->CurrentFilePattern;
194 }
195
196 delete [] this->MultiFileName;
197 }
198
199 //----------------------------------------------------------------------------
SetController(vtkMultiProcessController * c)200 void vtkPExodusIIReader::SetController( vtkMultiProcessController* c )
201 {
202 if ( this->Controller == c )
203 {
204 return;
205 }
206
207 this->Modified();
208
209 if ( this->Controller )
210 {
211 this->Controller->UnRegister( this );
212 }
213
214 this->Controller = c;
215
216 if ( this->Controller )
217 {
218 this->Controller->Register( this );
219 this->ProcRank = this->Controller->GetLocalProcessId();
220 this->ProcSize = this->Controller->GetNumberOfProcesses();
221 }
222
223 if ( ! this->Controller || this->ProcSize <= 0 )
224 {
225 this->ProcRank = 0;
226 this->ProcSize = 1;
227 }
228 }
229
230 //----------------------------------------------------------------------------
RequestInformation(vtkInformation * request,vtkInformationVector ** inputVector,vtkInformationVector * outputVector)231 int vtkPExodusIIReader::RequestInformation(
232 vtkInformation* request,
233 vtkInformationVector** inputVector,
234 vtkInformationVector* outputVector )
235 {
236 vtkInformation* outInfo = outputVector->GetInformationObject( 0 );
237 outInfo->Set(
238 CAN_HANDLE_PIECE_REQUEST(), 1);
239
240 int requestInformationRetVal = 0;
241 if ( this->ProcRank == 0 )
242 {
243 bool newName = this->GetMetadataMTime() < this->FileNameMTime;
244 bool newPattern =
245 (
246 ( this->FilePattern &&
247 ( ! this->CurrentFilePattern ||
248 ! vtksys::SystemTools::ComparePath(
249 this->FilePattern, this->CurrentFilePattern ) ||
250 ( ( this->FileRange[0] != this->CurrentFileRange[0] ) ||
251 ( this->FileRange[1] != this->CurrentFileRange[1] ) ) ) ) ||
252 ( this->FilePrefix &&
253 ! vtksys::SystemTools::ComparePath(
254 this->FilePrefix, this->CurrentFilePrefix ) )
255 );
256
257 // setting filename for the first time builds the prefix/pattern
258 // if one clears the prefix/pattern, but the filename stays the same,
259 // we should rebuild the prefix/pattern
260 bool rebuildPattern =
261 newPattern && this->FilePattern[0] == '\0' && this->FilePrefix[0] == '\0';
262
263 bool sanity = ( ( this->FilePattern && this->FilePrefix ) || this->FileName );
264
265 if ( ! sanity )
266 {
267 vtkErrorMacro( << "Must SetFilePattern AND SetFilePrefix, or SetFileName(s)" );
268 this->Broadcast( this->Controller );
269 return 0;
270 }
271
272 if ( newPattern && ! rebuildPattern )
273 {
274 size_t nmSize = strlen( this->FilePattern ) + strlen( this->FilePrefix ) + 20;
275 char* nm = new char[nmSize];
276 snprintf( nm, nmSize, this->FilePattern, this->FilePrefix, this->FileRange[0] );
277 delete [] this->FileName;
278 this->FileName = nm;
279 }
280 else if ( newName || rebuildPattern )
281 {
282 if ( this->NumberOfFileNames == 1 )
283 {
284 // A singleton file may actually be a hint to look for
285 // a series of files with the same base name. Must compute
286 // this now for ParaView.
287
288 this->DeterminePattern( this->FileNames[0] );
289 }
290 }
291
292 int numFiles = this->NumberOfFileNames;
293 if ( numFiles <= 1 )
294 {
295 numFiles = this->NumberOfFiles;
296 }
297
298 // Go through the filenames and see if any of them actually have data
299 // in them. It's possible that some of them don't and if they don't
300 // we won't have the proper information generated.
301 int reader_idx=0;
302 for ( int fileIndex = 0; fileIndex < numFiles; ++fileIndex, ++reader_idx )
303 {
304 if ( this->NumberOfFileNames > 1 )
305 {
306 strcpy( this->MultiFileName, this->FileNames[fileIndex] );
307 if ( this->GetGenerateFileIdArray() )
308 {
309 vtkPExodusIIReader::DetermineFileId( this->FileNames[fileIndex] );
310 }
311 }
312 else if ( this->FilePattern )
313 {
314 snprintf( this->MultiFileName, vtkPExodusIIReaderMAXPATHLEN, this->FilePattern, this->FilePrefix, fileIndex );
315 }
316 char* nm = new char[strlen( this->MultiFileName )+1];
317 strcpy(nm, this->MultiFileName);
318 delete [] this->FileName;
319 this->FileName = nm;
320 nm = nullptr;
321
322 // Read in info based on this->FileName
323 requestInformationRetVal = this->Superclass::RequestInformation( request, inputVector, outputVector );
324
325 if ( this->Metadata->ArrayInfo.size() )
326 {
327 // We have a file with actual data in it
328 break;
329 }
330 } // loop over file names
331 }
332 this->Controller->Broadcast( &requestInformationRetVal, 1, 0);
333 if (!requestInformationRetVal)
334 {
335 return 0;
336 }
337
338 if ( this->ProcSize > 1 )
339 {
340 this->Broadcast( this->Controller );
341 if ( this->ProcRank )
342 {
343 // The rank 0 node's RequestInformation annotates the output with the available
344 // time steps. Now that we've received time steps, advertise them on other procs.
345 this->AdvertiseTimeSteps( outInfo );
346 }
347 }
348
349 // Check whether we have been given a certain timestep to stop at. If so,
350 // override the output time keys with the actual range that ALL readers can read.
351 // If files are still being written to, some files might be on different timesteps
352 // than others.
353 if ( (this->LastCommonTimeStep >= 0) && !this->GetHasModeShapes() )
354 {
355 double* times = outInfo->Get( vtkStreamingDemandDrivenPipeline::TIME_STEPS() );
356 int numTimes = outInfo->Length( vtkStreamingDemandDrivenPipeline::TIME_STEPS() );
357 numTimes = this->LastCommonTimeStep + 1 < numTimes ? this->LastCommonTimeStep + 1 : numTimes;
358 std::vector<double> commonTimes;
359 commonTimes.insert( commonTimes.begin(), times, times + numTimes );
360 double timeRange[2];
361 timeRange[1] = commonTimes[numTimes - 1];
362 timeRange[0] = commonTimes[0];
363
364 outInfo->Set( vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2 );
365 outInfo->Set( vtkStreamingDemandDrivenPipeline::TIME_STEPS(), &commonTimes[0], numTimes );
366 }
367
368 if ( this->CurrentFilePrefix )
369 {
370 delete [] this->CurrentFilePrefix;
371 this->CurrentFilePrefix = nullptr;
372 delete [] this->CurrentFilePattern;
373 this->CurrentFilePattern = nullptr;
374 this->CurrentFileRange[0] = 0;
375 this->CurrentFileRange[1] = 0;
376 }
377
378 if ( this->FilePrefix )
379 {
380 this->CurrentFilePrefix = vtksys::SystemTools::DuplicateString( this->FilePrefix );
381 this->CurrentFilePattern = vtksys::SystemTools::DuplicateString( this->FilePattern );
382 this->CurrentFileRange[0] = this->FileRange[0];
383 this->CurrentFileRange[1] = this->FileRange[1];
384 }
385
386 return 1;
387 }
388
389
390 //----------------------------------------------------------------------------
RequestData(vtkInformation * vtkNotUsed (request),vtkInformationVector ** vtkNotUsed (inputVector),vtkInformationVector * outputVector)391 int vtkPExodusIIReader::RequestData(
392 vtkInformation* vtkNotUsed(request),
393 vtkInformationVector** vtkNotUsed(inputVector),
394 vtkInformationVector* outputVector )
395 {
396 int fileIndex;
397 int processNumber;
398 int numProcessors;
399 int min, max, idx;
400 int reader_idx;
401
402 vtkInformation* outInfo = outputVector->GetInformationObject( 0 );
403 // get the output
404 vtkMultiBlockDataSet* output = vtkMultiBlockDataSet::SafeDownCast(
405 outInfo->Get( vtkDataObject::DATA_OBJECT() ) );
406
407 // The whole notion of pieces for this reader is really
408 // just a division of files between processors
409 processNumber =
410 outInfo->Get( vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER() );
411 numProcessors =
412 outInfo->Get( vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES() );
413
414 int numFiles = this->NumberOfFileNames;
415 int start = 0;
416
417 if ( numFiles <= 1 )
418 {
419 start = this->FileRange[0]; // use prefix/pattern/range
420 numFiles = this->NumberOfFiles;
421 }
422
423
424 // Someone has requested a file that is above the number
425 // of pieces I have. That may have been caused by having
426 // more processors than files. So I'm going to create an
427 // empty unstructured grid that contains all the meta
428 // information but has 0 cells
429 if ( processNumber >= numFiles )
430 {
431 #ifdef DBG_PEXOIIRDR
432 vtkWarningMacro("Creating empty grid for processor: " << processNumber);
433 #endif
434 this->Metadata->SetUpEmptyGrid( output );
435 return 1;
436 }
437
438 // Divide the files evenly between processors
439 int num_files_per_process = numFiles / numProcessors;
440
441 // This if/else logic is for when you don't have a nice even division of files
442 // Each process computes which sequence of files it needs to read in
443 int left_over_files = numFiles - (num_files_per_process*numProcessors);
444 if ( processNumber < left_over_files )
445 {
446 min = (num_files_per_process+1) * processNumber + start;
447 max = min + (num_files_per_process+1) - 1;
448 }
449 else
450 {
451 min = num_files_per_process * processNumber + left_over_files + start;
452 max = min + num_files_per_process - 1;
453 }
454 #ifdef DBG_PEXOIIRDR
455 vtkWarningMacro("Processor: " << processNumber << " reading files: " << min <<" " <<max);
456 #endif
457
458 #ifdef DBG_PEXOIIRDR
459 vtkWarningMacro("Parallel read for processor: " << processNumber);
460 #endif
461
462 // We are going to read in the files one by one and then
463 // append them together. So now we make sure that we have
464 // the correct number of serial exodus readers and we create
465 // our append object that puts the 'pieces' together
466 unsigned int numMyFiles = max - min + 1;
467
468 vtkSmartPointer<vtkAppendCompositeDataLeaves> append =
469 vtkSmartPointer<vtkAppendCompositeDataLeaves>::New();
470 append->AppendFieldDataOn();
471
472 /*
473 if ( this->ExodusModelMetadata )
474 {
475 this->NewExodusModel();
476 }
477 */
478
479 if ( this->ReaderList.size() < numMyFiles )
480 {
481 for ( reader_idx = static_cast<int>( this->ReaderList.size() ); reader_idx < static_cast<int>(numMyFiles); ++reader_idx )
482 {
483 vtkExodusIIReader* er = vtkExodusIIReader::New();
484 vtkPExodusIIReaderUpdateProgress* progress = vtkPExodusIIReaderUpdateProgress::New();
485 progress->SetReader( this );
486 progress->SetIndex( reader_idx );
487 er->AddObserver( vtkCommand::ProgressEvent, progress );
488 progress->Delete();
489
490 this->ReaderList.push_back( er );
491 }
492 }
493 else if ( this->ReaderList.size() > numMyFiles )
494 {
495 for ( reader_idx = static_cast<int>( this->ReaderList.size() ) - 1; reader_idx >= static_cast<int>(numMyFiles); --reader_idx )
496 {
497 this->ReaderList[reader_idx]->Delete();
498 ReaderList.pop_back();
499 }
500 }
501
502 // If this is the first execution, we need to initialize the arrays
503 // that store the number of points/cells output by each reader
504 if(this->NumberOfCellsPerFile.size()==0)
505 {
506 this->NumberOfCellsPerFile.resize(max-min+1,0);
507 }
508 if(this->NumberOfPointsPerFile.size()==0)
509 {
510 this->NumberOfPointsPerFile.resize(max-min+1,0);
511 }
512
513 #ifdef DBG_PEXOIIRDR
514 cout << "\n\n ************************************* Parallel master reader dump\n";
515 this->Dump();
516 #endif // DBG_PEXOIIRDR
517
518 //setup the cache size for each reader
519 double fractionalCacheSize = 0;
520 if (this->VariableCacheSize > 0 )
521 {
522 fractionalCacheSize = this->VariableCacheSize / static_cast<int>( this->ReaderList.size() );
523 }
524
525 // This constructs the filenames
526 for ( fileIndex = min, reader_idx=0; fileIndex <= max; ++fileIndex, ++reader_idx )
527 {
528 int fileId = -1;
529 if ( this->NumberOfFileNames > 1 )
530 {
531 strcpy( this->MultiFileName, this->FileNames[fileIndex] );
532 if ( this->GetGenerateFileIdArray() )
533 {
534 fileId = vtkPExodusIIReader::DetermineFileId( this->FileNames[fileIndex] );
535 }
536 }
537 else if ( this->FilePattern )
538 {
539 snprintf( this->MultiFileName, vtkPExodusIIReaderMAXPATHLEN, this->FilePattern, this->FilePrefix, fileIndex );
540 if ( this->GetGenerateFileIdArray() )
541 {
542 fileId = fileIndex;
543 }
544 }
545 else
546 {
547 vtkErrorMacro("Some weird problem with filename/filepattern");
548 return 0;
549 }
550
551 if ( outInfo->Has( vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP() ) )
552 { // Get the requested time step. We only support requests of a single time step in this reader right now
553 double requestedTimeStep = outInfo->Get( vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEP() );
554
555 // Save the time value in the output data information.
556 int length = outInfo->Length( vtkStreamingDemandDrivenPipeline::TIME_STEPS() );
557 double* steps = outInfo->Get( vtkStreamingDemandDrivenPipeline::TIME_STEPS() );
558
559 if ( ! this->GetHasModeShapes() )
560 {
561 int cnt = 0;
562 int closestStep = 0;
563 double minDist = -1;
564 for ( cnt = 0; cnt < length; ++ cnt )
565 {
566 double tdist =
567 ( steps[cnt] - requestedTimeStep > requestedTimeStep - steps[cnt] ) ?
568 steps[cnt] - requestedTimeStep : requestedTimeStep - steps[cnt];
569 if ( minDist < 0 || tdist < minDist )
570 {
571 minDist = tdist;
572 closestStep = cnt;
573 }
574 }
575 this->TimeStep = closestStep;
576 this->ReaderList[reader_idx]->SetTimeStep( this->TimeStep );
577 output->GetInformation()->Set( vtkDataObject::DATA_TIME_STEP(), steps[this->TimeStep] );
578 }
579 else
580 {
581 // Let the metadata know the time value so that the
582 // Metadata->RequestData call below will generate the animated mode
583 // shape properly.
584
585 // Don't use this->SetModeShapeTime because that will cause Modified
586 // to be called.
587 //this->SetModeShapeTime( requestedTimeStep );
588 double phase = requestedTimeStep - floor(requestedTimeStep);
589 this->Metadata->ModeShapeTime = phase;
590
591 this->ReaderList[reader_idx]->SetTimeStep( this->TimeStep );
592 this->ReaderList[reader_idx]->SetModeShapeTime( requestedTimeStep );
593 output->GetInformation()->Set( vtkDataObject::DATA_TIME_STEP(), requestedTimeStep );
594 //output->GetInformation()->Remove( vtkDataObject::DATA_TIME_STEP() );
595 }
596 }
597 else
598 {
599 this->ReaderList[reader_idx]->SetTimeStep( this->TimeStep );
600 }
601
602 this->ReaderList[reader_idx]->SetGenerateObjectIdCellArray( this->GetGenerateObjectIdCellArray() );
603 this->ReaderList[reader_idx]->SetGenerateGlobalElementIdArray( this->GetGenerateGlobalElementIdArray() );
604 this->ReaderList[reader_idx]->SetGenerateGlobalNodeIdArray( this->GetGenerateGlobalNodeIdArray() );
605 this->ReaderList[reader_idx]->SetGenerateImplicitElementIdArray( this->GetGenerateImplicitElementIdArray() );
606 this->ReaderList[reader_idx]->SetGenerateImplicitNodeIdArray( this->GetGenerateImplicitNodeIdArray() );
607 this->ReaderList[reader_idx]->SetGenerateFileIdArray( this->GetGenerateFileIdArray() );
608 this->ReaderList[reader_idx]->SetFileId( fileId );
609 this->ReaderList[reader_idx]->SetApplyDisplacements( this->GetApplyDisplacements() );
610 this->ReaderList[reader_idx]->SetDisplacementMagnitude( this->GetDisplacementMagnitude() );
611 this->ReaderList[reader_idx]->SetHasModeShapes( this->GetHasModeShapes() );
612 this->ReaderList[reader_idx]->SetAnimateModeShapes( this->GetAnimateModeShapes() );
613
614 //this->ReaderList[reader_idx]->SetExodusModelMetadata( this->ExodusModelMetadata );
615 // For now, this *must* come last before the UpdateInformation() call because its MTime is compared to the metadata's MTime,
616 // which is modified by the calls above.
617 this->ReaderList[reader_idx]->SetFileName( this->MultiFileName );
618 this->ReaderList[reader_idx]->SetXMLFileName( this->XMLFileName );
619 //this->ReaderList[reader_idx]->PackExodusModelOntoOutputOff();
620
621 // BUG #15632: Pass time information from first file to all others.
622 if (reader_idx > 1)
623 {
624 this->ReaderList[reader_idx]->Metadata->SetTimesOverrides(
625 this->ReaderList[0]->Metadata->Times);
626 }
627
628 this->ReaderList[reader_idx]->UpdateInformation();
629 #ifdef DBG_PEXOIIRDR
630 cout << "\n\n ************************************* Reader " << reader_idx << " dump\n";
631 this->ReaderList[reader_idx]->Dump();
632 #endif // DBG_PEXOIIRDR
633
634 int typ;
635 for ( typ = 0; typ < numObjTypes; ++typ )
636 {
637 int nObj = this->ReaderList[reader_idx]->GetNumberOfObjects( objTypes[typ] );
638 for ( idx = 0; idx < nObj; ++idx )
639 {
640 this->ReaderList[reader_idx]->SetObjectStatus( objTypes[typ], idx, this->GetObjectStatus( objTypes[typ], idx ) );
641 }
642 }
643
644 for ( typ = 0; typ < numObjAttribTypes; ++typ )
645 {
646 int nObj = this->ReaderList[reader_idx]->GetNumberOfObjects( objAttribTypes[typ] );
647 for ( idx = 0; idx < nObj; ++idx )
648 {
649 int nObjAtt = this->GetNumberOfObjectAttributes( objAttribTypes[typ], idx );
650 for ( int aidx = 0; aidx < nObjAtt; ++aidx )
651 {
652 this->ReaderList[reader_idx]->SetObjectAttributeStatus( objAttribTypes[typ], idx, aidx,
653 this->GetObjectAttributeStatus( objAttribTypes[typ], idx, aidx ) );
654 }
655 }
656 }
657
658 for ( typ = 0; typ < numObjResultTypes; ++typ )
659 {
660 int nObjArr = this->GetNumberOfObjectArrays( objResultTypes[typ] );
661 for ( idx = 0; idx < nObjArr; ++idx )
662 {
663 this->ReaderList[reader_idx]->SetObjectArrayStatus(
664 objResultTypes[typ], idx, this->GetObjectArrayStatus( objResultTypes[typ], idx ) );
665 }
666 }
667
668 //set this reader to use the full amount of the cache
669 this->ReaderList[reader_idx]->SetCacheSize(this->VariableCacheSize);
670
671 //call the reader
672 this->ReaderList[reader_idx]->Update();
673
674 //set the reader back to the fractional amount
675 this->ReaderList[reader_idx]->SetCacheSize(fractionalCacheSize);
676
677 #if 0
678 vtkCompositeDataSet* subgrid = this->ReaderList[reader_idx]->GetOutput();
679 //subgrid->ShallowCopy( this->ReaderList[reader_idx]->GetOutput() );
680
681 int ncells = subgrid->GetNumberOfCells();
682
683 if ( ( ncells > 0 ) && this->Metadata->GetGenerateFileIdArray() )
684 {
685 vtkIntArray* ia = vtkIntArray::New();
686 ia->SetNumberOfValues(ncells);
687 for ( idx = 0; idx < ncells; ++ idx )
688 {
689 ia->SetValue( idx, fileId );
690 }
691 ia->SetName( "vtkFileId" );
692 subgrid->GetCellData()->AddArray( ia );
693 ia->Delete();
694 }
695
696 // Don't append if you don't have any cells
697 if ( ncells != 0 )
698 {
699 if ( this->ExodusModelMetadata )
700 {
701 vtkExodusModel* em = this->ReaderList[reader_idx]->GetExodusModel();
702 if ( em )
703 {
704 this->ExodusModel->MergeExodusModel( em );
705 }
706 }
707
708 totalCells += ncells;
709 totalPoints += subgrid->GetNumberOfPoints();
710 this->NumberOfCellsPerFile[reader_idx] = ncells;
711 this->NumberOfPointsPerFile[reader_idx] = subgrid->GetNumberOfPoints();
712
713 append->AddInput( subgrid );
714 subgrid->Delete();
715 }
716 #else // 0
717 append->AddInputConnection( this->ReaderList[reader_idx]->GetOutputPort() );
718 #endif // 0
719 }
720
721 // Append complains/barfs if you update it without any inputs
722 if (append->GetNumberOfInputConnections(0) != 0)
723 {
724 append->Update();
725 output->ShallowCopy( append->GetOutput() );
726 }
727
728 // I've copied append's output to the 'output' so delete append
729 append = nullptr;
730
731 #if 0 // FIXME: Need multiblock version... or not?
732 if ( this->PackExodusModelOntoOutput )
733 {
734 // The metadata is written to field arrays and attached
735 // to the output unstructured grid.
736 if ( this->ExodusModel )
737 {
738 vtkModelMetadata::RemoveMetadata( output );
739 this->ExodusModel->GetModelMetadata()->Pack( output );
740 }
741 }
742 #endif // 0
743
744 return 1;
745 }
746
747 //----------------------------------------------------------------------------
SetFileRange(int min,int max)748 void vtkPExodusIIReader::SetFileRange(int min, int max)
749 {
750 if ( min == this->FileRange[0] && max == this->FileRange[1] )
751 {
752 return;
753 }
754 this->FileRange[0] = min;
755 this->FileRange[1] = max;
756 this->NumberOfFiles = max-min+1;
757 this->Modified();
758 }
759 //----------------------------------------------------------------------------
SetFileName(const char * name)760 void vtkPExodusIIReader::SetFileName(const char *name)
761 {
762 this->SetFileNames( 1, &name );
763 }
764
SetFileNames(int nfiles,const char ** names)765 void vtkPExodusIIReader::SetFileNames( int nfiles, const char** names )
766 {
767 // If I have an old list of filename delete them
768 if ( this->FileNames )
769 {
770 for ( int i = 0; i < this->NumberOfFileNames; ++ i )
771 {
772 delete [] this->FileNames[i];
773 }
774 delete [] this->FileNames;
775 this->FileNames = nullptr;
776 }
777
778 // Set the number of files
779 this->NumberOfFileNames = nfiles;
780
781 // Allocate memory for new filenames
782 this->FileNames = new char*[this->NumberOfFileNames];
783
784 // Copy filenames
785 for (int i = 0; i < nfiles; ++ i )
786 {
787 this->FileNames[i] = vtksys::SystemTools::DuplicateString( names[i] );
788 }
789
790 this->Superclass::SetFileName( names[0] );
791 }
792
793 //----------------------------------------------------------------------------
DetermineFileId(const char * file)794 int vtkPExodusIIReader::DetermineFileId( const char* file )
795 {
796 // Assume the file number is the last digits found in the file name.
797 int fileId = 0;
798 const char* start = file;
799 const char* end = file + strlen(file) - 1;
800 const char* numString = end;
801
802 if ( ! isdigit( *numString ) )
803 {
804 while ( numString > start )
805 {
806 --numString;
807 if ( isdigit( *numString ) ) break;
808 }
809
810 if ( numString == start )
811 {
812 if ( isdigit( *numString ) )
813 {
814 fileId = atoi( numString );
815 }
816 return fileId; // no numbers in file name
817 }
818 }
819
820 while(numString > start)
821 {
822 --numString;
823 if ( ! isdigit( *numString ) ) break;
824 }
825
826 if ( ( numString == start ) && ( isdigit( *numString ) ) )
827 {
828 fileId = atoi( numString );
829 }
830 else
831 {
832 fileId = atoi( ++ numString );
833 }
834
835 return fileId;
836 }
837
DeterminePattern(const char * file)838 int vtkPExodusIIReader::DeterminePattern( const char* file )
839 {
840 char pattern[20] = "%s";
841 int scount = 0;
842 int cc = 0;
843 int min = 0, max = 0;
844
845 // First check for file names for which we should _not_ look for a numbered
846 // sequence. If using the extension .ex2 or .ex2v2, then we should not.
847 // Furthermore, if the filename ends in .e-s#, then this number is indicative
848 // of a restart number, not a partition number, so we should not look for
849 // numbered sequences there either.
850 vtksys::RegularExpression ex2RegEx("\\.ex2$");
851 vtksys::RegularExpression ex2v2RegEx("\\.ex2v2$");
852 vtksys::RegularExpression restartRegEx("\\.e-s\\.?[0-9]+(\\.ex2v[0-9]+)?$");
853
854 // This regular expression finds the number for a numbered sequence. This
855 // number appears at the end of file (or potentially right before an extension
856 // like .ex2v3 or perhaps a future version of this extension). The matches
857 // (in parentheses) are as follows:
858 // 1 - The prefix.
859 // 2 - The sequence number.
860 // 3 - The optional extension.
861 vtksys::RegularExpression
862 numberRegEx("^(.*[^0-9])([0-9]+)(\\.ex2v[0-9]+)?$");
863
864 if ( ex2RegEx.find(file) || ex2v2RegEx.find(file)
865 || restartRegEx.find(file) || !numberRegEx.find(file) )
866 {
867 // Set my info
868 //this->SetFilePattern( pattern ); // XXX Bad set
869 //this->SetFilePrefix( file ); // XXX Bad set
870 //this->SetFileRange( min, max ); // XXX Bad set
871 delete [] this->FilePattern;
872 delete [] this->FilePrefix;
873 this->FilePattern = vtksys::SystemTools::DuplicateString( pattern );
874 this->FilePrefix = vtksys::SystemTools::DuplicateString( file );
875 this->FileRange[0] = min;
876 this->FileRange[1] = max;
877 this->NumberOfFiles = max - min + 1;
878 return VTK_OK;
879 }
880
881 // If we are here, then numberRegEx matched and we have found the part of
882 // the filename that is the number. Extract the filename parts.
883 std::string prefix = numberRegEx.match(1);
884 scount = static_cast<int>(numberRegEx.match(2).size());
885 std::string extension = numberRegEx.match(3);
886
887 // Determine the pattern
888 snprintf(pattern, sizeof(pattern), "%%s%%0%ii%s", scount, extension.c_str());
889
890 // Count up the files
891 char buffer[1024];
892 vtksys::SystemTools::Stat_t fs;
893
894 // First go up every 100
895 for ( cc = min + 100; true; cc += 100 )
896 {
897 snprintf( buffer, sizeof(buffer), pattern, prefix.c_str(), cc );
898
899 if (vtksys::SystemTools::Stat(buffer, &fs) == -1)
900 break;
901
902 }
903 // Okay if I'm here than stat has failed so -100 on my cc
904 cc = cc - 100;
905 for ( cc = cc + 1; true; ++cc )
906 {
907 snprintf( buffer, sizeof(buffer), pattern, prefix.c_str(), cc );
908
909 if (vtksys::SystemTools::Stat(buffer, &fs) == -1)
910 break;
911 }
912 // Okay if I'm here than stat has failed so -1 on my cc
913 max = cc - 1;
914
915 // Second, go down every 100
916 // We can't assume that we're starting at 0 because the file selector
917 // will pick up every file that ends in .ex2v3... not just the first one.
918 for ( cc = min - 100; true; cc -= 100 )
919 {
920 if ( cc < 0 )
921 break;
922
923 snprintf( buffer, sizeof(buffer), pattern, prefix.c_str(), cc );
924
925 if (vtksys::SystemTools::Stat(buffer, &fs) == -1)
926 break;
927
928 }
929
930 cc += 100;
931 // Okay if I'm here than stat has failed so -100 on my cc
932 for (cc = cc - 1; true; --cc )
933 {
934 if ( cc < 0 )
935 break;
936
937 snprintf( buffer, sizeof(buffer), pattern, prefix.c_str(), cc );
938
939 if (vtksys::SystemTools::Stat(buffer, &fs) == -1)
940 break;
941 }
942 min = cc + 1;
943
944 // If the user did not specify a range before this,
945 // than set the range to the min and max
946 if ( ( this->FileRange[0] == -1 ) && ( this->FileRange[1] == -1 ) )
947 {
948 //this->SetFileRange( min, max ); // XXX Bad set
949 this->FileRange[0] = min;
950 this->FileRange[1] = max;
951 this->NumberOfFiles = max - min + 1;
952 }
953
954 // Set my info
955 //this->SetFilePattern( pattern ); // XXX Bad set
956 //this->SetFilePrefix( prefix ); // XXX Bad set
957 //delete [] prefix;
958 delete [] this->FilePattern;
959 delete [] this->FilePrefix;
960 this->FilePattern = vtksys::SystemTools::DuplicateString( pattern );
961 this->FilePrefix = vtksys::SystemTools::DuplicateString(prefix.c_str());
962
963 return VTK_OK;
964 }
965
966 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)967 void vtkPExodusIIReader::PrintSelf( ostream& os, vtkIndent indent )
968 {
969 vtkExodusIIReader::PrintSelf( os, indent );
970
971 if ( this->FilePattern )
972 {
973 os << indent << "FilePattern: " << this->FilePattern << endl;
974 }
975 else
976 {
977 os << indent << "FilePattern: nullptr\n";
978 }
979
980 if ( this->FilePattern )
981 {
982 os << indent << "FilePrefix: " << this->FilePrefix << endl;
983 }
984 else
985 {
986 os << indent << "FilePrefix: nullptr\n";
987 }
988
989 os << indent << "FileRange: "
990 << this->FileRange[0] << " " << this->FileRange[1] << endl;
991
992 os << indent << "NumberOfFiles: " << this->NumberOfFiles << endl;
993 os << indent << "Controller: " << this->Controller << endl;
994 os << indent << "VariableCacheSize: " << this->VariableCacheSize << endl;
995 }
996
GetTotalNumberOfElements()997 vtkIdType vtkPExodusIIReader::GetTotalNumberOfElements()
998 {
999 vtkIdType total = 0;
1000 std::vector<vtkExodusIIReader*>::iterator it;
1001 for ( it = this->ReaderList.begin(); it != this->ReaderList.end(); ++ it )
1002 {
1003 total += (*it)->GetTotalNumberOfElements();
1004 }
1005 return total;
1006 }
1007
GetTotalNumberOfNodes()1008 vtkIdType vtkPExodusIIReader::GetTotalNumberOfNodes()
1009 {
1010 vtkIdType total = 0;
1011 std::vector<vtkExodusIIReader*>::iterator it;
1012 for ( it = this->ReaderList.begin(); it != this->ReaderList.end(); ++ it )
1013 {
1014 total += (*it)->GetTotalNumberOfNodes();
1015 }
1016 return total;
1017 }
1018
BroadcastXmitString(vtkMultiProcessController * ctrl,char * str)1019 static void BroadcastXmitString( vtkMultiProcessController* ctrl, char* str )
1020 {
1021 int len;
1022 if ( str )
1023 {
1024 len = static_cast<int>( strlen( str ) ) + 1;
1025 ctrl->Broadcast( &len, 1, 0 );
1026 ctrl->Broadcast( str, len, 0 );
1027 }
1028 else
1029 {
1030 len = 0;
1031 ctrl->Broadcast( &len, 1, 0 );
1032 }
1033 }
1034
BroadcastRecvString(vtkMultiProcessController * ctrl,std::vector<char> & str)1035 static bool BroadcastRecvString( vtkMultiProcessController* ctrl,
1036 std::vector<char>& str )
1037 {
1038 int len;
1039 ctrl->Broadcast( &len, 1, 0 );
1040 if ( len )
1041 {
1042 str.resize( len );
1043 ctrl->Broadcast( &str[0], len, 0 );
1044 return true;
1045 }
1046 return false;
1047 }
1048
BroadcastDoubleVector(vtkMultiProcessController * controller,std::vector<double> & dvec,int rank)1049 static void BroadcastDoubleVector( vtkMultiProcessController* controller,
1050 std::vector<double>& dvec, int rank )
1051 {
1052 unsigned long len = static_cast<unsigned long>( dvec.size() );
1053 controller->Broadcast( &len, 1, 0 );
1054 if ( rank )
1055 {
1056 dvec.resize( len );
1057 }
1058 if ( len )
1059 {
1060 controller->Broadcast( &dvec[0], len, 0 );
1061 }
1062 }
1063
BroadcastIntVector(vtkMultiProcessController * controller,std::vector<int> & ivec,int rank)1064 static void BroadcastIntVector( vtkMultiProcessController* controller,
1065 std::vector<int>& ivec, int rank )
1066 {
1067 unsigned long len = static_cast<unsigned long>( ivec.size() );
1068 controller->Broadcast( &len, 1, 0 );
1069 if ( rank )
1070 {
1071 ivec.resize( len );
1072 }
1073 if ( len )
1074 {
1075 controller->Broadcast( &ivec[0], len, 0 );
1076 }
1077 }
1078
BroadcastString(vtkMultiProcessController * controller,vtkStdString & str,int rank)1079 static void BroadcastString( vtkMultiProcessController* controller,
1080 vtkStdString& str, int rank )
1081 {
1082 unsigned long len = static_cast<unsigned long>( str.size() ) + 1;
1083 controller->Broadcast( &len, 1, 0 );
1084 if ( len )
1085 {
1086 if ( rank )
1087 {
1088 std::vector<char> tmp;
1089 tmp.resize( len );
1090 controller->Broadcast( &(tmp[0]), len, 0 );
1091 str = &tmp[0];
1092 }
1093 else
1094 {
1095 const char* start = str.c_str();
1096 std::vector<char> tmp( start, start + len );
1097 controller->Broadcast( &tmp[0], len, 0 );
1098 }
1099 }
1100 }
1101
BroadcastStringVector(vtkMultiProcessController * controller,std::vector<vtkStdString> & svec,int rank)1102 static void BroadcastStringVector( vtkMultiProcessController* controller,
1103 std::vector<vtkStdString>& svec, int rank )
1104 {
1105 unsigned long len = static_cast<unsigned long>( svec.size() );
1106 controller->Broadcast( &len, 1, 0 );
1107 if ( rank )
1108 svec.resize( len );
1109 std::vector<vtkStdString>::iterator it;
1110 for ( it = svec.begin(); it != svec.end(); ++ it )
1111 {
1112 BroadcastString( controller, *it, rank );
1113 }
1114 }
1115
BroadcastObjectInfo(vtkMultiProcessController * controller,vtkExodusIIReaderPrivate::ObjectInfoType * oinfo,int rank)1116 static void BroadcastObjectInfo( vtkMultiProcessController* controller,
1117 vtkExodusIIReaderPrivate::ObjectInfoType* oinfo, int rank )
1118 {
1119 controller->Broadcast( &oinfo->Size, 1, 0 );
1120 controller->Broadcast( &oinfo->Status, 1, 0 );
1121 controller->Broadcast( &oinfo->Id, 1, 0 );
1122 BroadcastString( controller, oinfo->Name, rank );
1123 }
1124
BroadcastBlockSetInfo(vtkMultiProcessController * controller,vtkExodusIIReaderPrivate::BlockSetInfoType * bsinfo,int rank)1125 static void BroadcastBlockSetInfo( vtkMultiProcessController* controller,
1126 vtkExodusIIReaderPrivate::BlockSetInfoType* bsinfo, int rank )
1127 {
1128 BroadcastObjectInfo( controller, bsinfo, rank );
1129 controller->Broadcast( &bsinfo->FileOffset, 1, 0 );
1130 unsigned long len;
1131 unsigned long i;
1132 std::map<vtkIdType,vtkIdType>::iterator it;
1133 vtkIdType item[2];
1134 if ( rank == 0 )
1135 {
1136 len = static_cast<unsigned long>( bsinfo->PointMap.size() );
1137 controller->Broadcast( &len, 1, 0 );
1138 for ( it = bsinfo->PointMap.begin(); it != bsinfo->PointMap.end(); ++ it )
1139 {
1140 item[0] = it->first;
1141 item[1] = it->second;
1142 controller->Broadcast( item, 2, 0 );
1143 }
1144 }
1145 else
1146 {
1147 if ( bsinfo->CachedConnectivity )
1148 {
1149 bsinfo->CachedConnectivity->Delete();
1150 }
1151 bsinfo->CachedConnectivity = 0;
1152 bsinfo->PointMap.clear();
1153 bsinfo->ReversePointMap.clear();
1154 controller->Broadcast( &len, 1, 0 );
1155 for ( i = 0; i < len; ++ i )
1156 {
1157 controller->Broadcast( item, 2, 0 );
1158 bsinfo->PointMap[item[0]] = item[1];
1159 bsinfo->ReversePointMap[item[1]] = item[0];
1160 }
1161 }
1162 controller->Broadcast( &bsinfo->NextSqueezePoint, 1, 0 );
1163 }
1164
BroadcastBlockInfo(vtkMultiProcessController * controller,vtkExodusIIReaderPrivate::BlockInfoType * binfo,int rank)1165 static void BroadcastBlockInfo( vtkMultiProcessController* controller,
1166 vtkExodusIIReaderPrivate::BlockInfoType* binfo, int rank )
1167 {
1168 BroadcastBlockSetInfo( controller, binfo, rank );
1169 BroadcastString( controller, binfo->TypeName, rank );
1170 controller->Broadcast( binfo->BdsPerEntry, 3, 0 );
1171 controller->Broadcast( &binfo->AttributesPerEntry, 1, 0 );
1172 BroadcastStringVector( controller, binfo->AttributeNames, rank );
1173 BroadcastIntVector( controller, binfo->AttributeStatus, rank );
1174 controller->Broadcast( &binfo->CellType, 1, 0 );
1175 controller->Broadcast( &binfo->PointsPerCell, 1, 0 );
1176 }
1177
BroadcastPartInfo(vtkMultiProcessController * controller,vtkExodusIIReaderPrivate::PartInfoType * pinfo,int rank)1178 static void BroadcastPartInfo( vtkMultiProcessController* controller,
1179 vtkExodusIIReaderPrivate::PartInfoType* pinfo, int rank )
1180 {
1181 BroadcastObjectInfo( controller, pinfo, rank );
1182 BroadcastIntVector( controller, pinfo->BlockIndices, rank );
1183 }
1184
BroadcastAssemblyInfo(vtkMultiProcessController * controller,vtkExodusIIReaderPrivate::AssemblyInfoType * ainfo,int rank)1185 static void BroadcastAssemblyInfo( vtkMultiProcessController* controller,
1186 vtkExodusIIReaderPrivate::AssemblyInfoType* ainfo, int rank )
1187 {
1188 BroadcastObjectInfo( controller, ainfo, rank );
1189 BroadcastIntVector( controller, ainfo->BlockIndices, rank );
1190 }
1191
BroadcastMaterialInfo(vtkMultiProcessController * controller,vtkExodusIIReaderPrivate::MaterialInfoType * minfo,int rank)1192 static void BroadcastMaterialInfo( vtkMultiProcessController* controller,
1193 vtkExodusIIReaderPrivate::MaterialInfoType* minfo, int rank )
1194 {
1195 BroadcastObjectInfo( controller, minfo, rank );
1196 BroadcastIntVector( controller, minfo->BlockIndices, rank );
1197 }
1198
BroadcastSetInfo(vtkMultiProcessController * controller,vtkExodusIIReaderPrivate::SetInfoType * sinfo,int rank)1199 static void BroadcastSetInfo( vtkMultiProcessController* controller,
1200 vtkExodusIIReaderPrivate::SetInfoType* sinfo, int rank )
1201 {
1202 BroadcastBlockSetInfo( controller, sinfo, rank );
1203 controller->Broadcast( &sinfo->DistFact, 1, 0 );
1204 }
1205
BroadcastArrayInfo(vtkMultiProcessController * controller,vtkExodusIIReaderPrivate::ArrayInfoType * ainfo,int rank)1206 static void BroadcastArrayInfo( vtkMultiProcessController* controller,
1207 vtkExodusIIReaderPrivate::ArrayInfoType* ainfo, int rank )
1208 {
1209 if ( rank )
1210 ainfo->Reset();
1211
1212 BroadcastString( controller, ainfo->Name, rank );
1213 controller->Broadcast( &ainfo->Components, 1, 0 );
1214 controller->Broadcast( &ainfo->GlomType, 1, 0 );
1215 controller->Broadcast( &ainfo->StorageType, 1, 0 );
1216 controller->Broadcast( &ainfo->Source, 1, 0 );
1217 controller->Broadcast( &ainfo->Status, 1, 0 );
1218 BroadcastStringVector( controller, ainfo->OriginalNames, rank );
1219 BroadcastIntVector( controller, ainfo->OriginalIndices, rank );
1220 BroadcastIntVector( controller, ainfo->ObjectTruth, rank );
1221 }
1222
BroadcastArrayInfoVector(vtkMultiProcessController * controller,std::vector<vtkExodusIIReaderPrivate::ArrayInfoType> & ainfo,int rank)1223 static void BroadcastArrayInfoVector( vtkMultiProcessController* controller,
1224 std::vector<vtkExodusIIReaderPrivate::ArrayInfoType>& ainfo, int rank )
1225 {
1226 unsigned long len = static_cast<unsigned long>( ainfo.size() );
1227 controller->Broadcast( &len, 1, 0 );
1228 if ( rank )
1229 ainfo.resize( len );
1230 unsigned long i;
1231 for ( i = 0; i < len; ++ i )
1232 {
1233 BroadcastArrayInfo( controller, &ainfo[i], rank );
1234 }
1235 }
1236
BroadcastSortedObjectIndices(vtkMultiProcessController * controller,std::map<int,std::vector<int>> & oidx,int rank)1237 static void BroadcastSortedObjectIndices( vtkMultiProcessController* controller,
1238 std::map<int,std::vector<int> >& oidx, int rank )
1239 {
1240 unsigned long len = static_cast<unsigned long>( oidx.size() );
1241 controller->Broadcast( &len, 1, 0 );
1242 if ( rank == 0 )
1243 {
1244 std::map<int,std::vector<int> >::iterator it;
1245 int tmp;
1246 for ( it = oidx.begin(); it != oidx.end(); ++ it )
1247 {
1248 tmp = it->first;
1249 controller->Broadcast( &tmp, 1, 0 );
1250 BroadcastIntVector( controller, it->second, rank );
1251 }
1252 }
1253 else
1254 {
1255 unsigned long i;
1256 for ( i = 0; i < len; ++ i )
1257 {
1258 std::vector<int> blank;
1259 int key;
1260 controller->Broadcast( &key, 1, 0 );
1261 oidx[key] = blank;
1262 BroadcastIntVector( controller, oidx[key], rank );
1263 }
1264 }
1265 }
1266
BroadcastArrayInfoMap(vtkMultiProcessController * controller,std::map<int,std::vector<vtkExodusIIReaderPrivate::ArrayInfoType>> & oidx,int rank)1267 static void BroadcastArrayInfoMap(
1268 vtkMultiProcessController* controller,
1269 std::map<int,std::vector<vtkExodusIIReaderPrivate::ArrayInfoType> >& oidx, int rank )
1270 {
1271 unsigned long len = static_cast<unsigned long>( oidx.size() );
1272 controller->Broadcast( &len, 1, 0 );
1273 if ( rank == 0 )
1274 {
1275 int tmp;
1276 std::map<int,std::vector<vtkExodusIIReaderPrivate::ArrayInfoType> >::iterator it;
1277 for ( it = oidx.begin(); it != oidx.end(); ++ it )
1278 {
1279 tmp = it->first;
1280 controller->Broadcast( &tmp, 1, 0 );
1281 BroadcastArrayInfoVector( controller, it->second, rank );
1282 }
1283 }
1284 else
1285 {
1286 unsigned long i;
1287 for ( i = 0; i < len; ++ i )
1288 {
1289 std::vector<vtkExodusIIReaderPrivate::ArrayInfoType> blank;
1290 int key;
1291 controller->Broadcast( &key, 1, 0 );
1292 oidx[key] = blank;
1293 BroadcastArrayInfoVector( controller, oidx[key], rank );
1294 }
1295 }
1296 }
1297
BroadcastModelParameters(vtkMultiProcessController * controller,ex_init_params & params,int vtkNotUsed (rank))1298 static void BroadcastModelParameters(
1299 vtkMultiProcessController* controller, ex_init_params& params, int vtkNotUsed(rank) )
1300 {
1301 controller->Broadcast( params.title, MAX_LINE_LENGTH + 1, 0 );
1302 controller->Broadcast( ¶ms.num_dim, 1, 0 );
1303 controller->Broadcast( ¶ms.num_nodes, 1, 0 );
1304 controller->Broadcast( ¶ms.num_edge, 1, 0 );
1305 controller->Broadcast( ¶ms.num_edge_blk, 1, 0 );
1306 controller->Broadcast( ¶ms.num_face, 1, 0 );
1307 controller->Broadcast( ¶ms.num_face_blk, 1, 0 );
1308 controller->Broadcast( ¶ms.num_elem, 1, 0 );
1309 controller->Broadcast( ¶ms.num_elem_blk, 1, 0 );
1310 controller->Broadcast( ¶ms.num_node_sets, 1, 0 );
1311 controller->Broadcast( ¶ms.num_edge_sets, 1, 0 );
1312 controller->Broadcast( ¶ms.num_face_sets, 1, 0 );
1313 controller->Broadcast( ¶ms.num_side_sets, 1, 0 );
1314 controller->Broadcast( ¶ms.num_elem_sets, 1, 0 );
1315 controller->Broadcast( ¶ms.num_node_maps, 1, 0 );
1316 controller->Broadcast( ¶ms.num_edge_maps, 1, 0 );
1317 controller->Broadcast( ¶ms.num_face_maps, 1, 0 );
1318 controller->Broadcast( ¶ms.num_elem_maps, 1, 0 );
1319 }
1320
BroadcastBlockInfoVector(vtkMultiProcessController * controller,std::vector<vtkExodusIIReaderPrivate::BlockInfoType> & binfo,int rank)1321 static void BroadcastBlockInfoVector( vtkMultiProcessController* controller,
1322 std::vector<vtkExodusIIReaderPrivate::BlockInfoType>& binfo, int rank )
1323 {
1324 unsigned long len = static_cast<unsigned long>( binfo.size() );
1325 controller->Broadcast( &len, 1, 0 );
1326 if ( rank )
1327 binfo.resize( len );
1328 std::vector<vtkExodusIIReaderPrivate::BlockInfoType>::iterator it;
1329 for ( it = binfo.begin(); it != binfo.end(); ++ it )
1330 {
1331 BroadcastBlockInfo( controller, &(*it), rank );
1332 }
1333 }
1334
BroadcastBlockInfoMap(vtkMultiProcessController * controller,std::map<int,std::vector<vtkExodusIIReaderPrivate::BlockInfoType>> & binfo,int rank)1335 static void BroadcastBlockInfoMap( vtkMultiProcessController* controller,
1336 std::map<int,std::vector<vtkExodusIIReaderPrivate::BlockInfoType> >& binfo, int rank )
1337 {
1338 unsigned long len = static_cast<unsigned long>( binfo.size() );
1339 controller->Broadcast( &len, 1, 0 );
1340 int tmp;
1341 if ( rank == 0 )
1342 {
1343 std::map<int,std::vector<vtkExodusIIReaderPrivate::BlockInfoType> >::iterator it;
1344 for ( it = binfo.begin(); it != binfo.end(); ++ it )
1345 {
1346 tmp = it->first;
1347 controller->Broadcast( &tmp, 1, 0 );
1348 BroadcastBlockInfoVector( controller, it->second, rank );
1349 }
1350 }
1351 else
1352 {
1353 unsigned long i;
1354 std::vector<vtkExodusIIReaderPrivate::BlockInfoType> blank;
1355 for ( i = 0; i < len; ++ i )
1356 {
1357 controller->Broadcast( &tmp, 1, 0 );
1358 binfo[tmp] = blank;
1359 BroadcastBlockInfoVector( controller, binfo[tmp], rank );
1360 }
1361 }
1362 }
1363
BroadcastSetInfoVector(vtkMultiProcessController * controller,std::vector<vtkExodusIIReaderPrivate::SetInfoType> & sinfo,int rank)1364 static void BroadcastSetInfoVector( vtkMultiProcessController* controller,
1365 std::vector<vtkExodusIIReaderPrivate::SetInfoType>& sinfo, int rank )
1366 {
1367 unsigned long len = static_cast<unsigned long>( sinfo.size() );
1368 controller->Broadcast( &len, 1, 0 );
1369 if ( rank )
1370 sinfo.resize( len );
1371 std::vector<vtkExodusIIReaderPrivate::SetInfoType>::iterator it;
1372 for ( it = sinfo.begin(); it != sinfo.end(); ++ it )
1373 {
1374 BroadcastSetInfo( controller, &(*it), rank );
1375 }
1376 }
1377
BroadcastSetInfoMap(vtkMultiProcessController * controller,std::map<int,std::vector<vtkExodusIIReaderPrivate::SetInfoType>> & sinfo,int rank)1378 static void BroadcastSetInfoMap( vtkMultiProcessController* controller,
1379 std::map<int,std::vector<vtkExodusIIReaderPrivate::SetInfoType> >& sinfo, int rank )
1380 {
1381 unsigned long len = static_cast<unsigned long>( sinfo.size() );
1382 controller->Broadcast( &len, 1, 0 );
1383 int tmp;
1384 if ( rank == 0 )
1385 {
1386 std::map<int,std::vector<vtkExodusIIReaderPrivate::SetInfoType> >::iterator it;
1387 for ( it = sinfo.begin(); it != sinfo.end(); ++ it )
1388 {
1389 tmp = it->first;
1390 controller->Broadcast( &tmp, 1, 0 );
1391 BroadcastSetInfoVector( controller, it->second, rank );
1392 }
1393 }
1394 else
1395 {
1396 unsigned long i;
1397 std::vector<vtkExodusIIReaderPrivate::SetInfoType> blank;
1398 for ( i = 0; i < len; ++ i )
1399 {
1400 controller->Broadcast( &tmp, 1, 0 );
1401 sinfo[tmp] = blank;
1402 BroadcastSetInfoVector( controller, sinfo[tmp], rank );
1403 }
1404 }
1405 }
1406
BroadcastMapInfoVector(vtkMultiProcessController * controller,std::vector<vtkExodusIIReaderPrivate::MapInfoType> & minfo,int rank)1407 static void BroadcastMapInfoVector( vtkMultiProcessController* controller,
1408 std::vector<vtkExodusIIReaderPrivate::MapInfoType>& minfo, int rank )
1409 {
1410 unsigned long len = static_cast<unsigned long>( minfo.size() );
1411 controller->Broadcast( &len, 1, 0 );
1412 if ( rank )
1413 minfo.resize( len );
1414 std::vector<vtkExodusIIReaderPrivate::MapInfoType>::iterator it;
1415 for ( it = minfo.begin(); it != minfo.end(); ++ it )
1416 {
1417 BroadcastObjectInfo( controller, &(*it), rank );
1418 }
1419 }
1420
BroadcastMapInfoMap(vtkMultiProcessController * controller,std::map<int,std::vector<vtkExodusIIReaderPrivate::MapInfoType>> & minfo,int rank)1421 static void BroadcastMapInfoMap( vtkMultiProcessController* controller,
1422 std::map<int,std::vector<vtkExodusIIReaderPrivate::MapInfoType> >& minfo, int rank )
1423 {
1424 unsigned long len = static_cast<unsigned long>( minfo.size() );
1425 controller->Broadcast( &len, 1, 0 );
1426 int tmp;
1427 if ( rank == 0 )
1428 {
1429 std::map<int,std::vector<vtkExodusIIReaderPrivate::MapInfoType> >::iterator it;
1430 for ( it = minfo.begin(); it != minfo.end(); ++ it )
1431 {
1432 tmp = it->first;
1433 controller->Broadcast( &tmp, 1, 0 );
1434 BroadcastMapInfoVector( controller, it->second, rank );
1435 }
1436 }
1437 else
1438 {
1439 unsigned long i;
1440 std::vector<vtkExodusIIReaderPrivate::MapInfoType> blank;
1441 for ( i = 0; i < len; ++ i )
1442 {
1443 controller->Broadcast( &tmp, 1, 0 );
1444 minfo[tmp] = blank;
1445 BroadcastMapInfoVector( controller, minfo[tmp], rank );
1446 }
1447 }
1448 }
1449
BroadcastPartInfoVector(vtkMultiProcessController * controller,std::vector<vtkExodusIIReaderPrivate::PartInfoType> & pinfo,int rank)1450 static void BroadcastPartInfoVector( vtkMultiProcessController* controller,
1451 std::vector<vtkExodusIIReaderPrivate::PartInfoType>& pinfo, int rank )
1452 {
1453 unsigned long len = static_cast<unsigned long>( pinfo.size() );
1454 controller->Broadcast( &len, 1, 0 );
1455 if ( rank )
1456 pinfo.resize( len );
1457 std::vector<vtkExodusIIReaderPrivate::PartInfoType>::iterator it;
1458 for ( it = pinfo.begin(); it != pinfo.end(); ++ it )
1459 {
1460 BroadcastPartInfo( controller, &(*it), rank );
1461 }
1462 }
1463
BroadcastMaterialInfoVector(vtkMultiProcessController * controller,std::vector<vtkExodusIIReaderPrivate::MaterialInfoType> & minfo,int rank)1464 static void BroadcastMaterialInfoVector( vtkMultiProcessController* controller,
1465 std::vector<vtkExodusIIReaderPrivate::MaterialInfoType>& minfo, int rank )
1466 {
1467 unsigned long len = static_cast<unsigned long>( minfo.size() );
1468 controller->Broadcast( &len, 1, 0 );
1469 if ( rank )
1470 minfo.resize( len );
1471 std::vector<vtkExodusIIReaderPrivate::MaterialInfoType>::iterator it;
1472 for ( it = minfo.begin(); it != minfo.end(); ++ it )
1473 {
1474 BroadcastMaterialInfo( controller, &(*it), rank );
1475 }
1476 }
1477
BroadcastAssemblyInfoVector(vtkMultiProcessController * controller,std::vector<vtkExodusIIReaderPrivate::AssemblyInfoType> & ainfo,int rank)1478 static void BroadcastAssemblyInfoVector( vtkMultiProcessController* controller,
1479 std::vector<vtkExodusIIReaderPrivate::AssemblyInfoType>& ainfo, int rank )
1480 {
1481 unsigned long len = static_cast<unsigned long>( ainfo.size() );
1482 controller->Broadcast( &len, 1, 0 );
1483 if ( rank )
1484 ainfo.resize( len );
1485 std::vector<vtkExodusIIReaderPrivate::AssemblyInfoType>::iterator it;
1486 for ( it = ainfo.begin(); it != ainfo.end(); ++ it )
1487 {
1488 BroadcastAssemblyInfo( controller, &(*it), rank );
1489 }
1490 }
1491
Broadcast(vtkMultiProcessController * ctrl)1492 void vtkPExodusIIReader::Broadcast( vtkMultiProcessController* ctrl )
1493 {
1494 if ( ctrl )
1495 {
1496 int rank = ctrl->GetLocalProcessId();
1497 BroadcastBlockInfoMap( ctrl, this->Metadata->BlockInfo, rank );
1498 BroadcastSetInfoMap( ctrl, this->Metadata->SetInfo, rank );
1499 BroadcastMapInfoMap( ctrl, this->Metadata->MapInfo, rank );
1500 BroadcastPartInfoVector( ctrl, this->Metadata->PartInfo, rank );
1501 BroadcastMaterialInfoVector( ctrl, this->Metadata->MaterialInfo, rank );
1502 BroadcastAssemblyInfoVector( ctrl, this->Metadata->AssemblyInfo, rank );
1503 BroadcastSortedObjectIndices( ctrl, this->Metadata->SortedObjectIndices, rank );
1504 BroadcastArrayInfoMap( ctrl, this->Metadata->ArrayInfo, rank );
1505 ctrl->Broadcast( &this->Metadata->AppWordSize, 1, 0 );
1506 ctrl->Broadcast( &this->Metadata->DiskWordSize, 1, 0 );
1507 ctrl->Broadcast( &this->Metadata->ExodusVersion, 1, 0 );
1508 ctrl->Broadcast( &this->Metadata->ExodusVersion, 1, 0 );
1509 BroadcastModelParameters( ctrl, this->Metadata->ModelParameters, rank );
1510 BroadcastDoubleVector( ctrl, this->Metadata->Times, rank );
1511
1512 ctrl->Broadcast( this->TimeStepRange, 2, 0 );
1513 if ( rank == 0 )
1514 {
1515 BroadcastXmitString( ctrl, this->FilePattern );
1516 BroadcastXmitString( ctrl, this->FilePrefix );
1517 }
1518 else
1519 {
1520 std::vector<char> tmp;
1521 delete [] this->FilePattern;
1522 delete [] this->FilePrefix;
1523 //this->SetFilePattern( BroadcastRecvString( ctrl, tmp ) ? &tmp[0] : 0 ); // XXX Bad set
1524 //this->SetFilePrefix( BroadcastRecvString( ctrl, tmp ) ? &tmp[0] : 0 ); // XXX Bad set
1525 this->FilePattern = BroadcastRecvString( ctrl, tmp ) ? vtksys::SystemTools::DuplicateString( &tmp[0] ) : 0;
1526 this->FilePrefix = BroadcastRecvString( ctrl, tmp ) ? vtksys::SystemTools::DuplicateString( &tmp[0] ) : 0;
1527 }
1528 ctrl->Broadcast( this->FileRange, 2, 0 );
1529 ctrl->Broadcast( &this->NumberOfFiles, 1, 0 );
1530 }
1531 }
1532