1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkPWindBladeReader.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 // This class was developed by Sohail Shafii; University of California Davis;
16 // Davis, CA 95616. sohailshafii@yahoo.com.
17
18 #include "vtkPWindBladeReader.h"
19
20 #include "vtkDataArraySelection.h"
21 #include "vtkFloatArray.h"
22 #include "vtkInformation.h"
23 #include "vtkInformationVector.h"
24 #include "vtkMPI.h"
25 #include "vtkMPIController.h"
26 #include "vtkObjectFactory.h"
27 #include "vtkStreamingDemandDrivenPipeline.h"
28 #include "vtksys/SystemTools.hxx"
29
30 #include <sstream>
31 #include <vector>
32
33 vtkStandardNewMacro(vtkPWindBladeReader);
34
35 // This macro can be wrapped around MPI function calls to easily report errors.
36 // Reporting errors is more important with file I/O because, unlike network I/O,
37 // they usually don't terminate the program.
38 #define MPICall(funcall) \
39 { \
40 int __my_result = funcall; \
41 if (__my_result != MPI_SUCCESS) \
42 { \
43 char errormsg[MPI_MAX_ERROR_STRING]; \
44 int dummy; \
45 MPI_Error_string(__my_result, errormsg, &dummy); \
46 vtkErrorMacro(<< "Received error when calling" << endl \
47 << #funcall << endl << endl \
48 << errormsg); \
49 } \
50 }
51
52 class PWindBladeReaderInternal
53 {
54 public:
55 MPI_File FilePtr;
56 };
57
58 //-----------------------------------------------------------------------------
vtkPWindBladeReader()59 vtkPWindBladeReader::vtkPWindBladeReader()
60 {
61 this->PInternal = new PWindBladeReaderInternal();
62 }
63
64 //-----------------------------------------------------------------------------
~vtkPWindBladeReader()65 vtkPWindBladeReader::~vtkPWindBladeReader()
66 {
67 delete this->PInternal;
68 }
69
70 //-----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)71 void vtkPWindBladeReader::PrintSelf(ostream &os, vtkIndent indent)
72 {
73 this->Superclass::PrintSelf(os, indent);
74 }
75
76 //-----------------------------------------------------------------------------
RequestData(vtkInformation * reqInfo,vtkInformationVector ** inVector,vtkInformationVector * outVector)77 int vtkPWindBladeReader::RequestData(vtkInformation *reqInfo,
78 vtkInformationVector **inVector,
79 vtkInformationVector *outVector)
80 {
81 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
82 {
83 // serial case
84 return this->Superclass::RequestData(reqInfo, inVector, outVector);
85 }
86 int port = reqInfo->Get(vtkDemandDrivenPipeline::FROM_OUTPUT_PORT());
87
88 // field data port
89 if (port == 0)
90 {
91 std::ostringstream fileName;
92 vtkStructuredGrid *field = this->GetFieldOutput();
93 this->InitFieldData(outVector, fileName, field);
94 char* cchar = new char[strlen(fileName.str().c_str()) + 1];
95 strcpy(cchar, fileName.str().c_str());
96 MPICall(MPI_File_open(MPI_COMM_WORLD, cchar, MPI_MODE_RDONLY, MPI_INFO_NULL, &this->PInternal->FilePtr));
97 delete [] cchar;
98 if (this->PInternal->FilePtr == nullptr)
99 {
100 vtkWarningMacro(<< "Could not open file " << fileName.str());
101 }
102 this->SetUpFieldVars(field);
103 MPICall(MPI_File_close(&this->PInternal->FilePtr));
104 return 1;
105 }
106 // Request data is on blade and is displayed only by processor 0
107 // Even if the blade is turned off, it must update with time along with field
108 else if (port == 1)
109 {
110 if (this->UseTurbineFile == 1 &&
111 vtkMultiProcessController::GetGlobalController()->GetLocalProcessId() == 0)
112 {
113 this->InitBladeData(outVector);
114 }
115 return 1;
116 }
117 // Request data in on ground
118 else if (port == 2)
119 {
120 this->SetUpGroundData(outVector);
121 }
122
123 return 1;
124 }
125
126
127 //----------------------------------------------------------------------------
128 // Calculate pressure from tempg and density
129 // Calculate pressure - pre from pressure in first z position
130 // Requires that all data be present
131 //----------------------------------------------------------------------------
CalculatePressure(int pressure,int prespre,int tempg,int density)132 void vtkPWindBladeReader::CalculatePressure(int pressure, int prespre,
133 int tempg, int density)
134 {
135 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
136 {
137 return this->Superclass::CalculatePressure(pressure, prespre,
138 tempg, density);
139 }
140 float *pressureData = nullptr, *prespreData = nullptr;
141 this->InitPressureData(pressure, prespre, pressureData, prespreData);
142
143 // Read tempg and Density components from file
144 float* tempgData = new float[this->BlockSize];
145 float* densityData = new float[this->BlockSize];
146
147 MPI_Status status;
148 char native[7] = "native";
149 MPICall(MPI_File_set_view(this->PInternal->FilePtr, this->VariableOffset[tempg], MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
150 MPICall(MPI_File_read_all(this->PInternal->FilePtr, tempgData, this->BlockSize, MPI_FLOAT, &status));
151 MPICall(MPI_File_set_view(this->PInternal->FilePtr, this->VariableOffset[density], MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
152 MPICall(MPI_File_read_all(this->PInternal->FilePtr, densityData, this->BlockSize, MPI_FLOAT, &status));
153
154 // Only the requested subextents are stored on this processor
155 this->SetUpPressureData(pressureData, prespreData, tempgData, densityData);
156
157 delete [] tempgData;
158 delete [] densityData;
159 }
160
161 //----------------------------------------------------------------------------
162 // Calculate vorticity from UVW
163 // Requires ghost cell information so fetch all data from files for now
164 //----------------------------------------------------------------------------
CalculateVorticity(int vort,int uvw,int density)165 void vtkPWindBladeReader::CalculateVorticity(int vort, int uvw, int density)
166 {
167 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
168 return this->Superclass::CalculateVorticity(vort, uvw, density);
169
170 // Set the number of components and tuples for the requested data
171 this->Data[vort]->SetNumberOfComponents(1);
172 this->Data[vort]->SetNumberOfTuples(this->NumberOfTuples);
173 float* vortData = this->Data[vort]->GetPointer(0);
174
175 // Read U and V components (two int block sizes in between)
176 float* uData = new float[this->BlockSize];
177 float* vData = new float[this->BlockSize];
178
179 MPI_Status status;
180 char native[7] = "native";
181 MPICall(MPI_File_set_view(this->PInternal->FilePtr, this->VariableOffset[uvw], MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
182 MPICall(MPI_File_read_all(this->PInternal->FilePtr, uData, this->BlockSize, MPI_FLOAT, &status));
183 MPICall(MPI_File_set_view(this->PInternal->FilePtr, (2 * sizeof(int)), MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
184 MPICall(MPI_File_read_all(this->PInternal->FilePtr, vData, this->BlockSize, MPI_FLOAT, &status));
185
186 // Read Density component
187 float* densityData = new float[this->BlockSize];
188 MPICall(MPI_File_set_view(this->PInternal->FilePtr, this->VariableOffset[density], MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
189 MPICall(MPI_File_read_all(this->PInternal->FilePtr, densityData, this->BlockSize, MPI_FLOAT, &status));
190
191 this->SetUpVorticityData(uData, vData, densityData, vortData);
192
193 delete [] uData;
194 delete [] vData;
195 delete [] densityData;
196 }
197
198 //----------------------------------------------------------------------------
199 // Load one variable data array of BLOCK structure into ParaView
200 //----------------------------------------------------------------------------
LoadVariableData(int var)201 void vtkPWindBladeReader::LoadVariableData(int var)
202 {
203 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
204 return this->Superclass::LoadVariableData(var);
205
206 this->Data[var]->Delete();
207 this->Data[var] = vtkFloatArray::New();
208 this->Data[var]->SetName(VariableName[var].c_str());
209
210 // Skip to the appropriate variable block and read byte count
211 char native[7] = "native";
212 MPICall(MPI_File_set_view(this->PInternal->FilePtr, this->VariableOffset[var], MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
213
214 int numberOfComponents = 0, planeSize = 0, rowSize;
215 float *varData = nullptr;
216 float* block = new float[this->BlockSize];
217 this->InitVariableData(var, numberOfComponents, varData, planeSize, rowSize);
218 for (int comp = 0; comp < numberOfComponents; comp++)
219 {
220 MPI_Status status;
221 MPICall(MPI_File_read_all(this->PInternal->FilePtr, block, this->BlockSize, MPI_FLOAT, &status));
222
223 int pos = comp;
224 for (int k = this->SubExtent[4]; k <= this->SubExtent[5]; k++)
225 {
226 for (int j = this->SubExtent[2]; j <= this->SubExtent[3]; j++)
227 {
228 for (int i = this->SubExtent[0]; i <= this->SubExtent[1]; i++)
229 {
230 int index = (k * planeSize) + (j * rowSize) + i;
231 varData[pos] = block[index];
232 pos += numberOfComponents;
233 }
234 }
235 }
236
237 // Skip closing and opening byte sizes
238 MPICall(MPI_File_seek(this->PInternal->FilePtr, (2 * sizeof(int)), MPI_SEEK_CUR));
239 }
240 delete [] block;
241 }
242
243 //----------------------------------------------------------------------------
244 // Load one variable data array of BLOCK structure into ParaView
245 //----------------------------------------------------------------------------
ReadGlobalData()246 bool vtkPWindBladeReader::ReadGlobalData()
247 {
248 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
249 {
250 return this->Superclass::ReadGlobalData();
251 }
252
253 std::string fileName = this->Filename;
254 vtksys::SystemTools::ConvertToUnixSlashes(fileName);
255
256 std::vector<char> inBuf(vtkWindBladeReader::LINE_SIZE);
257 MPI_File tempFile;
258 char native[7] = "native";
259 char* cchar = new char[strlen(fileName.c_str()) + 1];
260 strcpy(cchar, fileName.c_str());
261 MPICall(MPI_File_open(MPI_COMM_WORLD, cchar, MPI_MODE_RDONLY, MPI_INFO_NULL, &tempFile));
262 delete [] cchar;
263
264 std::stringstream inStr;
265 MPI_Offset i, tempSize;
266 MPI_Status status;
267
268 MPICall(MPI_File_get_size(tempFile, &tempSize));
269 MPICall(MPI_File_set_view(tempFile, 0, MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
270
271 for(i = 0; i < tempSize; i = i + vtkWindBladeReader::LINE_SIZE)
272 {
273 if(i + vtkWindBladeReader::LINE_SIZE > tempSize)
274 {
275 MPICall(MPI_File_read_all(tempFile, &(inBuf[0]), tempSize - i, MPI_BYTE, &status));
276 inStr.write(&(inBuf[0]), tempSize - i);
277 }
278 else
279 {
280 MPICall(MPI_File_read_all(tempFile, &(inBuf[0]), vtkWindBladeReader::LINE_SIZE, MPI_BYTE, &status));
281 inStr.write(&(inBuf[0]), vtkWindBladeReader::LINE_SIZE);
282 }
283 }
284
285 MPICall(MPI_File_close(&tempFile));
286 return this->SetUpGlobalData(fileName, inStr);
287 }
288
289 //----------------------------------------------------------------------------
290 //
291 // Open the first data file and verify that the data is where is should be
292 // Each data block is enclosed by two ints which record the number of bytes
293 // Save the file offset for each variable
294 //
295 //----------------------------------------------------------------------------
FindVariableOffsets()296 bool vtkPWindBladeReader::FindVariableOffsets()
297 {
298 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
299 return this->Superclass::FindVariableOffsets();
300
301 // Open the first data file
302 std::ostringstream fileName;
303 fileName << this->RootDirectory << "/"
304 << this->DataDirectory << "/"
305 << this->DataBaseName << this->TimeStepFirst;
306
307 char* cchar = new char[strlen(fileName.str().c_str()) + 1];
308 strcpy(cchar, fileName.str().c_str());
309 MPICall(MPI_File_open(MPI_COMM_WORLD, cchar, MPI_MODE_RDONLY, MPI_INFO_NULL, &this->PInternal->FilePtr));
310 delete [] cchar;
311
312 if (this->PInternal->FilePtr == nullptr)
313 {
314 vtkErrorMacro("Could not open file " << fileName.str());
315 return false;
316 }
317
318 // Scan file recording offsets which points to the first data value
319 int byteCount;
320
321 MPI_Status status;
322 char native[7] = "native";
323 MPICall(MPI_File_set_view(this->PInternal->FilePtr, 0, MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
324 MPICall(MPI_File_read_all(this->PInternal->FilePtr, &byteCount, 1, MPI_INT, &status));
325 MPI_Offset offset;
326 MPICall(MPI_File_get_position(this->PInternal->FilePtr, &offset));
327 MPICall(MPI_File_close(&this->PInternal->FilePtr));
328
329 this->BlockSize = byteCount / BYTES_PER_DATA;
330
331 for (int var = 0; var < this->NumberOfFileVariables; var++)
332 {
333 this->VariableOffset[var] = offset;
334
335 // Skip over the SCALAR or VECTOR components for this variable
336 int numberOfComponents = 1;
337 if (this->VariableStruct[var] == VECTOR)
338 {
339 numberOfComponents = DIMENSION;
340 }
341
342 // Skip data plus two integer byte counts, for each component.
343 offset += numberOfComponents * (byteCount + (2 * sizeof(int)));
344 }
345
346 return true;
347 }
348
349 //----------------------------------------------------------------------------
350 // Create the z topography from 2D (x,y) elevations and return in zData
351 //----------------------------------------------------------------------------
CreateZTopography(float * zValues)352 void vtkPWindBladeReader::CreateZTopography(float* zValues)
353 {
354 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
355 return this->Superclass::CreateZTopography(zValues);
356
357 // Read the x,y topography data file
358 std::ostringstream fileName;
359 fileName << this->RootDirectory << "/"
360 << this->TopographyFile;
361
362 int blockSize = this->Dimension[0] * this->Dimension[1];
363 float* topoData = new float[blockSize];
364 char* cchar = new char[strlen(fileName.str().c_str()) + 1];
365
366 strcpy(cchar, fileName.str().c_str());
367 MPICall(MPI_File_open(MPI_COMM_WORLD, cchar, MPI_MODE_RDONLY, MPI_INFO_NULL, &this->PInternal->FilePtr));
368 delete [] cchar;
369
370 MPI_Status status;
371 char native[7] = "native";
372 MPICall(MPI_File_set_view(this->PInternal->FilePtr, BYTES_PER_DATA, MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
373 MPICall(MPI_File_read_all(this->PInternal->FilePtr, topoData, blockSize, MPI_FLOAT, &status));
374
375 this->ProcessZCoords(topoData, zValues);
376
377 delete [] topoData;
378 MPICall(MPI_File_close(&this->PInternal->FilePtr));
379 }
380
381 //----------------------------------------------------------------------------
382 // Build the turbine towers
383 // Parse a blade file to set the number of cells and points in blades
384 //----------------------------------------------------------------------------
SetupBladeData()385 void vtkPWindBladeReader::SetupBladeData()
386 {
387 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
388 return this->Superclass::SetupBladeData();
389
390 // Load the tower information
391 std::ostringstream fileName;
392 fileName << this->RootDirectory << "/"
393 << this->TurbineDirectory << "/"
394 << this->TurbineTowerName;
395 std::vector<char> inBuf(vtkWindBladeReader::LINE_SIZE);
396
397 MPI_File tempFile;
398 char native[7] = "native";
399 char* cchar = new char[strlen(fileName.str().c_str()) + 1];
400 strcpy(cchar, fileName.str().c_str());
401 MPICall(MPI_File_open(MPI_COMM_WORLD, cchar, MPI_MODE_RDONLY, MPI_INFO_NULL, &tempFile));
402 delete [] cchar;
403
404 std::stringstream inStr;
405 MPI_Offset i, tempSize;
406 MPI_Status status;
407
408 MPICall(MPI_File_get_size(tempFile, &tempSize));
409 MPICall(MPI_File_set_view(tempFile, 0, MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
410
411 for(i = 0; i < tempSize; i = i + vtkWindBladeReader::LINE_SIZE)
412 {
413 if(i + vtkWindBladeReader::LINE_SIZE > tempSize)
414 {
415 MPICall(MPI_File_read_all(tempFile, &(inBuf[0]), tempSize - i, MPI_BYTE, &status));
416 inStr.write(&(inBuf[0]), tempSize - i);
417 }
418 else
419 {
420 MPICall(MPI_File_read_all(tempFile, &(inBuf[0]), vtkWindBladeReader::LINE_SIZE, MPI_BYTE, &status));
421 inStr.write(&(inBuf[0]), vtkWindBladeReader::LINE_SIZE);
422 }
423 }
424
425 MPICall(MPI_File_close(&tempFile));
426
427 if (!inStr)
428 {
429 vtkWarningMacro("Could not open " << fileName.str() << endl);
430 }
431
432 int numColumns = 0;
433 this->ReadBladeHeader(fileName.str(), inStr, numColumns);
434
435 // Calculate the number of cells in unstructured turbine blades
436 std::ostringstream fileName2;
437 fileName2 << this->RootDirectory << "/"
438 << this->TurbineDirectory << "/"
439 << this->TurbineBladeName << this->TimeStepFirst;
440
441 cchar = new char[strlen(fileName2.str().c_str()) + 1];
442 strcpy(cchar, fileName2.str().c_str());
443 MPICall(MPI_File_open(MPI_COMM_WORLD, cchar, MPI_MODE_RDONLY, MPI_INFO_NULL, &tempFile));
444 delete [] cchar;
445
446 std::stringstream inStr2;
447
448 MPICall(MPI_File_get_size(tempFile, &tempSize));
449 MPICall(MPI_File_set_view(tempFile, 0, MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
450
451 for(i = 0; i < tempSize; i = i + vtkWindBladeReader::LINE_SIZE)
452 {
453 if(i + vtkWindBladeReader::LINE_SIZE > tempSize)
454 {
455 MPICall(MPI_File_read_all(tempFile, &(inBuf[0]), tempSize - i, MPI_BYTE, &status));
456 inStr2.write(&(inBuf[0]), tempSize - i);
457 }
458 else
459 {
460 MPICall(MPI_File_read_all(tempFile, &(inBuf[0]), vtkWindBladeReader::LINE_SIZE, MPI_BYTE, &status));
461 inStr2.write(&(inBuf[0]), vtkWindBladeReader::LINE_SIZE);
462 }
463 }
464
465 MPICall(MPI_File_close(&tempFile));
466
467 if (!inStr2)
468 {
469 vtkWarningMacro("Could not open blade file: " << fileName2.str().c_str() <<
470 " to calculate blade cells.");
471 for (int j = this->TimeStepFirst + this->TimeStepDelta; j <= this->TimeStepLast;
472 j += this->TimeStepDelta)
473 {
474 std::ostringstream fileName3;
475 fileName3 << this->RootDirectory << "/"
476 << this->TurbineDirectory << "/"
477 << this->TurbineBladeName << j;
478 //std::cout << "Trying " << fileName3.str().c_str() << "...";
479
480 cchar = new char[strlen(fileName3.str().c_str()) + 1];
481 strcpy(cchar, fileName3.str().c_str());
482 MPICall(MPI_File_open(MPI_COMM_WORLD, cchar, MPI_MODE_RDONLY, MPI_INFO_NULL, &tempFile));
483 delete [] cchar;
484
485 inStr2.clear();
486 inStr2.str("");
487
488 MPICall(MPI_File_get_size(tempFile, &tempSize));
489 MPICall(MPI_File_set_view(tempFile, 0, MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
490
491 for(i = 0; i < tempSize; i = i + vtkWindBladeReader::LINE_SIZE)
492 {
493 if(i + vtkWindBladeReader::LINE_SIZE > tempSize)
494 {
495 MPICall(MPI_File_read_all(tempFile, &(inBuf[0]), tempSize - i, MPI_BYTE, &status));
496 inStr2.write(&(inBuf[0]), tempSize - i);
497 }
498 else
499 {
500 MPICall(MPI_File_read_all(tempFile, &(inBuf[0]), vtkWindBladeReader::LINE_SIZE, MPI_BYTE, &status));
501 inStr2.write(&(inBuf[0]), vtkWindBladeReader::LINE_SIZE);
502 }
503 }
504 MPICall(MPI_File_close(&tempFile));
505
506 if(inStr2.good())
507 {
508 vtkWarningMacro("Success with " << fileName3.str());
509 break;
510 }
511 else
512 {
513 vtkWarningMacro("Failure with " << fileName3.str());
514 }
515 }
516 }
517
518 this->NumberOfBladeCells = 0;
519 // if we have at least 13 columns, then this is the new format with a header in the
520 // turbine blade file
521 if (numColumns >= 13 && inStr2)
522 {
523 int linesSkipped = 0;
524 // each blade tower tries to split the columns such that there are
525 // five items per line in header, so skip those lines
526 this->NumberOfLinesToSkip = this->NumberOfBladeTowers*(int)ceil(numColumns/5.0);
527 // now skip the first few lines based on header, if that applies
528 while(inStr2.getline(&(inBuf[0]), vtkWindBladeReader::LINE_SIZE) &&
529 linesSkipped < this->NumberOfLinesToSkip-1)
530 {
531 linesSkipped++;
532 }
533 }
534 while (inStr2.getline(&(inBuf[0]), vtkWindBladeReader::LINE_SIZE))
535 {
536 this->NumberOfBladeCells++;
537 }
538 this->NumberOfBladePoints = this->NumberOfBladeCells * NUM_PART_SIDES;
539 // Points and cells needed for constant towers
540 this->NumberOfBladePoints += this->NumberOfBladeTowers * NUM_BASE_SIDES;
541 this->NumberOfBladeCells += this->NumberOfBladeTowers;
542 }
543
544 //----------------------------------------------------------------------------
545 // Build the turbine blades
546 //----------------------------------------------------------------------------
LoadBladeData(int timeStep)547 void vtkPWindBladeReader::LoadBladeData(int timeStep)
548 {
549 if (!vtkMPIController::GetGlobalController()->IsA("vtkMPIController"))
550 return this->Superclass::LoadBladeData(timeStep);
551
552 this->BPoints->Delete();
553 this->BPoints = vtkPoints::New();
554
555 // Open the file for this time step
556 std::ostringstream fileName;
557 fileName << this->RootDirectory << "/"
558 << this->TurbineDirectory << "/"
559 << this->TurbineBladeName
560 << this->TimeSteps[timeStep];
561 std::vector<char> inBuf(vtkWindBladeReader::LINE_SIZE);
562
563 // only rank 0 reads this so we have to be careful
564 MPI_File tempFile;
565 char native[7] = "native";
566 char* cchar = new char[strlen(fileName.str().c_str()) + 1];
567 strcpy(cchar, fileName.str().c_str());
568 // here only rank 0 opens it : MPI_COMM_SELF
569 MPICall(MPI_File_open(MPI_COMM_SELF, cchar, MPI_MODE_RDONLY, MPI_INFO_NULL, &tempFile));
570 delete [] cchar;
571
572 std::stringstream inStr;
573 MPI_Offset i, tempSize;
574 MPI_Status status;
575
576 MPICall(MPI_File_get_size(tempFile, &tempSize));
577 MPICall(MPI_File_set_view(tempFile, 0, MPI_BYTE, MPI_BYTE, native, MPI_INFO_NULL));
578
579 for(i = 0; i < tempSize; i = i + vtkWindBladeReader::LINE_SIZE)
580 {
581 if(i + vtkWindBladeReader::LINE_SIZE > tempSize)
582 {
583 MPICall(MPI_File_read(tempFile, &(inBuf[0]), tempSize - i, MPI_BYTE, &status));
584 inStr.write(&(inBuf[0]), tempSize - i);
585 }
586 else
587 {
588 MPICall(MPI_File_read(tempFile, &(inBuf[0]), vtkWindBladeReader::LINE_SIZE, MPI_BYTE, &status));
589 inStr.write(&(inBuf[0]), vtkWindBladeReader::LINE_SIZE);
590 }
591 }
592 MPICall(MPI_File_close(&tempFile));
593
594 this->ReadBladeData(inStr);
595 }
596