Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 233191
Collapse All | Expand All

(-)ParaView3-src/VTK/IO/vtkOpenFOAMReader.cxx (-2908 / +6931 lines)
Lines 12-3488 Link Here
12
     PURPOSE.  See the above copyright notice for more information.
12
     PURPOSE.  See the above copyright notice for more information.
13
13
14
=========================================================================*/
14
=========================================================================*/
15
// Thanks to Terry Jordan of SAIC at the National Energy 
15
// Thanks to Terry Jordan of SAIC at the National Energy
16
// Technology Laboratory who developed this class.
16
// Technology Laboratory who developed this class.
17
// Please address all comments to Terry Jordan (terry.jordan@sa.netl.doe.gov)
17
// Please address all comments to Terry Jordan (terry.jordan@sa.netl.doe.gov)
18
//
18
//
19
// Token-based FoamFile format lexer/parser, performance enhancements,
20
// gzipped file and lagrangian field support by Takuya Oshima
21
// (oshima@eng.niigata-u.ac.jp)
22
//
23
// * GUI Based selection of mesh regions and fields available in the case
24
// * Minor bug fixes / Strict memory allocation checks
25
// * Minor performance enhancements
26
// by Philippose Rajan (sarith@rocketmail.com)
27
28
// version 2008-07-26
29
30
// Hijack the CRC routine of zlib to omit CRC check for gzipped files
31
// (on OSes other than Windows where the mechanism doesn't work due
32
// to pre-bound DLL symbols) if set to 1, or not (set to 0). Affects
33
// performance by about 3% - 4%.
34
#define VTK_FOAMFILE_OMIT_CRCCHECK 1
35
36
// The input/output buffer sizes for zlib in bytes.
37
#define VTK_FOAMFILE_INBUFSIZE (16384)
38
#define VTK_FOAMFILE_OUTBUFSIZE (131072)
39
#define VTK_FOAMFILE_INCLUDE_STACK_SIZE (10)
40
41
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
42
#define _CRT_SECURE_NO_WARNINGS 1
43
#endif
44
45
#if VTK_FOAMFILE_OMIT_CRCCHECK
46
#define ZLIB_INTERNAL
47
#endif
48
49
// for possible future extension of linehead-aware directives
50
#define VTK_FOAMFILE_RECOGNIZE_LINEHEAD 0
51
19
#include "vtkOpenFOAMReader.h"
52
#include "vtkOpenFOAMReader.h"
20
53
21
#include <vtkstd/string>
22
#include <vtkstd/vector>
54
#include <vtkstd/vector>
23
#include <vtksys/ios/sstream>
55
#include <vtksys/ios/sstream>
56
#include <vtk_zlib.h>
24
57
25
#include "vtkInformation.h"
58
#include "vtkCallbackCommand.h"
26
#include "vtkInformationVector.h"
27
#include "vtkErrorCode.h"
28
#include "vtkDataArraySelection.h"
29
#include "vtkStreamingDemandDrivenPipeline.h"
30
#include "vtkCellArray.h"
59
#include "vtkCellArray.h"
60
#include "vtkCellData.h"
61
#include "vtkCharArray.h"
62
#include "vtkConvexPointSet.h"
31
#include "vtkDataArraySelection.h"
63
#include "vtkDataArraySelection.h"
32
#include "vtkIntArray.h"
64
#include "vtkDirectory.h"
33
#include "vtkFloatArray.h"
34
#include "vtkDoubleArray.h"
65
#include "vtkDoubleArray.h"
35
#include "vtkPoints.h"
66
#include "vtkFloatArray.h"
36
#include "vtkCellData.h"
37
#include "vtkHexahedron.h"
67
#include "vtkHexahedron.h"
38
#include "vtkWedge.h"
68
#include "vtkInformation.h"
69
#include "vtkInformationVector.h"
70
#include "vtkIntArray.h"
71
#include "vtkMultiBlockDataSet.h"
72
#include "vtkObjectFactory.h"
73
#include "vtkPointData.h"
74
#include "vtkPoints.h"
75
#include "vtkPolyData.h"
76
#include "vtkPolygon.h"
39
#include "vtkPyramid.h"
77
#include "vtkPyramid.h"
40
#include "vtkVertex.h"
78
#include "vtkQuad.h"
79
#include "vtkSmartPointer.h"
80
#include "vtkSortDataArray.h"
81
#include "vtkStdString.h"
82
#include "vtkStreamingDemandDrivenPipeline.h"
83
#include "vtkStringArray.h"
41
#include "vtkTetra.h"
84
#include "vtkTetra.h"
42
#include "vtkConvexPointSet.h"
43
#include "vtkTriangle.h"
85
#include "vtkTriangle.h"
44
#include "vtkQuad.h"
45
#include "vtkPolygon.h"
46
#include "vtkUnstructuredGrid.h"
86
#include "vtkUnstructuredGrid.h"
47
#include "vtkMultiBlockDataSet.h"
87
#include "vtkVertex.h"
48
#include "vtkUnstructuredGridAlgorithm.h"
88
#include "vtkWedge.h"
49
#include "vtkObjectFactory.h"
89
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
50
#include "vtkDirectory.h"
90
#include "vtksys/DateStamp.h"
51
91
#endif
52
#include <ctype.h>
53
#include <sys/stat.h>
54
92
55
#ifdef VTK_USE_ANSI_STDLIB
93
#if !(defined(_WIN32) && !defined(__CYGWIN__) || defined(__LIBCATAMOUNT__))
56
#define VTK_IOS_NOCREATE
94
// for getpwnam() / getpwuid()
57
#else
95
#include <sys/types.h>
58
#define VTK_IOS_NOCREATE | ios::nocreate
96
#include <pwd.h>
97
// for getuid()
98
#include <unistd.h>
59
#endif
99
#endif
100
// for fabs()
101
#include <math.h>
60
102
61
vtkCxxRevisionMacro(vtkOpenFOAMReader, "$Revision: 1.12 $");
103
vtkCxxRevisionMacro(vtkOpenFOAMReader, "$Revision: 1.7.2.2 $");
62
vtkStandardNewMacro(vtkOpenFOAMReader);
104
vtkStandardNewMacro(vtkOpenFOAMReader);
63
105
64
struct stdString
106
#if VTK_FOAMFILE_OMIT_CRCCHECK
107
uLong ZEXPORT crc32(uLong, const Bytef *, uInt)
108
{ return 0; }
109
#endif
110
111
template<typename T> class objectVector: public vtkstd::vector<T>
65
{
112
{
66
  vtkstd::string value;
113
  typedef vtkstd::vector<T> Superclass;
114
115
public:
116
  ~objectVector()
117
  {
118
    for(size_t arrayI = 0; arrayI < Superclass::size(); arrayI++)
119
      {
120
      if(Superclass::operator[](arrayI) != NULL)
121
        {
122
        Superclass::operator[](arrayI)->Delete();
123
        }
124
      }
125
  }
67
};
126
};
68
127
69
struct stringVector
128
class intArrayVector: public objectVector<vtkIntArray*> {};
129
class unstructuredGridVector: public objectVector<vtkUnstructuredGrid*> {};
130
typedef objectVector<vtkPolyData*> polyDataVector;
131
typedef objectVector<vtkStringArray*> stringArrayVector;
132
133
struct vtkOpenFOAMReader::intVectorVector
70
{
134
{
71
  vtkstd::vector< vtkstd::string > value;
135
private:
136
  vtkIntArray *body_, *indices_;
137
  int nElements_;
138
  void clear() { indices_->Delete(); body_->Delete(); }
139
  intVectorVector();
140
141
public:
142
  intVectorVector(const intVectorVector &ivv)
143
    : body_(vtkIntArray::New()), indices_(vtkIntArray::New()),
144
    nElements_(ivv.nElements_)
145
  {
146
    indices_->DeepCopy(ivv.indices_); // vtkDataArrays do not have ShallowCopy
147
    body_->DeepCopy(ivv.body_);
148
  }
149
  intVectorVector(const int nElements, const int bodyLength)
150
    : body_(vtkIntArray::New()), indices_(vtkIntArray::New()),
151
    nElements_(nElements)
152
  {
153
    indices_->SetNumberOfValues(nElements + 1);
154
    body_->SetNumberOfValues(bodyLength);
155
  }
156
157
  ~intVectorVector() { clear(); }
158
159
  // GetSize() returns all allocated size (Size) while GetDataSize()
160
  // returns actually used size (MaxId * nComponents)
161
  int bodySize() const { return body_->GetSize(); }
162
  // note that vtkIntArray::Resize() allocates (current size + new
163
  // size) bytes if current size < new size
164
  void resizeBody(const int bodyLength) { body_->Resize(bodyLength); }
165
  int *setIndex(const int i, const int bodyI)
166
    { return body_->GetPointer(*indices_->GetPointer(i) = bodyI); }
167
  void setValue(const int bodyI, int value) { body_->SetValue(bodyI, value); }
168
  const int *operator[](const int i) const
169
    { return body_->GetPointer(indices_->GetValue(i)); }
170
  int size(const int i) const
171
    { return indices_->GetValue(i + 1) - indices_->GetValue(i); }
172
  int nElements() const { return nElements_; }
72
};
173
};
73
174
74
struct intVector
175
struct vtkFoamBoundaryEntry
75
{
176
{
76
  vtkstd::vector< int > value;
177
  vtkStdString boundaryName;
178
  int nFaces, startFace, allBoundariesStartFace;
179
  bool isActive, isPhysicalBoundary;
77
};
180
};
78
181
79
struct intVectorVector
182
struct vtkOpenFOAMReader::vtkFoamBoundaryDict
183
  : public vtkstd::vector<vtkFoamBoundaryEntry>
80
{
184
{
81
  vtkstd::vector< vtkstd::vector< int > > value;
185
  // we need to keep the path to time directory where the current mesh
186
  // is read from, since boundaryDict may be accessed multiple times
187
  // at a timestep for patch selections
188
  vtkStdString timeDir;
82
};
189
};
83
190
84
struct faceVectorVector
191
//-----------------------------------------------------------------------------
192
// class vtkFoamError
193
// class for exception-carrying object
194
struct vtkOpenFOAMReader::vtkFoamError: public vtkStdString
85
{
195
{
86
  vtkstd::vector< vtkstd::vector< face > > value;
196
public:
197
  vtkFoamError(): vtkStdString() {}
198
  vtkFoamError(const vtkFoamError& e): vtkStdString(e) {}
199
  ~vtkFoamError() {}
200
  // a super-easy way to make use of operator<<()'s defined in
201
  // vtksys_ios::ostringstream class
202
  template <class T> vtkFoamError& operator<<(const T& t)
203
  { vtksys_ios::ostringstream os; os << t; operator+=(os.str()); return *this; }
87
};
204
};
88
205
89
vtkOpenFOAMReader::vtkOpenFOAMReader()
206
//-----------------------------------------------------------------------------
207
// class vtkFoamToken
208
// token class which also works as container for list types
209
// - a word token is treated as a string token for simplicity
210
// - handles only atomic types. Handling of list types are left to the
211
//   derived classes.
212
struct vtkOpenFOAMReader::vtkFoamToken
90
{
213
{
91
  vtkDebugMacro(<<"Constructor");
214
public:
92
  this->SetNumberOfInputPorts(0);
215
  enum tokenType
93
216
  {
94
  //INTIALIZE FILE NAME
217
    // undefined type
95
  this->FileName = NULL;
218
    UNDEFINED,
96
219
    // atomic types
97
  //VTK CLASSES
220
    PUNCTUATION, LABEL, SCALAR, STRING, IDENTIFIER,
98
  this->Points = vtkPoints::New();
221
    // vtkObject-derived list types
99
  this->CellDataArraySelection = vtkDataArraySelection::New();
222
    STRINGLIST, LABELLIST, SCALARLIST, VECTORLIST,
100
223
    // original list types
101
  //DATA COUNTS
224
    LABELLISTLIST, ENTRYVALUELIST, EMPTYLIST, DICTIONARY,
102
  this->NumFaces = 0;
225
    // exceptional state
103
  this->NumPoints = 0;
226
    UNIFORMLABELLIST, UNIFORMSCALARLIST,
104
  this->NumCells = 0;
227
    // error state
105
228
    ERROR
106
  this->TimeStepData = new stringVector;
229
  };
107
  this->Path = new stdString;
230
108
  this->PathPrefix = new stdString;
231
protected:
109
  this->PolyMeshPointsDir = new stringVector;
232
  tokenType type_;
110
  this->PolyMeshFacesDir = new stringVector;
233
  union
111
  this->BoundaryNames = new stringVector;
234
  {
112
  this->PointZoneNames = new stringVector;
235
    char char_;
113
  this->FaceZoneNames = new stringVector;
236
    int int_;
114
  this->CellZoneNames = new stringVector;
237
    double double_;
115
238
    vtkStdString* string_;
116
  this->FacePoints = new intVectorVector;
239
    vtkObjectBase *vtkObjectPtr_;
117
  this->FacesOwnerCell = new intVectorVector;
240
    // vtkObject-derived list types
118
  this->FacesNeighborCell = new intVectorVector;
241
    vtkIntArray *labelListPtr_;
119
  this->FacesOfCell = new faceVectorVector;
242
    vtkFloatArray *scalarListPtr_, *vectorListPtr_;
120
  this->SizeOfBoundary = new intVector;
243
    vtkStringArray *stringListPtr_;
121
244
    // original list types
122
  //DATA TIMES
245
    intVectorVector *labelListListPtr_;
123
  this->NumberOfTimeSteps = 0;
246
    vtkstd::vector<vtkFoamEntryValue*> *entryValuePtrs_;
124
  this->Steps = NULL;
247
    vtkFoamDict *dictPtr_;
125
  this->TimeStep = 0;
248
  };
126
  this->TimeStepRange[0] = 0;
249
127
  this->TimeStepRange[1] = 0;
250
  void clear()
128
  this->RequestInformationFlag = true;
251
  {
129
}
252
    if(type_ == STRING || type_ == IDENTIFIER)
253
      {
254
      delete string_;
255
      }
256
  }
257
258
  void assignData(const vtkFoamToken& value)
259
  {
260
    switch(value.type_)
261
      {
262
      case PUNCTUATION:
263
        char_ = value.char_;
264
        break;
265
      case LABEL:
266
        int_ = value.int_;
267
        break;
268
      case SCALAR:
269
        double_ = value.double_;
270
        break;
271
      case STRING: case IDENTIFIER:
272
        string_ = new vtkStdString(*value.string_);
273
      }
274
  }
275
276
public:
277
  vtkFoamToken(): type_(UNDEFINED) {}
278
  vtkFoamToken(const vtkFoamToken& value): type_(value.type_)
279
    { assignData(value); }
280
  ~vtkFoamToken() { clear(); }
281
282
  const tokenType type() const { return type_; }
283
284
  template<typename T> bool is() const;
285
  template<typename T> T to() const;
286
287
  const vtkStdString toString() const { return *string_; }
288
  const vtkStdString toIdentifier() const { return *string_; }
289
290
  void setBad() { clear(); type_ = ERROR; }
291
  void setIdentifier(const vtkStdString& idString)
292
  { operator=(idString); type_ = IDENTIFIER; }
293
294
  void operator=(const char value)
295
  { clear(); type_ = PUNCTUATION; char_ = value; }
296
  void operator=(const int value)
297
  { clear(); type_ = LABEL; int_ = value; }
298
  void operator=(const double value)
299
  { clear(); type_ = SCALAR; double_ = value; }
300
  void operator=(const char *value)
301
  { clear(); type_ = STRING; string_ = new vtkStdString(value); }
302
  void operator=(const vtkStdString& value)
303
  { clear(); type_ = STRING; string_ = new vtkStdString(value); }
304
  void operator=(const vtkFoamToken& value)
305
  { clear(); type_ = value.type_; assignData(value); }
306
  bool operator==(const char value) const
307
  { return type_ == PUNCTUATION && char_ == value; }
308
  bool operator==(const int value) const
309
  { return type_ == LABEL && int_ == value; }
310
  bool operator==(const vtkStdString& value) const
311
  { return type_ == STRING && *string_ == value; }
312
  bool operator!=(const vtkStdString& value) const
313
  { return type_ != STRING || *string_ != value; }
314
  bool operator!=(const char value) const { return !operator==(value); }
315
316
  friend vtksys_ios::ostringstream& operator<<(vtksys_ios::ostringstream& str,
317
    const vtkFoamToken& value)
318
  {
319
    switch(value.type())
320
      {
321
      case ERROR:
322
        str << "badToken (an unexpected EOF?)";
323
        break;
324
      case PUNCTUATION:
325
        str << value.char_;
326
        break;
327
      case LABEL:
328
        str << value.int_;
329
        break;
330
      case SCALAR:
331
        str << value.double_;
332
        break;
333
      case STRING: case IDENTIFIER:
334
        str << *value.string_;
335
        break;
336
      }
337
    return str;
338
  }
339
};
130
340
131
vtkOpenFOAMReader::~vtkOpenFOAMReader()
341
template<> inline bool vtkOpenFOAMReader::vtkFoamToken::is<int>() const
342
{ return type_ == LABEL; }
343
template<> inline bool vtkOpenFOAMReader::vtkFoamToken::is<float>() const
344
{ return type_ == LABEL || type_ == SCALAR; }
345
template<> inline bool vtkOpenFOAMReader::vtkFoamToken::is<double>() const
346
{ return type_ == SCALAR; }
347
template<> inline int vtkOpenFOAMReader::vtkFoamToken::to() const
348
{ return int_; }
349
template<> inline float vtkOpenFOAMReader::vtkFoamToken::to() const
350
{ return type_ == LABEL ? int_ : double_; }
351
template<> inline double vtkOpenFOAMReader::vtkFoamToken::to() const
352
{ return type_ == LABEL ? int_ : double_; }
353
354
//-----------------------------------------------------------------------------
355
// class vtkFoamFileStack
356
// list of variables that have to be saved when a file is included.
357
struct vtkOpenFOAMReader::vtkFoamFileStack
132
{
358
{
133
  vtkDebugMacro(<<"DeConstructor");
359
protected:
134
  this->Points->Delete();
360
  vtkStdString fileName_;
135
  this->CellDataArraySelection->Delete();
361
  FILE *file_;
136
  this->SetFileName(0);
362
  bool isCompressed_;
137
  delete [] this->Steps;
363
  z_stream z_;
364
  int zStatus_;
365
  int lineNumber_;
366
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
367
  bool wasNewline_;
368
#endif
138
369
139
  delete this->TimeStepData;
370
  // buffer pointers. using raw pointers for performance reason.
140
  delete this->Path;
371
  unsigned char *inbuf_;
141
  delete this->PathPrefix;
372
  unsigned char *outbuf_;
142
  delete this->PolyMeshPointsDir;
373
  unsigned char *bufPtr_;
143
  delete this->PolyMeshFacesDir;
374
  unsigned char *bufEndPtr_;
144
  delete this->BoundaryNames;
375
145
  delete this->PointZoneNames;
376
  vtkFoamFileStack()
146
  delete this->FaceZoneNames;
377
    : fileName_(), file_(NULL), isCompressed_(false), zStatus_(Z_OK),
147
  delete this->CellZoneNames;
378
    lineNumber_(0),
148
  delete this->FacePoints;
379
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
149
  delete this->FacesOwnerCell;
380
    wasNewline_(true),
150
  delete this->FacesNeighborCell;
381
#endif
151
  delete this->FacesOfCell;
382
    inbuf_(NULL), outbuf_(NULL), bufPtr_(NULL), bufEndPtr_(NULL)
152
  delete this->SizeOfBoundary;
383
    { z_.zalloc = Z_NULL; z_.zfree = Z_NULL; z_.opaque = Z_NULL; }
153
}
154
384
155
int vtkOpenFOAMReader::RequestData(
385
  void reset()
156
  vtkInformation *vtkNotUsed(request),
386
  {
157
  vtkInformationVector **vtkNotUsed(inputVector),
387
    // path_ = "";
158
  vtkInformationVector *outputVector)
388
    file_ = NULL;
159
{
389
    isCompressed_ = false;
160
  vtkDebugMacro(<<"Request Data");
390
    // zStatus_ = Z_OK;
161
  vtkInformation* outInfo = outputVector->GetInformationObject(0);
391
    z_.zalloc = Z_NULL;
162
  vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::SafeDownCast(
392
    z_.zfree = Z_NULL;
163
    outInfo->Get(vtkMultiBlockDataSet::DATA_OBJECT()));
393
    z_.opaque = Z_NULL;
164
  if(!this->FileName)
394
    // lineNumber_ = 0;
165
    {
395
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
166
    vtkErrorMacro("FileName has to be specified!");
396
    wasNewline_ = true;
167
    return 0;
397
#endif
168
    }
169
  this->CreateDataSet(output);
170
  return 1;
171
}
172
398
173
void vtkOpenFOAMReader::PrintSelf(ostream& os, vtkIndent indent)
399
    inbuf_ = NULL;
174
{
400
    outbuf_ = NULL;
175
  vtkDebugMacro(<<"Print Self");
401
    // bufPtr_ = NULL;
176
  this->Superclass::PrintSelf(os,indent);
402
    // bufEndPtr_ = NULL;
177
  os << indent << "File Name: "
403
  }
178
     << (this->FileName ? this->FileName : "(none)") << "\n";
404
179
  os << indent << "Number Of Nodes: " << this->NumPoints << "\n";
405
public:
180
  os << indent << "Number Of Cells: " << this->NumCells << "\n";
406
  const vtkStdString& fileName() const { return fileName_; }
181
  os << indent << "Number of Time Steps: " << this->NumberOfTimeSteps << endl;
407
  int lineNumber() const { return lineNumber_; }
182
  os << indent << "TimeStepRange: " 
408
};
183
     << this->TimeStepRange[0] << " - " << this->TimeStepRange[1]
184
     << endl;
185
  os << indent << "TimeStep: " << this->TimeStep << endl;
186
  return;
187
}
188
409
189
int vtkOpenFOAMReader::RequestInformation(
410
//-----------------------------------------------------------------------------
190
  vtkInformation *vtkNotUsed(request),
411
// class vtkFoamFile
191
  vtkInformationVector **vtkNotUsed(inputVector),
412
// read and tokenize the input.
192
  vtkInformationVector *outputVector)
413
struct vtkOpenFOAMReader::vtkFoamFile: public vtkFoamFileStack
193
{
414
{
194
  if(!this->FileName)
415
public:
195
    {
416
  // #inputMode values
196
    vtkErrorMacro("FileName has to be specified!");
417
  enum inputModes { INPUT_MODE_MERGE, INPUT_MODE_OVERWRITE, INPUT_MODE_ERROR };
197
    return 0;
198
    }
199
  vtkDebugMacro(<<"Request Info");
200
  if(RequestInformationFlag)
201
    {
202
    vtkDebugMacro(<<this->FileName);
203
    this->Path->value.append(this->FileName);
204
    this->ReadControlDict();
205
    this->TimeStepRange[0] = 0;
206
    this->TimeStepRange[1] = this->NumberOfTimeSteps-1;
207
    this->PopulatePolyMeshDirArrays();
208
    outputVector->GetInformationObject(0)->Set(
209
      vtkStreamingDemandDrivenPipeline::TIME_STEPS(), this->Steps,
210
      this->NumberOfTimeSteps);
211
    this->RequestInformationFlag = false;
212
    }
213
418
214
  //Add scalars and vectors to metadata
419
private:
215
  //create path to current time step
420
  bool is13Positions_;
216
  vtksys_ios::stringstream tempPath;
421
  inputModes inputMode_;
217
  tempPath << this->PathPrefix->value.c_str();
218
  tempPath << this->Steps[this->TimeStep];
219
422
220
  //open the directory and get num of files
423
  // inclusion handling
221
  int numSolvers;
424
  vtkFoamFileStack *stack_[VTK_FOAMFILE_INCLUDE_STACK_SIZE];
222
  vtkDirectory * directory = vtkDirectory::New();
425
  int stackI_;
223
  int opened = directory->Open(tempPath.str().c_str());
426
  vtkStdString casePath_;
224
  if(opened)
225
    {
226
    numSolvers = directory->GetNumberOfFiles();
227
    }
228
  else
229
    {
230
    numSolvers = -1; //no dir
231
    }
232
427
233
  //clear prior timestep data
428
  // declare and define as private
234
  this->TimeStepData->value.clear();
429
  vtkFoamFile();
430
  bool inflateNext(unsigned char *buf, int requestSize);
431
  int nextTokenHead();
432
  // hacks to keep exception throwing / recursive codes out-of-line to make
433
  // putBack(), getc() and readExpecting() inline expandable
434
  void throwDuplicatedPutBackException();
435
  void throwUnexpectedEOFException();
436
  void throwUnexpectedNondigitCharExecption(const int c);
437
  void throwUnexpectedTokenException(const char, const int c);
438
  int readNext();
235
439
236
  //loop over all files and locate
440
  void putBack(const int c)
237
  //volScalars and volVectors
441
  {
238
  for(int j = 0; j < numSolvers; j++)
442
    if(--bufPtr_ < outbuf_)
239
    {
240
    const char * tempSolver = directory->GetFile(j);
241
    if(tempSolver != (char *)"polyMesh")
242
      {
443
      {
243
      if(tempSolver != (char *)"." && tempSolver != (char *)"..")
444
      throwDuplicatedPutBackException();
244
        {
245
        vtkstd::string type(this->GetDataType(tempPath.str().c_str(),
246
                                              tempSolver));
247
        if(strcmp(type.c_str(), "Scalar") == 0)
248
        {
249
          this->TimeStepData->value.push_back(vtkstd::string(tempSolver));
250
          this->CellDataArraySelection->AddArray(tempSolver);
251
          }
252
        else if(strcmp(type.c_str(), "Vector") == 0)
253
          {
254
          this->TimeStepData->value.push_back(vtkstd::string(tempSolver));
255
          this->CellDataArraySelection->AddArray(tempSolver);
256
          }
257
        }
258
      }
445
      }
259
    }
446
    *bufPtr_ = c;
260
447
  }
261
  directory->Delete();
262
  return 1;
263
}
264
265
//
266
// CELL METHODS
267
//
268
int vtkOpenFOAMReader::GetNumberOfCellArrays()
269
{
270
  return this->CellDataArraySelection->GetNumberOfArrays();
271
}
272
273
const char* vtkOpenFOAMReader::GetCellArrayName(int index)
274
{
275
  return this->CellDataArraySelection->GetArrayName(index);
276
}
277
278
int vtkOpenFOAMReader::GetCellArrayStatus(const char* name)
279
{
280
  return this->CellDataArraySelection->ArrayIsEnabled(name);
281
}
282
283
void vtkOpenFOAMReader::SetCellArrayStatus(const char* name, int status)
284
{
285
  if(status)
286
    {
287
    this->CellDataArraySelection->EnableArray(name);
288
    }
289
  else
290
    {
291
    this->CellDataArraySelection->DisableArray(name);
292
    }
293
  return;
294
}
295
448
296
void vtkOpenFOAMReader::DisableAllCellArrays()
449
  // get a character
297
{
450
  int getc() { return bufPtr_ == bufEndPtr_ ? readNext() : *bufPtr_++; }
298
  this->CellDataArraySelection->DisableAllArrays();
299
  return;
300
}
301
451
302
void vtkOpenFOAMReader::EnableAllCellArrays()
452
  vtkFoamError stackString()
303
{
453
  {
304
  this->CellDataArraySelection->EnableAllArrays();
454
    vtksys_ios::ostringstream os;
305
  return;
455
    if(stackI_ > 0)
306
}
456
      {
457
      os << "\n included";
307
458
308
// ****************************************************************************
459
      for(int stackI = stackI_ - 1; stackI >= 0; stackI--)
309
//  Method: vtkOpenFOAMReader::CombineOwnerNeigbor
460
        {
310
//
461
        os << " from line " << stack_[stackI]->lineNumber() << " of "
311
//  Purpose:
462
          << stack_[stackI]->fileName() << "\n";
312
//  add Owner faces to the faces of a cell and then add the neighor faces
463
        }
313
//
464
      os << ": ";
314
// ****************************************************************************
465
      }
315
void vtkOpenFOAMReader::CombineOwnerNeigbor()
466
    return vtkFoamError() << os.str();
316
{
467
  }
317
  vtkDebugMacro(<<"Combine owner & neighbor faces");
318
  //reintialize faces of the cells
319
  face tempFace;
320
  this->FacesOfCell->value.clear();
321
  this->FacesOfCell->value.resize(this->NumCells);
322
468
323
  //add owner faces to cell
469
  bool closeIncludedFile()
324
  for(int i = 0; i < (int)this->FacesOwnerCell->value.size(); i++)
470
  {
325
    {
471
    if(stackI_ == 0)
326
    for(int j = 0; j < (int)this->FacesOwnerCell->value[i].size(); j++)
327
      {
472
      {
328
      tempFace.faceIndex = this->FacesOwnerCell->value[i][j];
473
      return false;
329
      tempFace.neighborFace = false;
330
      this->FacesOfCell->value[i].push_back(tempFace);
331
      }
474
      }
332
    }
475
    clear();
476
    stackI_--;
477
    // use the default bitwise assignment operator
478
    vtkFoamFileStack::operator=(*stack_[stackI_]);
479
    delete stack_[stackI_];
480
    return true;
481
  }
333
482
334
  //add neighbor faces to cell
483
  void clear()
335
  for(int i = 0; i < (int)this->FacesNeighborCell->value.size(); i++)
484
  {
336
    {
485
    if(isCompressed_)
337
    for(int j = 0; j < (int)this->FacesNeighborCell->value[i].size(); j++)
338
      {
486
      {
339
      tempFace.faceIndex = this->FacesNeighborCell->value[i][j];
487
      inflateEnd(&z_);
340
      tempFace.neighborFace = true;
341
      this->FacesOfCell->value[i].push_back(tempFace);
342
      }
488
      }
343
    }
344
345
  //clean up memory
346
  this->FacesOwnerCell->value.clear();
347
  this->FacesNeighborCell->value.clear();
348
  return;
349
}
350
489
351
// ****************************************************************************
490
    delete [] inbuf_;
352
//  Method: vtkOpenFOAMReader::MakeInternalMesh
491
    delete [] outbuf_;
353
//
492
    inbuf_ = outbuf_ = NULL;
354
//  Purpose:
355
//  derive cell types and create the internal mesh
356
//
357
// ****************************************************************************
358
vtkUnstructuredGrid * vtkOpenFOAMReader::MakeInternalMesh()
359
{
360
  vtkDebugMacro(<<"Make internal mesh");
361
  //initialize variables
362
  bool foundDup = false;
363
  vtkstd::vector< int > cellPoints;
364
  vtkstd::vector< int > tempFaces[2];
365
  vtkstd::vector< int > firstFace;
366
  int pivotPoint = 0;
367
  int i, j, k, l, pCount;
368
  int faceCount = 0;
369
493
370
  //Create Mesh
494
    if(file_ != NULL)
371
  vtkUnstructuredGrid *  internalMesh = vtkUnstructuredGrid::New();
495
      {
372
  //loop through each cell, derive type and insert it into the mesh
496
      fclose(file_);
373
  //hexahedron, prism, pyramid, tetrahedron, wedge&tetWedge
497
      file_ = NULL;
374
  for(i = 0; i < (int)this->FacesOfCell->value.size(); i++)  //each cell
498
      }
375
    {
499
    // don't reset the line number so that the last line number is
500
    // retained after close
501
    // lineNumber_ = 0;
502
  }
376
503
377
    //calculate the total points for the cell
504
  const vtkStdString extractPath(const vtkStdString& path) const
378
    //used to derive cell type
505
  {
379
    int totalPointCount = 0;
506
#if defined(_WIN32) && PARAVIEW_VERSION_MAJOR >= 3
380
    for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++)  //each face
507
    const vtkStdString pathFindSeparator = "/\\", pathSeparator = "\\";
508
#else
509
    const vtkStdString pathFindSeparator = "/", pathSeparator = "/";
510
#endif
511
    const size_t pos = path.find_last_of(pathFindSeparator);
512
    return pos == vtkStdString::npos ? vtkStdString(".") + pathSeparator
513
      : path.substr(0, pos + 1);
514
  }
515
516
public:
517
  vtkFoamFile(const vtkStdString& casePath)
518
    : vtkFoamFileStack(), is13Positions_(false), inputMode_(INPUT_MODE_ERROR),
519
      stackI_(0), casePath_(casePath)
520
    {}
521
  ~vtkFoamFile() { close(); }
522
523
  void setIs13Positions(const bool is13Positions)
524
    { is13Positions_ = is13Positions; }
525
  const bool getIs13Positions() const { return is13Positions_; }
526
  inputModes getInputMode() const { return inputMode_; }
527
  const vtkStdString casePath() const { return casePath_; }
528
  const vtkStdString filePath() const { return extractPath(fileName_); }
529
530
  vtkStdString expandPath(const vtkStdString& pathIn,
531
    const vtkStdString& defaultPath)
532
  {
533
    vtkStdString expandedPath;
534
    bool isExpanded = false, wasPathSeparator = true;
535
    const int nChars = pathIn.length();
536
    for(int charI = 0; charI < nChars;)
537
      {
538
      char c = pathIn[charI];
539
      switch(c)
540
        {
541
        case '$': // $-variable expansion
542
          {
543
          vtkStdString variable;
544
          while(++charI < nChars && (isalnum(pathIn[charI])
545
            || pathIn[charI] == '_'))
546
            {
547
            variable += pathIn[charI];
548
            }
549
          if(variable == "FOAM_CASE") // discard path until the variable
550
            {
551
            expandedPath = casePath_;
552
	    wasPathSeparator = true;
553
	    isExpanded = true;
554
            }
555
          else
556
            {
557
            const char *value = getenv(variable.c_str());
558
            if(value != NULL)
559
              {
560
              expandedPath += value;
561
              }
562
            const size_t len = expandedPath.length();
563
            if(len > 0)
564
              {
565
              const char c = expandedPath[len - 1];
566
              wasPathSeparator = (c == '/' || c == '\\');
567
              }
568
            else
569
              {
570
              wasPathSeparator = false;
571
              }
572
            }
573
          }
574
          break;
575
        case '~': // home directory expansion
576
	  // not using kwsys::SystemTools::ConvertToUnixSlashes() for
577
	  // a bit better handling of "~"
578
	  if(wasPathSeparator)
579
            {
580
            vtkStdString userName;
581
            while(++charI < nChars && (pathIn[charI] != '/'
582
              && pathIn[charI] != '\\') && pathIn[charI] != '$')
583
              {
584
              userName += pathIn[charI];
585
              }
586
            if(userName == "")
587
              {
588
	      const char *homePtr = getenv("HOME");
589
	      if(homePtr == NULL)
590
		{
591
#if defined(_WIN32) && !defined(__CYGWIN__) || defined(__LIBCATAMOUNT__)
592
		expandedPath = "";
593
#else
594
		const struct passwd *pwentry = getpwuid(getuid());
595
	        if(pwentry == NULL)
596
		  {
597
                  throw stackString() << "Home directory path not found";
598
		  }
599
                expandedPath = pwentry->pw_dir;
600
#endif
601
		}
602
	      else
603
		{
604
	        expandedPath = homePtr;
605
		}
606
              }
607
            else
608
              {
609
#if defined(_WIN32) && !defined(__CYGWIN__) || defined(__LIBCATAMOUNT__)
610
	      const char *homePtr = getenv("HOME");
611
              expandedPath = extractPath(homePtr ? homePtr : "") + userName;
612
#else
613
	      if(userName == "OpenFOAM")
614
		{
615
		// so far only "~/.OpenFOAM" expansion is supported
616
		const char *homePtr = getenv("HOME");
617
		if(homePtr == NULL)
618
		  {
619
		  expandedPath = "";
620
		  }
621
		else
622
		  {
623
		  expandedPath = vtkStdString(homePtr) + "/.OpenFOAM";
624
		  }
625
		}
626
	      else
627
		{
628
		const struct passwd *pwentry = getpwnam(userName.c_str());
629
	        if(pwentry == NULL)
630
		  {
631
		  throw stackString() << "Home directory for user "
632
                    << userName.c_str() << " not found";
633
		  }
634
                expandedPath = pwentry->pw_dir;
635
		}
636
#endif
637
              }
638
	    wasPathSeparator = false;
639
            isExpanded = true;
640
	    break;
641
            }
642
	  // fall through
643
        default:
644
	  wasPathSeparator = (c == '/' || c == '\\');
645
          expandedPath += c;
646
          charI++;
647
        }
648
      }
649
    if(isExpanded || expandedPath.substr(0, 1) == "/"
650
      || expandedPath.substr(0, 1) == "\\")
651
      {
652
      return expandedPath;
653
      }
654
    else
381
      {
655
      {
382
      totalPointCount += 
656
      return defaultPath + expandedPath;
383
        (int)this->FacePoints->
384
                 value[this->FacesOfCell->value[i][j].faceIndex].size();
385
      }
657
      }
658
  }
386
659
387
    // using cell type - order points, create cell, & add to mesh
660
  void includeFile(const vtkStdString& includedFileName,
388
    //OFhex | vtkHexahedron
661
    const vtkStdString& defaultPath)
389
    if (totalPointCount == 24)
662
  {
663
    if(stackI_ >= VTK_FOAMFILE_INCLUDE_STACK_SIZE)
664
      {
665
      throw stackString() << "Exceeded maximum #include recursions of "
666
        << VTK_FOAMFILE_INCLUDE_STACK_SIZE;
667
      }
668
    // use the default bitwise copy constructor
669
    stack_[stackI_++] = new vtkFoamFileStack(*this);
670
    vtkFoamFileStack::reset();
671
672
    open(expandPath(includedFileName, defaultPath));
673
  }
674
675
  // the tokenizer
676
  // returns true if success, false if encountered EOF
677
  bool read(vtkFoamToken& token)
678
  {
679
    // expanded the outermost loop in nextTokenHead() for performance
680
    int c;
681
    while(isspace(c = getc())) // isspace() accepts -1 as EOF
682
      {
683
      if(c == '\n')
684
        {
685
        ++lineNumber_;
686
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
687
        wasNewline_ = true;
688
#endif
689
        }
690
      }
691
    if(c == 47) // '/' == 47
692
      {
693
      putBack(c);
694
      c = nextTokenHead();
695
      }
696
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
697
    if(c != '#')
390
      {
698
      {
391
      faceCount = 0;
699
      wasNewline_ = false;
700
      }
701
#endif
392
702
393
      //get first face
703
    const int MAXLEN =  1024;
394
      for(j = 0; j <
704
    char buf[MAXLEN + 1];
395
        (int)this->FacePoints->
705
    int charI = 0;
396
                    value[this->FacesOfCell->value[i][0].faceIndex].size(); j++)
706
    switch(c)
397
        {
707
      {
398
        firstFace.push_back(this->FacePoints->value[
708
      case '(': case ')':
399
          this->FacesOfCell->value[i][0].faceIndex][j]);
709
        // high-priority punctuation token
710
        token = (char)c;
711
        return true;
712
      case '1': case '2': case '3': case '4': case '5': case '6': case '7':
713
      case '8': case '9': case '0': case '-':
714
        // undetermined number token
715
        do
716
          {
717
          buf[charI++] = c;
718
          } while(isdigit(c = getc()) && charI < MAXLEN);
719
        if(c != '.' && c != 'e' && c != 'E' && charI < MAXLEN && c != EOF)
720
          {
721
          // label token
722
          buf[charI] = '\0';
723
          token = static_cast<int>(strtol(buf, NULL, 10));
724
          putBack(c);
725
          return true;
726
          }
727
        // fall through
728
      case '.':
729
        // scalar token
730
        if(c == '.' && charI < MAXLEN)
731
          {
732
          // read decimal fraction part
733
          buf[charI++] = c;
734
          while(isdigit(c = getc()) && charI < MAXLEN)
735
            {
736
            buf[charI++] = c;
737
            }
738
          }
739
        if((c == 'e' || c == 'E') && charI < MAXLEN)
740
          {
741
          // read exponent part
742
          buf[charI++] = c;
743
          if(((c = getc()) == '+' || c == '-') && charI < MAXLEN)
744
            {
745
            buf[charI++] = c;
746
            c = getc();
747
            }
748
          while(isdigit(c) && charI < MAXLEN)
749
            {
750
            buf[charI++] = c;
751
            c = getc();
752
            }
753
          }
754
        if(charI == 1 && buf[0] == '-')
755
          {
756
          token = '-';
757
          putBack(c);
758
          return true;
759
          }
760
        buf[charI] = '\0';
761
        token = strtod(buf, NULL);
762
        putBack(c);
763
        break;
764
      case ';': case '{': case '}': case '[': case ']': case ':': case ',':
765
      case '=': case '+': case '*': case '/':
766
        // low-priority punctuation token
767
        token = (char)c;
768
        return true;
769
      case '"':
770
        {
771
        // string token
772
        bool wasEscape = false;
773
        while((c = getc()) != EOF && charI < MAXLEN)
774
          {
775
          if(c == '\\' && !wasEscape)
776
            {
777
            wasEscape = true;
778
            continue;
779
            }
780
          else if(c == '"' && !wasEscape)
781
            {
782
            break;
783
            }
784
          else if(c == '\n')
785
            {
786
            ++lineNumber_;
787
            if(!wasEscape)
788
              {
789
              throw stackString() << "Unescaped newline in string constant";
790
              }
791
            }
792
          buf[charI++] = c;
793
          wasEscape = false;
794
          }
795
        buf[charI] = '\0';
796
        token = buf;
797
        }
798
        break;
799
      case EOF:
800
        // end of file
801
        token.setBad();
802
        return false;
803
      case '$':
804
        {
805
        vtkFoamToken identifierToken;
806
        if(!read(identifierToken))
807
          {
808
          throw stackString() << "Unexpected EOF reading identifier";
809
          }
810
        if(identifierToken.type() != vtkFoamToken::STRING)
811
          {
812
          throw stackString() << "Expected a word, found " << identifierToken;
813
          }
814
        token.setIdentifier(identifierToken.toString());
815
        return true;
816
        }
817
      case '#':
818
        {
819
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
820
        // placing #-directives in the middle of a line looks like
821
        // valid for the genuine OF 1.5 parser
822
        if(!wasNewline_)
823
          {
824
          throw stackString()
825
            << "Encountered #-directive in the middle of a line";
826
          }
827
        wasNewline_ = false;
828
#endif
829
        // read directive
830
        vtkFoamToken directiveToken;
831
        if(!read(directiveToken))
832
          {
833
          throw stackString() << "Unexpected EOF reading directive";
834
          }
835
        if(directiveToken == "include")
836
          {
837
          vtkFoamToken fileNameToken;
838
          if(!read(fileNameToken))
839
            {
840
            throw stackString() << "Unexpected EOF reading filename";
841
            }
842
          includeFile(fileNameToken.toString(), extractPath(fileName_));
843
          }
844
        else if(directiveToken == "inputMode")
845
          {
846
          vtkFoamToken modeToken;
847
          if(!read(modeToken))
848
            {
849
            throw stackString() << "Unexpected EOF reading inputMode specifier";
850
            }
851
          if(modeToken == "merge")
852
            {
853
            inputMode_ = INPUT_MODE_MERGE;
854
            }
855
          else if(modeToken == "overwrite")
856
            {
857
            inputMode_ = INPUT_MODE_OVERWRITE;
858
            }
859
          else if(modeToken == "error" || modeToken == "default")
860
            {
861
            inputMode_ = INPUT_MODE_ERROR;
862
            }
863
          else
864
            {
865
            throw stackString() << "Expected one of inputMode specifiers "
866
              "(merge, overwrite, error, default), found " << modeToken;
867
            }
868
          }
869
        else
870
          {
871
          throw stackString() << "Unsupported directive " << directiveToken;
872
          }
873
        return read(token);
874
        }
875
      default:
876
        // parses as a word token, but gives the STRING type for simplicity
877
        int inBrace = 0;
878
        do
879
          {
880
          if(c == '(')
881
            {
882
            inBrace++;
883
            }
884
          else if(c == ')' && --inBrace == -1)
885
            {
886
            break;
887
            }
888
          buf[charI++] = c;
889
          // valid characters that constitutes a word
890
          // cf. src/OpenFOAM/primitives/strings/word/wordI.H
891
          } while((c = getc()) != EOF && !isspace(c) && c != '"' && c != '/'
892
          && c != ';' && c != '{' && c != '}' && charI < MAXLEN);
893
        buf[charI] = '\0';
894
        token = buf;
895
        putBack(c);
896
      }
897
898
    if(c == EOF)
899
      {
900
      throwUnexpectedEOFException();
901
      }
902
    if(charI == MAXLEN)
903
      {
904
      throw stackString() << "Exceeded maximum allowed length of " << MAXLEN
905
        << " chars";
906
      }
907
    return true;
908
  }
909
910
  void open(const vtkStdString& fileName)
911
  {
912
    // reset line number to indicate the beginning of the file when an
913
    // exception is thrown
914
    lineNumber_ = 0;
915
    fileName_ = fileName;
916
917
    if(file_ != NULL)
918
      {
919
      throw stackString() << "File already opened within this object";
920
      }
921
922
    if((file_ = fopen(fileName.c_str(), "rb")) == NULL)
923
      {
924
      throw stackString() << "Can't open";
925
      }
926
927
    unsigned char zMagic[2];
928
    if(fread(zMagic, 1, 2, file_) == 2
929
      && zMagic[0] == 0x1f && zMagic[1] == 0x8b)
930
      {
931
      // gzip-compressed format
932
      z_.avail_in = 0;
933
      z_.next_in = Z_NULL;
934
      // + 32 to automatically recognize gzip format
935
      if(inflateInit2(&z_, 15 + 32) == Z_OK)
936
        {
937
        isCompressed_ = true;
938
        inbuf_ = new unsigned char[VTK_FOAMFILE_INBUFSIZE];
939
        }
940
      else
941
        {
942
        fclose(file_);
943
        file_ = NULL;
944
        throw stackString() << "Can't init zstream " << (z_.msg ? z_.msg : "");
945
        }
946
      }
947
    else
948
      {
949
      // uncompressed format
950
      isCompressed_ = false;
951
      }
952
    rewind(file_);
953
954
    zStatus_ = Z_OK;
955
    outbuf_ = new unsigned char[VTK_FOAMFILE_OUTBUFSIZE + 1];
956
    bufPtr_ = outbuf_ + 1;
957
    bufEndPtr_ = bufPtr_;
958
    lineNumber_ = 1;
959
  }
960
961
  void close()
962
  {
963
    while(closeIncludedFile());
964
    clear();
965
  }
966
967
  // gzread with buffering handling
968
  int read(unsigned char *buf, const int len)
969
  {
970
    int readlen;
971
    const int buflen = bufEndPtr_ - bufPtr_;
972
    if(len > buflen)
973
      {
974
      memcpy(buf, bufPtr_, buflen);
975
      readlen = inflateNext(buf + buflen, len - buflen);
976
      if(readlen >= 0)
977
        {
978
        readlen += buflen;
979
        }
980
      else
981
        {
982
        if(buflen == 0) // return EOF
983
          {
984
          readlen = -1;
985
          }
986
        else
987
          {
988
          readlen = buflen;
989
          }
990
        }
991
      bufPtr_ = bufEndPtr_;
992
      }
993
    else
994
      {
995
      memcpy(buf, bufPtr_, len);
996
      bufPtr_ += len;
997
      readlen = len;
998
      }
999
    for(int i = 0; i < readlen; i++)
1000
      {
1001
      if(buf[i] == '\n')
1002
        {
1003
        lineNumber_++;
1004
        }
1005
      }
1006
    return readlen;
1007
  }
1008
1009
  void readExpecting(const char expected)
1010
  {
1011
    // skip prepending invalid chars
1012
    // expanded the outermost loop in nextTokenHead() for performance
1013
    int c;
1014
    while(isspace(c = getc())) // isspace() accepts -1 as EOF
1015
      {
1016
      if(c == '\n')
1017
        {
1018
        ++lineNumber_;
1019
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
1020
        wasNewline_ = true;
1021
#endif
1022
        }
1023
      }
1024
    if(c == 47) // '/' == 47
1025
      {
1026
      putBack(c);
1027
      c = nextTokenHead();
1028
      }
1029
    if(c != expected)
1030
      {
1031
      throwUnexpectedTokenException(expected, c);
1032
      }
1033
  }
1034
1035
  void readExpecting(const char* str)
1036
  {
1037
    vtkFoamToken t;
1038
    if(!read(t) || t != str)
1039
      {
1040
      throw stackString() << "Expected string \"" << str << "\", found " << t;
1041
      }
1042
  }
1043
1044
  template<class T> T readValue(); //{ return static_cast<T>(0); }
1045
};
1046
1047
int vtkOpenFOAMReader::vtkFoamFile::readNext()
1048
{
1049
  if(!inflateNext(outbuf_ + 1, VTK_FOAMFILE_OUTBUFSIZE))
1050
    {
1051
    return closeIncludedFile() ? getc() : EOF;
1052
    }
1053
  return *bufPtr_++;
1054
}
1055
1056
// specialized for reading an integer value.
1057
// not using the standard strtol() for speed reason.
1058
template<> int vtkOpenFOAMReader::vtkFoamFile::readValue()
1059
{
1060
  // skip prepending invalid chars
1061
  // expanded the outermost loop in nextTokenHead() for performance
1062
  int c;
1063
  while(isspace(c = getc())) // isspace() accepts -1 as EOF
1064
    {
1065
    if(c == '\n')
1066
      {
1067
      ++lineNumber_;
1068
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
1069
      wasNewline_ = true;
1070
#endif
1071
      }
1072
    }
1073
  if(c == 47) // '/' == 47
1074
    {
1075
    putBack(c);
1076
    c = nextTokenHead();
1077
    }
1078
1079
  int nonNegative = c - 45; // '-' == 45
1080
  if(nonNegative == 0 || c == 43) // '+' == 43
1081
    {
1082
    c = getc();
1083
    if(c == '\n')
1084
      {
1085
      ++lineNumber_;
1086
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
1087
      wasNewline_ = true;
1088
#endif
1089
      }
1090
    }
1091
1092
  if(!isdigit(c)) // isdigit() accepts -1 as EOF
1093
    {
1094
    if(c == EOF)
1095
      {
1096
      throwUnexpectedEOFException();
1097
      }
1098
    else
1099
      {
1100
      throwUnexpectedNondigitCharExecption(c);
1101
      }
1102
    }
1103
1104
  int num = c - 48; // '0' == 48
1105
  while(isdigit(c = getc()))
1106
    {
1107
    num = 10 * num + c - 48;
1108
    }
1109
1110
  if(c == EOF)
1111
    {
1112
    throwUnexpectedEOFException();
1113
    }
1114
  putBack(c);
1115
1116
  return nonNegative ? num : -num;
1117
}
1118
1119
// extreamely simplified high-performing string to floating point
1120
// conversion code based on
1121
// ParaView3/VTK/Utilities/vtksqlite/vtk_sqlite3.c
1122
template<> float vtkOpenFOAMReader::vtkFoamFile::readValue()
1123
{
1124
  // skip prepending invalid chars
1125
  // expanded the outermost loop in nextTokenHead() for performance
1126
  int c;
1127
  while(isspace(c = getc())) // isspace() accepts -1 as EOF
1128
    {
1129
    if(c == '\n')
1130
      {
1131
      ++lineNumber_;
1132
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
1133
      wasNewline_ = true;
1134
#endif
1135
      }
1136
    }
1137
  if(c == 47) // '/' == 47
1138
    {
1139
    putBack(c);
1140
    c = nextTokenHead();
1141
    }
1142
1143
  // determine sign
1144
  int nonNegative = c - 45; // '-' == 45
1145
  if(nonNegative == 0 || c == 43) // '+' == 43
1146
    {
1147
    c = getc();
1148
    if(c == '\n')
1149
      {
1150
      ++lineNumber_;
1151
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
1152
      wasNewline_ = true;
1153
#endif
1154
      }
1155
    }
1156
1157
  if(!isdigit(c) && c != 46) // '.' == 46, isdigit() accepts EOF
1158
    {
1159
    throwUnexpectedNondigitCharExecption(c);
1160
    }
1161
1162
  // read integer part
1163
  double num = c - 48; // '0' == 48
1164
  while(isdigit(c = getc()))
1165
    {
1166
    num = num * 10.0 + (c - 48);
1167
    }
1168
1169
  // read decimal part
1170
  if(c == 46) // '.'
1171
    {
1172
    double divisor = 1.0;
1173
1174
    while(isdigit(c = getc()))
1175
      {
1176
      num = num * 10.0 + (c - 48);
1177
      divisor *= 10.0;
1178
      }
1179
    num /= divisor;
1180
    }
1181
1182
  // read exponent part
1183
  if(c == 69 || c == 101) // 'E' == 69, 'e' == 101
1184
    {
1185
    int esign = 1;
1186
    int eval = 0;
1187
    double scale = 1.0;
1188
1189
    c = getc();
1190
    if(c == 45) // '-'
1191
      {
1192
      esign = -1;
1193
      c = getc();
1194
      }
1195
    else if(c == 43) // '+'
1196
      {
1197
      c = getc();
1198
      }
1199
1200
    while(isdigit(c))
1201
      {
1202
      eval = eval * 10 + (c - 48);
1203
      c = getc();
1204
      }
1205
1206
    // fast exponent multiplication!
1207
    while(eval >= 64)
1208
      {
1209
      scale *= 1.0e+64;
1210
      eval -= 64;
1211
      }
1212
    while(eval >= 16)
1213
      {
1214
      scale *= 1.0e+16;
1215
      eval -= 16;
1216
      }
1217
    while(eval >= 4)
1218
      {
1219
      scale *= 1.0e+4;
1220
      eval -= 4;
1221
      }
1222
    while(eval >= 1)
1223
      {
1224
      scale *= 1.0e+1;
1225
      eval -= 1;
1226
      }
1227
1228
    if(esign < 0)
1229
      {
1230
      num /= scale;
1231
      }
1232
    else
1233
      {
1234
      num *= scale;
1235
      }
1236
    }
1237
1238
  if(c == EOF)
1239
    {
1240
    throwUnexpectedEOFException();
1241
    }
1242
  putBack(c);
1243
1244
  return static_cast<float>(nonNegative ? num : -num);
1245
}
1246
1247
// hacks to keep exception throwing code out-of-line to make
1248
// putBack() and readExpecting() inline expandable
1249
void vtkOpenFOAMReader::vtkFoamFile::throwUnexpectedEOFException()
1250
{ throw stackString() << "Unexpected EOF"; }
1251
1252
void vtkOpenFOAMReader::vtkFoamFile::throwUnexpectedNondigitCharExecption(
1253
  const int c)
1254
{
1255
  throw stackString() << "Expected a number, found a non-digit character "
1256
    << static_cast<char>(c);
1257
}
1258
1259
void vtkOpenFOAMReader::vtkFoamFile::throwUnexpectedTokenException(
1260
  const char expected, const int c)
1261
{
1262
  vtkFoamError sstr;
1263
  sstr << stackString() << "Expected punctuation token '" << expected
1264
    << "', found ";
1265
  if(c == EOF)
1266
    {
1267
    sstr << "EOF";
1268
    }
1269
  else
1270
    {
1271
    sstr << static_cast<char>(c);
1272
    }
1273
  throw sstr;
1274
}
1275
1276
void vtkOpenFOAMReader::vtkFoamFile::throwDuplicatedPutBackException()
1277
{ throw stackString() << "Attempted duplicated putBack()"; }
1278
1279
bool vtkOpenFOAMReader::vtkFoamFile::inflateNext(unsigned char *buf,
1280
  int requestSize)
1281
{
1282
  int size;
1283
  if(isCompressed_)
1284
    {
1285
    if(zStatus_ != Z_OK)
1286
      {
1287
      return false;
1288
      }
1289
    z_.next_out = buf;
1290
    z_.avail_out = requestSize;
1291
1292
    do
1293
      {
1294
      if(z_.avail_in == 0)
1295
        {
1296
        z_.next_in = inbuf_;
1297
        z_.avail_in = fread(inbuf_, 1, VTK_FOAMFILE_INBUFSIZE, file_);
1298
        if(ferror(file_))
1299
          {
1300
          throw stackString() << "Fread failed";
1301
          }
1302
        }
1303
      zStatus_ = inflate(&z_, Z_NO_FLUSH);
1304
      if(zStatus_ == Z_STREAM_END
1305
#if VTK_FOAMFILE_OMIT_CRCCHECK
1306
        // the dummy CRC function causes data error when finalizing
1307
        // so we have to proceed even when a data error is detected
1308
        || zStatus_ == Z_DATA_ERROR
1309
#endif
1310
        )
1311
        {
1312
        break;
1313
        }
1314
      if(zStatus_ != Z_OK)
1315
        {
1316
        throw stackString() << "Inflation failed: " << (z_.msg ? z_.msg : "");
1317
        }
1318
      }
1319
    while(z_.avail_out > 0);
1320
1321
    size = requestSize - z_.avail_out;
1322
    }
1323
  else
1324
    {
1325
    // not compressed
1326
    size = fread(buf, 1, requestSize, file_);
1327
    }
1328
1329
  if(size <= 0)
1330
    {
1331
    // retain the current location bufPtr_ to the end of the buffer so that
1332
    // getc() returns EOF again when called next time
1333
    return false;
1334
    }
1335
  // size > 0
1336
  bufPtr_ = outbuf_ + 1; // reserve the first byte for getback char
1337
  bufEndPtr_ = bufPtr_ + size;
1338
  return true;
1339
}
1340
1341
// get next semantically valid character
1342
int vtkOpenFOAMReader::vtkFoamFile::nextTokenHead()
1343
{
1344
  for(;;)
1345
    {
1346
    int c;
1347
    while(isspace(c = getc())) // isspace() accepts -1 as EOF
1348
      {
1349
      if(c == '\n')
1350
        {
1351
        ++lineNumber_;
1352
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
1353
        wasNewline_ = true;
1354
#endif
1355
        }
1356
      }
1357
    if(c == '/')
1358
      {
1359
      if((c = getc()) == '/')
1360
        {
1361
        while((c = getc()) != EOF && c != '\n');
1362
        if(c == EOF)
1363
          {
1364
          return c;
1365
          }
1366
        ++lineNumber_;
1367
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
1368
        wasNewline_ = true;
1369
#endif
1370
        }
1371
      else if(c == '*')
1372
        {
1373
        for(;;)
1374
          {
1375
          while((c = getc()) != EOF && c != '*')
1376
            {
1377
            if(c == '\n')
1378
              {
1379
              ++lineNumber_;
1380
              }
1381
            }
1382
          if(c == EOF)
1383
            {
1384
            return c;
1385
            }
1386
          else if((c = getc()) == '/')
1387
            {
1388
            break;
1389
            }
1390
          putBack(c);
1391
          }
1392
        }
1393
      else
1394
        {
1395
        putBack(c); // may be an EOF
1396
        return '/';
1397
        }
1398
      }
1399
    else // may be an EOF
1400
      {
1401
      return c;
1402
      }
1403
    }
1404
}
1405
1406
//-----------------------------------------------------------------------------
1407
// class vtkFoamIOobject
1408
// holds file handle, file format, name of the object the file holds and
1409
// type of the object.
1410
struct vtkOpenFOAMReader::vtkFoamIOobject: public vtkFoamFile
1411
{
1412
public:
1413
  enum fileFormat { UNDEFINED, ASCII, BINARY };
1414
1415
private:
1416
  fileFormat format_;
1417
  vtkStdString objectName_;
1418
  vtkStdString headerClassName_;
1419
  vtkFoamError e_;
1420
1421
  vtkFoamIOobject();
1422
  void readHeader(); // defined later
1423
public:
1424
  vtkFoamIOobject(const vtkStdString& casePath)
1425
    : vtkFoamFile(casePath), format_(UNDEFINED), e_() {}
1426
  ~vtkFoamIOobject() { close(); }
1427
1428
  bool open(const vtkStdString& file)
1429
  {
1430
    try
1431
      {
1432
      vtkFoamFile::open(file);
1433
      }
1434
    catch(vtkFoamError& e)
1435
      {
1436
      e_ = e;
1437
      return false;
1438
      }
1439
1440
    try
1441
      {
1442
      readHeader();
1443
      }
1444
    catch(vtkFoamError& e)
1445
      {
1446
      vtkFoamFile::close();
1447
      e_ = e;
1448
      return false;
1449
      }
1450
    return true;
1451
  }
1452
1453
  void close()
1454
  {
1455
    vtkFoamFile::close();
1456
    format_ = UNDEFINED;
1457
    objectName_.erase();
1458
    headerClassName_.erase();
1459
    e_.erase();
1460
  }
1461
  const fileFormat format() const { return format_; }
1462
  const vtkStdString& className() const { return headerClassName_; }
1463
  const vtkStdString& objectName() const { return objectName_; }
1464
  const vtkFoamError& error() const { return e_; }
1465
  void setError(const vtkFoamError& e) { e_ = e; }
1466
};
1467
1468
//-----------------------------------------------------------------------------
1469
// class vtkFoamEntryValue
1470
// a class that represents a value of a dictionary entry that corresponds to
1471
// its keyword. note that an entry can have more than one value.
1472
struct vtkOpenFOAMReader::vtkFoamEntryValue: public vtkFoamToken
1473
{
1474
private:
1475
  bool isUniform_;
1476
  bool managed_;
1477
  vtkFoamEntry *upperEntryPtr_;
1478
1479
  vtkFoamEntryValue();
1480
  vtkObjectBase *toVTKObject() { return vtkObjectPtr_; }
1481
  void clear();
1482
  void readList(vtkFoamIOobject& io);
1483
1484
protected:
1485
  // reads primitive int/float lists
1486
  template <typename listT, typename primitiveT> class listTraits
1487
  {
1488
    listT *ptr_;
1489
1490
  public:
1491
    listTraits(): ptr_(listT::New()) {}
1492
    listT *ptr() { return ptr_; }
1493
    void readUniformValues(vtkFoamIOobject& io, const int size)
1494
    {
1495
      primitiveT value = io.readValue<primitiveT>();
1496
      for(int i = 0; i < size; i++)
1497
	{
1498
	ptr_->SetValue(i, value);
1499
	}
1500
    }
1501
    void readAsciiList(vtkFoamIOobject& io, const int size)
1502
    {
1503
      for(int i = 0; i < size; i++)
1504
        {
1505
	ptr_->SetValue(i, io.readValue<primitiveT>());
1506
        }
1507
    }
1508
    void readBinaryList(vtkFoamIOobject& io, const int size)
1509
    {
1510
      io.read(reinterpret_cast<unsigned char *>(ptr_->GetPointer(0)),
1511
        size * sizeof(primitiveT));
1512
    }
1513
    void readValue(vtkFoamIOobject&, vtkFoamToken& currToken)
1514
    {
1515
      if(!currToken.is<primitiveT>())
1516
        {
1517
        throw vtkFoamError() << "Expected an integer or a (, found "
1518
          << currToken;
1519
        }
1520
      ptr_->InsertNextValue(currToken.to<primitiveT>());
1521
    }
1522
  };
1523
1524
  // reads rank 1 lists of types vector, sphericalTensor, symmTensor
1525
  // and tensor. if isPositions is true it reads Cloud type of data as
1526
  // particle positions. cf. (the positions format)
1527
  // src/lagrangian/basic/particle/particleIO.C
1528
  template <typename listT, typename primitiveT,
1529
    int nComponents, bool isPositions> class vectorListTraits
1530
  {
1531
    listT *ptr_;
1532
1533
  public:
1534
    vectorListTraits(): ptr_(listT::New())
1535
    { ptr_->SetNumberOfComponents(nComponents); }
1536
    listT *ptr() { return ptr_; }
1537
    void readUniformValues(vtkFoamIOobject& io, const int size)
1538
    {
1539
      io.readExpecting('(');
1540
      primitiveT vectorValue[nComponents];
1541
      for(int j = 0; j < nComponents; j++)
1542
        {
1543
	vectorValue[j] = io.readValue<primitiveT>();
1544
        }
1545
      for(int i = 0; i < size; i++)
1546
        {
1547
        ptr_->SetTuple(i, vectorValue);
1548
        }
1549
      io.readExpecting(')');
1550
      if(isPositions)
1551
        {
1552
        // skip label celli
1553
	io.readValue<int>();
1554
        }
1555
    }
1556
    void readAsciiList(vtkFoamIOobject& io, const int size)
1557
    {
1558
      for(int i = 0; i < size; i++)
1559
        {
1560
        io.readExpecting('(');
1561
        primitiveT *vectorTupleI = ptr_->GetPointer(nComponents * i);
1562
        for(int j = 0; j < nComponents; j++)
1563
          {
1564
          vectorTupleI[j] = io.readValue<primitiveT>();
1565
          }
1566
        io.readExpecting(')');
1567
        if(isPositions)
1568
          {
1569
          // skip label celli
1570
	  io.readValue<int>();
1571
          }
1572
        }
1573
    }
1574
    void readBinaryList(vtkFoamIOobject& io, const int size)
1575
    {
1576
      if(isPositions) // lagrangian/positions (class Cloud)
1577
        {
1578
        // allocate space along with the larger 1.4 format since the
1579
        // size must be determined at compile-time. we allocate on the
1580
        // stack to avoid leak when an exception is thrown.
1581
        unsigned char buffer[sizeof(double) * (nComponents + 1)
1582
	  + 2 * sizeof(int)];
1583
        const int nBytes = (io.getIs13Positions()
1584
        // skip label celli
1585
          ? sizeof(double) * nComponents + sizeof(int)
1586
        // skip label celli, label facei and scalar stepFraction
1587
          : sizeof(double) * (nComponents + 1) + 2 * sizeof(int));
1588
        for(int i = 0; i < size; i++)
1589
          {
1590
          io.readExpecting('(');
1591
          io.read(buffer, nBytes);
1592
          ptr_->SetTuple(i, reinterpret_cast<double *>(buffer));
1593
          io.readExpecting(')');
1594
          }
1595
	}
1596
      else
1597
	{
1598
        for(int i = 0; i < size; i++)
1599
          {
1600
          double buffer[nComponents];
1601
          io.read(reinterpret_cast<unsigned char *>(buffer),
1602
	    sizeof(double) * nComponents);
1603
          ptr_->SetTuple(i, buffer);
1604
          }
1605
	}
1606
    }
1607
    void readValue(vtkFoamIOobject& io, vtkFoamToken& currToken)
1608
    {
1609
      if(currToken != '(')
1610
        {
1611
        throw vtkFoamError() << "Expected '(', found " << currToken;
1612
        }
1613
      primitiveT v[nComponents];
1614
      for(int j = 0; j < nComponents; j++)
1615
        {
1616
	v[j] = io.readValue<primitiveT>();
1617
        }
1618
      ptr_->InsertNextTuple(v);
1619
      io.readExpecting(')');
1620
    }
1621
  };
1622
1623
public:
1624
  vtkFoamEntryValue(vtkFoamEntry *upperEntryPtr)
1625
    : vtkFoamToken(), isUniform_(false), managed_(true),
1626
      upperEntryPtr_(upperEntryPtr) {}
1627
  vtkFoamEntryValue(vtkFoamEntryValue&, vtkFoamEntry *);
1628
  ~vtkFoamEntryValue() { clear(); }
1629
1630
  void setEmptyList() { clear(); isUniform_ = false; type_ = EMPTYLIST; }
1631
  bool isUniform() const { return isUniform_; }
1632
  void read(vtkFoamIOobject& io);
1633
  void readDictionary(vtkFoamIOobject& io, const vtkFoamToken& firstKeyword);
1634
  vtkIntArray& labelList() const { return *labelListPtr_; }
1635
  const intVectorVector& labelListList() const { return *labelListListPtr_; }
1636
  vtkFloatArray& scalarList() { return *scalarListPtr_; }
1637
  vtkFloatArray& vectorList() { return *vectorListPtr_; }
1638
  vtkFoamDict& dictionary() { return *dictPtr_; }
1639
1640
  void *ptr()
1641
  {
1642
    managed_ = false; // the returned pointer will not be deleted by the d'tor
1643
    return (void *)labelListPtr_; // all list pointers are in a single union
1644
  }
1645
1646
  vtkStdString toString() const
1647
  { return type_ == STRING ? vtkFoamToken::toString() : vtkStdString(); }
1648
  float toFloat() const
1649
  {
1650
    return type_ == SCALAR || type_ == LABEL ? vtkFoamToken::to<float>() : 0.0F;
1651
  }
1652
  double toDouble() const
1653
  {
1654
    return type_ == SCALAR || type_ == LABEL ? vtkFoamToken::to<double>() : 0.0;
1655
  }
1656
  int toInt() const
1657
  { return type_ == LABEL ? vtkFoamToken::to<int>() : 0; }
1658
1659
  // the following two are for an exceptional expression of
1660
  // `LABEL{LABELorSCALAR}' without type prefix (e. g. `2{-0}' in
1661
  // mixedRhoE B.C. in rhopSonicFoam/shockTube)
1662
  void makeLabelList(const int labelValue, const int size)
1663
  {
1664
    labelListPtr_ = vtkIntArray::New();
1665
    type_ = LABELLIST;
1666
    vtkIntArray &ll = *labelListPtr_;
1667
    ll.SetNumberOfValues(size);
1668
    for(int i = 0; i < size; i++)
1669
      {
1670
      ll.SetValue(i, labelValue);
1671
      }
1672
  }
1673
  void makeScalarList(const float scalarValue, const int size)
1674
  {
1675
    scalarListPtr_ = vtkFloatArray::New();
1676
    type_ = SCALARLIST;
1677
    vtkFloatArray& sl = *scalarListPtr_;
1678
    sl.SetNumberOfValues(size);
1679
    for(int i = 0; i < size; i++)
1680
      {
1681
      sl.SetValue(i, scalarValue);
1682
      }
1683
  }
1684
1685
  // reads dimensionSet
1686
  void readDimensionSet(vtkFoamIOobject& io)
1687
  {
1688
    const int nDims = 7;
1689
    labelListPtr_ = vtkIntArray::New();
1690
    type_ = LABELLIST;
1691
    labelListPtr_->SetNumberOfValues(nDims);
1692
    for(int dimI = 0; dimI < nDims; dimI++)
1693
      {
1694
      labelListPtr_->SetValue(dimI, io.readValue<int>());
1695
      }
1696
    io.readExpecting(']');
1697
  }
1698
1699
  // generic reader for nonuniform lists. requires size prefix of the
1700
  // list to be present in the stream if the format is binary.
1701
  template <vtkFoamToken::tokenType listType, typename traitsT>
1702
  void readNonuniformList(vtkFoamIOobject& io)
1703
  {
1704
    vtkFoamToken currToken;
1705
    if(!io.read(currToken))
1706
      {
1707
      throw vtkFoamError() << "Unexpected EOF";
1708
      }
1709
    traitsT list;
1710
    type_ = listType;
1711
    vtkObjectPtr_ = list.ptr();
1712
    if(currToken.is<int>())
1713
      {
1714
      const int size = currToken.to<int>();
1715
      if(size < 0)
1716
        {
1717
        throw vtkFoamError() << "List size must not be negative: size = "
1718
          << size;
1719
        }
1720
      list.ptr()->SetNumberOfTuples(size);
1721
      if(!io.read(currToken))
1722
        {
1723
        throw vtkFoamError() << "Unexpected EOF";
1724
        }
1725
      // some objects have lists with only one element enclosed by {}
1726
      // e. g. simpleFoam/pitzDaily3Blocks/constant/polyMesh/faceZones
1727
      if(currToken == '{')
1728
        {
1729
	list.readUniformValues(io, size);
1730
        io.readExpecting('}');
1731
	return;
1732
        }
1733
      else if(currToken != '(')
1734
        {
1735
        throw vtkFoamError() << "Expected '(', found " << currToken;
1736
        }
1737
      else if(io.format() == vtkFoamIOobject::ASCII)
1738
        {
1739
	list.readAsciiList(io, size);
1740
        }
1741
      else
1742
        {
1743
        if(size > 0) // avoid invalid access to ll.at(0)
1744
          {
1745
	  list.readBinaryList(io, size);
1746
          }
1747
        }
1748
      io.readExpecting(')');
1749
      }
1750
    else if(currToken == '(')
1751
      {
1752
      while(io.read(currToken) && currToken != ')')
1753
        {
1754
	list.readValue(io, currToken);
1755
        }
1756
      list.ptr()->Squeeze();
1757
      }
1758
    else
1759
      {
1760
      throw vtkFoamError() << "Expected integer or '(', found " << currToken;
1761
      }
1762
  }
1763
1764
  // reads a list of labelLists. requires size prefix of the listList
1765
  // to be present. size of each sublist must also be present in the
1766
  // stream if the format is binary.
1767
  void readLabelListList(vtkFoamIOobject& io)
1768
  {
1769
    vtkFoamToken currToken;
1770
    if(!io.read(currToken))
1771
      {
1772
      throw vtkFoamError() << "Unexpected EOF";
1773
      }
1774
    if(currToken.type() == vtkFoamToken::LABEL)
1775
      {
1776
      const int sizeI = currToken.to<int>();
1777
      if(sizeI < 0)
1778
        {
1779
        throw vtkFoamError() << "List size must not be negative: size = "
1780
          << sizeI;
1781
        }
1782
      // gives initial guess for list size
1783
      labelListListPtr_ = new intVectorVector(sizeI, 4 * sizeI);
1784
      type_ = LABELLISTLIST;
1785
      io.readExpecting('(');
1786
      int bodyI = 0;
1787
      for(int i = 0; i < sizeI; i++)
1788
        {
1789
        if(!io.read(currToken))
1790
          {
1791
          throw vtkFoamError() << "Unexpected EOF";
1792
          }
1793
        if(currToken.type() == vtkFoamToken::LABEL)
1794
          {
1795
	  const int sizeJ = currToken.to<int>();
1796
          if(sizeJ < 0)
1797
            {
1798
            throw vtkFoamError() << "List size must not be negative: size = "
1799
              << sizeJ;
1800
            }
1801
          if(bodyI + sizeJ > labelListListPtr_->bodySize())
1802
            {
1803
            const int newSize = labelListListPtr_->bodySize() + sizeJ;
1804
            labelListListPtr_->resizeBody(newSize);
1805
            }
1806
          io.readExpecting('(');
1807
          int *listI = labelListListPtr_->setIndex(i, bodyI);
1808
          if(io.format() == vtkFoamIOobject::ASCII)
1809
            {
1810
            for(int j = 0; j < sizeJ; j++)
1811
              {
1812
	      listI[j] = io.readValue<int>();
1813
              }
1814
            }
1815
          else
1816
            {
1817
            if(sizeJ > 0) // avoid invalid reference to labelListI.at(0)
1818
              {
1819
              io.read(reinterpret_cast<unsigned char*>(listI),
1820
                sizeJ * sizeof(int));
1821
              }
1822
            }
1823
          bodyI += sizeJ;
1824
          io.readExpecting(')');
1825
          }
1826
        else if(currToken == '(')
1827
          {
1828
          labelListListPtr_->setIndex(i, bodyI);
1829
          while(io.read(currToken) && currToken != ')')
1830
            {
1831
            if(currToken.type() != vtkFoamToken::LABEL)
1832
              {
1833
              throw vtkFoamError() << "Expected an integer, found "
1834
                << currToken;
1835
              }
1836
            if(bodyI >= labelListListPtr_->bodySize())
1837
              {
1838
              const int newSize = labelListListPtr_->bodySize() + 1;
1839
              labelListListPtr_->resizeBody(newSize);
1840
              }
1841
            labelListListPtr_->setValue(bodyI++, currToken.to<int>());
1842
            }
1843
          }
1844
        else
1845
          {
1846
          throw vtkFoamError() << "Expected integer or '(', found "
1847
            << currToken;
1848
          }
1849
        }
1850
      // set the next index of the last element to calculate the last
1851
      // subarray size
1852
      labelListListPtr_->setIndex(sizeI, bodyI);
1853
      // shrink to the actually used size
1854
      labelListListPtr_->resizeBody(bodyI);
1855
      io.readExpecting(')');
1856
      }
1857
    else
1858
      {
1859
      throw vtkFoamError() << "Expected integer, found " << currToken;
1860
      }
1861
  }
1862
};
1863
1864
template<>
1865
void vtkOpenFOAMReader::vtkFoamEntryValue::listTraits<vtkFloatArray, float>
1866
::readBinaryList(vtkFoamIOobject& io, const int size)
1867
{
1868
  for(int i = 0; i < size; i++)
1869
    {
1870
    double buffer;
1871
    io.read(reinterpret_cast<unsigned char *>(&buffer), sizeof(double));
1872
    ptr_->SetValue(i, static_cast<float>(buffer));
1873
    }
1874
}
1875
1876
//-----------------------------------------------------------------------------
1877
// class vtkFoamEntry
1878
// a class that represents an entry of a dictionary. note that an
1879
// entry can have more than one value.
1880
struct vtkOpenFOAMReader::vtkFoamEntry
1881
{
1882
private:
1883
  vtkStdString keyword_;
1884
  vtkstd::vector<vtkFoamEntryValue*> valuePtrs_;
1885
  vtkFoamDict *upperDictPtr_;
1886
1887
  vtkFoamEntry();
1888
1889
public:
1890
  vtkFoamEntry(vtkFoamDict *upperDictPtr): upperDictPtr_(upperDictPtr) {}
1891
  vtkFoamEntry(const vtkFoamEntry& entry, vtkFoamDict *upperDictPtr)
1892
    : keyword_(entry.keyword()), valuePtrs_(entry.size()),
1893
      upperDictPtr_(upperDictPtr)
1894
  {
1895
    for(size_t valueI = 0; valueI < entry.size(); valueI++)
1896
      {
1897
      valuePtrs_[valueI] = new vtkFoamEntryValue(entry.value(valueI), this);
1898
      }
1899
  }
1900
1901
  ~vtkFoamEntry() { clear(); }
1902
1903
  void clear()
1904
  {
1905
    for(size_t i = 0; i < valuePtrs_.size(); i++)
1906
      {
1907
      delete valuePtrs_[i];
1908
      }
1909
    valuePtrs_.clear();
1910
  }
1911
  const vtkStdString& keyword() const { return keyword_; }
1912
  vtkStdString& keyword() { return keyword_; }
1913
  size_t size() const { return valuePtrs_.size(); }
1914
  // returns false if the number of the values is 0 to simplify things
1915
  bool found() const { return valuePtrs_.size() > 0; }
1916
  vtkFoamEntryValue& value(const int i) const { return *valuePtrs_[i]; }
1917
  vtkFoamEntryValue& firstValue() const { return *valuePtrs_[0]; }
1918
  vtkIntArray& labelList() const
1919
  { return firstValue().labelList(); }
1920
  const intVectorVector& labelListList() const
1921
  { return firstValue().labelListList(); }
1922
  vtkFloatArray& scalarList()
1923
  { return firstValue().scalarList(); }
1924
  vtkFloatArray& vectorList()
1925
  { return firstValue().vectorList(); }
1926
  vtkFoamDict& dictionary() // not using firstValue() for breaking constness
1927
  { return valuePtrs_[0]->dictionary(); }
1928
  void *ptr() { return firstValue().ptr(); }
1929
  vtkFoamDict *upperDictPtr() { return upperDictPtr_; }
1930
1931
  vtkStdString toString() const
1932
  { return found() ? firstValue().toString() : vtkStdString(); }
1933
  float toFloat() const
1934
  { return found() ? firstValue().toFloat() : 0.0F; }
1935
  double toDouble() const
1936
  { return found() ? firstValue().toDouble() : 0.0; }
1937
  int toInt() const
1938
  { return found() ? firstValue().toInt() : 0; }
1939
1940
  void readDictionary(vtkFoamIOobject& io)
1941
  {
1942
    valuePtrs_.push_back(new vtkFoamEntryValue(this));
1943
    valuePtrs_.back()->readDictionary(io, vtkFoamToken());
1944
  }
1945
1946
  // read values of an entry
1947
  void read(vtkFoamIOobject& io);
1948
};
1949
1950
//-----------------------------------------------------------------------------
1951
// class vtkFoamDict
1952
// a class that holds a FoamFile data structure
1953
struct vtkOpenFOAMReader::vtkFoamDict: public vtkFoamEntryValue
1954
{
1955
private:
1956
  vtkstd::vector<vtkFoamEntry*> entryPtrs_;
1957
  vtkFoamEntry *dummyEntryPtr_;
1958
  vtkFoamDict *upperDictPtr_;
1959
1960
  vtkFoamDict(const vtkFoamDict &);
1961
1962
public:
1963
  vtkFoamDict(vtkFoamDict *upperDictPtr = NULL)
1964
    : vtkFoamEntryValue(NULL), dummyEntryPtr_(NULL), upperDictPtr_(upperDictPtr)
1965
  { dictPtr_  = NULL; } // avoid destruction in vtkFoamEntryValue::clear()
1966
  vtkFoamDict(vtkFoamDict& dict, vtkFoamDict *upperDictPtr)
1967
    : vtkFoamEntryValue(dict, NULL), entryPtrs_(dict.size()),
1968
      dummyEntryPtr_(NULL), upperDictPtr_(upperDictPtr)
1969
  {
1970
    if(dict.type() == vtkFoamToken::DICTIONARY)
1971
      {
1972
      for(size_t entryI = 0; entryI < dict.size(); entryI++)
1973
        {
1974
        entryPtrs_[entryI] = new vtkFoamEntry(dict.entry(entryI), this);
1975
        }
1976
      }
1977
  }
1978
1979
  ~vtkFoamDict()
1980
  {
1981
    if(type_ == DICTIONARY)
1982
      {
1983
      for(size_t i = 0; i < entryPtrs_.size(); i++)
1984
        {
1985
        delete entryPtrs_[i];
1986
        }
1987
      }
1988
    delete dummyEntryPtr_;
1989
  }
1990
1991
  size_t size() const { return entryPtrs_.size(); }
1992
  vtkFoamDict *upperDictPtr() { return upperDictPtr_; }
1993
  const vtkFoamEntry& entry(const int i) const { return *entryPtrs_[i]; }
1994
  vtkFoamEntry& entry(const int i) { return *entryPtrs_[i]; }
1995
  vtkFoamEntry& lookup(const vtkStdString& keyword)
1996
  {
1997
    if(type_ == DICTIONARY)
1998
      {
1999
      for(size_t i = 0; i < entryPtrs_.size(); i++)
2000
        {
2001
        if(entryPtrs_[i]->keyword() == keyword) // found
2002
          {
2003
          return *entryPtrs_[i];
2004
          }
2005
        }
2006
      }
2007
2008
    // not found
2009
    if(dummyEntryPtr_ == NULL)
2010
      {
2011
      dummyEntryPtr_ = new vtkFoamEntry(NULL);
2012
      }
2013
    return *dummyEntryPtr_;
2014
  }
2015
2016
  // reads a FoamFile or a subdictionary. if the stream to be read is
2017
  // a subdictionary the preceding '{' is assumed to have already been
2018
  // thrown away.
2019
  bool read(vtkFoamIOobject& io, const bool isSubDictionary = false,
2020
    const vtkFoamToken& firstToken = vtkFoamToken())
2021
  {
2022
    try
2023
      {
2024
      vtkFoamToken currToken;
2025
      if(firstToken.type() == vtkFoamToken::UNDEFINED)
2026
        {
2027
        if(!isSubDictionary)
2028
          {
2029
          if(io.className() == "scalarField") // lagrangian scalars
2030
            {
2031
            readNonuniformList<SCALARLIST, listTraits<vtkFloatArray, float> >(
2032
	      io);
2033
            return true;
2034
            }
2035
          // polyMesh/points, lagrangian vectors
2036
          else if(io.className() == "sphericalTensorField")
2037
            {
2038
	    readNonuniformList<VECTORLIST,
2039
	      vectorListTraits<vtkFloatArray, float, 1, false> >(io);
2040
            return true;
2041
            }
2042
          else if(io.className() == "vectorField")
2043
            {
2044
	    readNonuniformList<VECTORLIST,
2045
	      vectorListTraits<vtkFloatArray, float, 3, false> >(io);
2046
            return true;
2047
            }
2048
          else if(io.className() == "symmTensorField")
2049
            {
2050
	    readNonuniformList<VECTORLIST,
2051
	      vectorListTraits<vtkFloatArray, float, 6, false> >(io);
2052
            return true;
2053
            }
2054
          else if(io.className() == "tensorField")
2055
            {
2056
	    readNonuniformList<VECTORLIST,
2057
	      vectorListTraits<vtkFloatArray, float, 9, false> >(io);
2058
            return true;
2059
            }
2060
          // lagrangian positions. there are many concrete class names
2061
          // e. g. Cloud<parcel>, basicKinematicCloud etc.
2062
          else if(io.className().find("Cloud") != vtkStdString::npos
2063
            && io.objectName() == "positions")
2064
            {
2065
	    readNonuniformList<VECTORLIST,
2066
              vectorListTraits<vtkFloatArray, float, 3, true> >(io);
2067
            return true;
2068
            }
2069
          else if(io.className() == "faceList") // polyMesh/faces
2070
            {
2071
            readLabelListList(io);
2072
            return true;
2073
            }
2074
          else if(io.className() == "labelList") // polyMesh/{owner|neighbour}
2075
            {
2076
	    readNonuniformList<LABELLIST, listTraits<vtkIntArray, int> >(io);
2077
            return true;
2078
            }
2079
          }
2080
2081
        // read the first token
2082
        if(!io.read(currToken))
2083
          {
2084
          throw vtkFoamError() << "Unexpected EOF";
2085
          }
2086
2087
        // list of dictionaries is read as a usual dictionary
2088
        // polyMesh/boundary, point/face/cell-Zones
2089
        if(!isSubDictionary && currToken.type() == vtkFoamToken::LABEL)
2090
          {
2091
          io.readExpecting('(');
2092
          if(currToken.to<int>() > 0)
2093
            {
2094
            if(!io.read(currToken))
2095
              {
2096
              throw vtkFoamError() << "Unexpected EOF";
2097
              }
2098
            // continue to read as a usual dictionary
2099
            }
2100
          else // return as empty dictionary
2101
            {
2102
            io.readExpecting(')');
2103
            type_ = DICTIONARY;
2104
            return true;
2105
            }
2106
          }
2107
        // some boundary files does not have the number of boundary
2108
        // patches (e.g. settlingFoam/tank3D). in this case we need to
2109
        // explicitly read the file as a dictionary.
2110
        else if(!isSubDictionary && currToken == '('
2111
          && io.className() == "polyBoundaryMesh") // polyMesh/boundary
2112
          {
2113
	    if(!io.read(currToken)) // read the first keyword
2114
            {
2115
            throw vtkFoamError() << "Unexpected EOF";
2116
            }
2117
          if(currToken == ')') // return as empty dictionary
2118
            {
2119
            type_ = DICTIONARY;
2120
            return true;
2121
            }
2122
          }
2123
	// the following two else-if clauses are for an exceptional
2124
	// expression of `LABEL{LABELorSCALAR}' without type prefix
2125
	// (e. g. `2{-0}' in mixedRhoE B.C. in
2126
	// rhopSonicFoam/shockTube)
2127
	else if(isSubDictionary && currToken.type() == vtkFoamToken::LABEL)
2128
	  {
2129
	  vtkFoamToken::operator=(currToken.to<int>());
2130
          type_ = UNIFORMLABELLIST;
2131
          io.readExpecting('}');
2132
          return true;
2133
          }
2134
	else if(isSubDictionary && currToken.type() == vtkFoamToken::SCALAR)
2135
	  {
2136
	  vtkFoamToken::operator=(currToken.to<float>());
2137
          type_ = UNIFORMSCALARLIST;
2138
          io.readExpecting('}');
2139
          return true;
2140
          }
2141
        // return as empty dictionary
2142
        else if(isSubDictionary && currToken == '}')
2143
          {
2144
          type_ = DICTIONARY;
2145
          return true;
2146
          }
2147
        }
2148
      // if firstToken is given as string set read the following stream
2149
      // as subdictionary
2150
      else if(firstToken.type() == vtkFoamToken::STRING)
2151
        {
2152
        type_ = DICTIONARY;
2153
        entryPtrs_.push_back(new vtkFoamEntry(this));
2154
        entryPtrs_.back()->keyword() = firstToken.toString();
2155
        entryPtrs_.back()->readDictionary(io);
2156
        if(!io.read(currToken) || currToken == '}' || currToken == ')')
2157
          {
2158
          return true;
2159
          }
2160
        }
2161
      else // quite likely an identifier
2162
        {
2163
        currToken = firstToken;
2164
        }
2165
2166
      if(currToken == ';' || currToken.type() == vtkFoamToken::STRING
2167
        || currToken.type() == vtkFoamToken::IDENTIFIER) // general dictionary
2168
        {
2169
        // type must be set first so that lookup() works
2170
        type_ = DICTIONARY;
2171
        do
2172
          {
2173
          if(currToken.type() == vtkFoamToken::STRING)
2174
            {
2175
            vtkFoamEntry& previousEntry = lookup(currToken.toString());
2176
            if(previousEntry.found())
2177
              {
2178
              if(io.getInputMode() == vtkFoamFile::INPUT_MODE_MERGE)
2179
                {
2180
                if(previousEntry.firstValue().type()
2181
                  == vtkFoamToken::DICTIONARY)
2182
                  {
2183
                  io.readExpecting('{');
2184
                  previousEntry.firstValue().dictionary().read(io, true);
2185
                  }
2186
                else
2187
                  {
2188
                  previousEntry.clear();
2189
                  previousEntry.read(io);
2190
                  }
2191
                }
2192
              else if(io.getInputMode() == vtkFoamFile::INPUT_MODE_OVERWRITE)
2193
                {
2194
                previousEntry.clear();
2195
                previousEntry.read(io);
2196
                }
2197
              else // INPUT_MODE_ERROR
2198
                {
2199
                throw vtkFoamError() << "Found duplicated entries with keyword "
2200
                  << currToken.toString();
2201
                }
2202
              }
2203
            else
2204
              {
2205
              entryPtrs_.push_back(new vtkFoamEntry(this));
2206
              entryPtrs_.back()->keyword() = currToken.toString();
2207
              entryPtrs_.back()->read(io);
2208
              }
2209
2210
            if(currToken == "FoamFile")
2211
              {
2212
              // delete the FoamFile header subdictionary entry
2213
              delete entryPtrs_.back();
2214
              entryPtrs_.pop_back();
2215
              }
2216
	    else if(currToken == "include")
2217
              {
2218
              // include the named file. Exiting the included file at
2219
              // EOF will be handled automatically by
2220
              // vtkFoamFile::closeIncludedFile()
2221
              if(entryPtrs_.back()->firstValue().type() != vtkFoamToken::STRING)
2222
                {
2223
                throw vtkFoamError()
2224
                  << "Expected string as the file name to be included, found "
2225
                  << entryPtrs_.back()->firstValue();
2226
                }
2227
              vtkStdString includeFileName(entryPtrs_.back()->toString());
2228
              delete entryPtrs_.back();
2229
              entryPtrs_.pop_back();
2230
              io.includeFile(includeFileName, io.filePath());
2231
              }
2232
            }
2233
          else if(currToken.type() == vtkFoamToken::IDENTIFIER)
2234
            {
2235
	    // substitute identifier
2236
	    const vtkStdString identifier(currToken.toIdentifier());
2237
2238
	    for(vtkFoamDict *uDictPtr = this;;)
2239
	      {
2240
	      const vtkFoamEntry&
2241
		identifiedEntry = uDictPtr->lookup(identifier);
2242
2243
	      if(identifiedEntry.found())
2244
		{
2245
		if(identifiedEntry.firstValue().type()
2246
                  != vtkFoamToken::DICTIONARY)
2247
		  {
2248
		  throw vtkFoamError()
2249
		    << "Expected dictionary for substituting entry "
2250
		    << identifier;
2251
		  }
2252
		vtkFoamDict& identifiedDict
2253
		  = identifiedEntry.firstValue().dictionary();
2254
		for(size_t entryI = 0; entryI < identifiedDict.size(); entryI++)
2255
		  {
2256
                  // I think #inputMode handling should be done here
2257
                  // as well, but the genuine FoamFile parser for OF
2258
                  // 1.5 does not seem to be doing it.
2259
		  entryPtrs_.push_back(
2260
                    new vtkFoamEntry(identifiedDict.entry(entryI), this));
2261
		  }
2262
                break;
2263
                }
2264
              else
2265
                {
2266
                uDictPtr = uDictPtr->upperDictPtr();
2267
                if(uDictPtr == NULL)
2268
                  {
2269
                  throw vtkFoamError() << "Substituting entry " << identifier
2270
                    << " not found";
2271
                  }
2272
                }
2273
              }
2274
            }
2275
          // skip empty entry only with ';'
2276
          } while(io.read(currToken)
2277
          && (currToken.type() == vtkFoamToken::STRING
2278
          || currToken.type() == vtkFoamToken::IDENTIFIER || currToken == ';'));
2279
2280
        if(currToken.type() == vtkFoamToken::ERROR || currToken == '}'
2281
          || currToken == ')')
2282
          {
2283
          return true;
2284
          }
2285
	type_ = UNDEFINED;
2286
        throw vtkFoamError()
2287
          << "Expected keyword, closing brace, ';' or EOF, found " << currToken;
2288
        }
2289
      throw vtkFoamError() << "Expected keyword or identifier, found "
2290
        << currToken;
2291
      }
2292
    catch(vtkFoamError& e)
2293
      {
2294
      if(isSubDictionary)
2295
        {
2296
        throw;
2297
        }
2298
      else
2299
        {
2300
        io.setError(e);
2301
        return false;
2302
        }
2303
      }
2304
  }
2305
};
2306
2307
void vtkOpenFOAMReader::vtkFoamIOobject::readHeader()
2308
{
2309
  vtkFoamToken firstToken;
2310
2311
  readExpecting("FoamFile");
2312
  readExpecting('{');
2313
2314
  vtkFoamDict headerDict;
2315
  // throw exception in case of error
2316
  headerDict.read(*this, true, vtkFoamToken());
2317
2318
  const vtkFoamEntry& formatEntry = headerDict.lookup("format");
2319
  if(!formatEntry.found())
2320
    {
2321
    throw vtkFoamError()
2322
      << "format entry (binary/ascii) not found in FoamFile header";
2323
    }
2324
  // case does matter (e. g. "BINARY" is treated as ascii)
2325
  // cf. src/OpenFOAM/db/IOstreams/IOstreams/IOstream.C
2326
  format_ = (formatEntry.toString() == "binary" ? BINARY : ASCII);
2327
2328
  const vtkFoamEntry& classEntry = headerDict.lookup("class");
2329
  if(!classEntry.found())
2330
    {
2331
    throw vtkFoamError() << "class name not found in FoamFile header";
2332
    }
2333
  headerClassName_ = classEntry.toString();
2334
2335
  const vtkFoamEntry& objectEntry = headerDict.lookup("object");
2336
  if(!objectEntry.found())
2337
    {
2338
    throw vtkFoamError() << "object name not found in FoamFile header";
2339
    }
2340
  objectName_ = objectEntry.toString();
2341
}
2342
2343
vtkOpenFOAMReader::vtkFoamEntryValue::vtkFoamEntryValue(
2344
  vtkFoamEntryValue& value, vtkFoamEntry *upperEntryPtr)
2345
  : vtkFoamToken(value), isUniform_(value.isUniform()), managed_(true),
2346
    upperEntryPtr_(upperEntryPtr)
2347
{
2348
  switch(type_)
2349
    {
2350
    case LABELLIST: case SCALARLIST: case VECTORLIST: case STRINGLIST:
2351
      vtkObjectPtr_ = value.toVTKObject();
2352
      vtkObjectPtr_->Register(0); // increase reference count +1
2353
      break;
2354
    case LABELLISTLIST:
2355
      labelListListPtr_ = new intVectorVector(*value.labelListListPtr_);
2356
      break;
2357
    case ENTRYVALUELIST:
2358
      {
2359
      const int nValues = value.entryValuePtrs_->size();
2360
      entryValuePtrs_ = new vtkstd::vector<vtkFoamEntryValue*>(nValues);
2361
      for(int valueI = 0; valueI < nValues; valueI++)
2362
	{
2363
        entryValuePtrs_->operator[](valueI) = new vtkFoamEntryValue(
2364
          *value.entryValuePtrs_->operator[](valueI), upperEntryPtr_);
2365
	}
2366
      }
2367
      break;
2368
    case DICTIONARY:
2369
      // upperEntryPtr_ is null when called from vtkFoamDict constructor
2370
      if(upperEntryPtr_ != NULL)
2371
        {
2372
        dictPtr_
2373
          = new vtkFoamDict(*value.dictPtr_, upperEntryPtr_->upperDictPtr());
2374
        }
2375
      else
2376
        {
2377
        dictPtr_ = NULL;
2378
        }
2379
      break;
2380
    case EMPTYLIST:
2381
      break;
2382
    }
2383
}
2384
2385
void vtkOpenFOAMReader::vtkFoamEntryValue::clear()
2386
{
2387
  if(managed_)
2388
    {
2389
    switch(type_)
2390
      {
2391
      case LABELLIST: case SCALARLIST: case VECTORLIST: case STRINGLIST:
2392
        vtkObjectPtr_->Delete();
2393
        break;
2394
      case LABELLISTLIST:
2395
        delete labelListListPtr_;
2396
        break;
2397
      case ENTRYVALUELIST:
2398
        for(size_t valueI = 0; valueI < entryValuePtrs_->size() ; valueI++)
2399
          {
2400
          delete entryValuePtrs_->operator[](valueI);
2401
          }
2402
        delete entryValuePtrs_;
2403
        break;
2404
      case DICTIONARY:
2405
        delete dictPtr_;
2406
        break;
2407
      }
2408
    }
2409
}
2410
2411
// general-purpose list reader - guess the type of the list and read
2412
// it. only supports ascii format and assumes the preceding '(' has
2413
// already been thrown away.  the reader supports nested list with
2414
// variable lengths (e. g. `((token token) (token token token)).'
2415
// also supports compound of tokens and lists (e. g. `((token token)
2416
// token)') only if a list comes as the first value.
2417
void vtkOpenFOAMReader::vtkFoamEntryValue::readList(vtkFoamIOobject& io)
2418
{
2419
  vtkFoamToken currToken;
2420
  io.read(currToken);
2421
2422
  // initial guess of the list type
2423
  if(currToken.type() == vtkFoamToken::LABEL)
2424
    {
2425
    // if the first token is of type LABEL it might be either an element of
2426
    // a labelList or the size of a sublist so proceed to the next token
2427
    vtkFoamToken nextToken;
2428
    if(!io.read(nextToken))
2429
      {
2430
      throw vtkFoamError() << "Unexpected EOF";
2431
      }
2432
    if(nextToken.type() == vtkFoamToken::LABEL)
2433
      {
2434
      labelListPtr_ = vtkIntArray::New();
2435
      labelListPtr_->InsertNextValue(currToken.to<int>());
2436
      labelListPtr_->InsertNextValue(nextToken.to<int>());
2437
      type_ = LABELLIST;
2438
      }
2439
    else if(nextToken.type() == vtkFoamToken::SCALAR)
2440
      {
2441
      scalarListPtr_ = vtkFloatArray::New();
2442
      scalarListPtr_->InsertNextValue(currToken.to<float>());
2443
      scalarListPtr_->InsertNextValue(nextToken.to<float>());
2444
      type_ = SCALARLIST;
2445
      }
2446
    else if(nextToken == '(') // list of list: read recursively
2447
      {
2448
      entryValuePtrs_ = new vtkstd::vector<vtkFoamEntryValue*>;
2449
      entryValuePtrs_->push_back(new vtkFoamEntryValue(upperEntryPtr_));
2450
      entryValuePtrs_->back()->readList(io);
2451
      type_ = ENTRYVALUELIST;
2452
      }
2453
    else if(nextToken == ')') // list with only one label element
2454
      {
2455
      labelListPtr_ = vtkIntArray::New();
2456
      labelListPtr_->SetNumberOfValues(1);
2457
      labelListPtr_->SetValue(0, currToken.to<int>());
2458
      type_ = LABELLIST;
2459
      return;
2460
      }
2461
    else
2462
      {
2463
      throw vtkFoamError() << "Expected number, '(' or ')', found "
2464
        << nextToken;
2465
      }
2466
    }
2467
  else if(currToken.type() == vtkFoamToken::SCALAR)
2468
    {
2469
    scalarListPtr_ = vtkFloatArray::New();
2470
    scalarListPtr_->InsertNextValue(currToken.to<float>());
2471
    type_ = SCALARLIST;
2472
    }
2473
  // if the first word is a string we have to read another token to determine
2474
  // if the first word is a keyword for the following dictionary
2475
  else if(currToken.type() == vtkFoamToken::STRING)
2476
    {
2477
    vtkFoamToken nextToken;
2478
    if(!io.read(nextToken))
2479
      {
2480
      throw vtkFoamError() << "Unexpected EOF";
2481
      }
2482
    if(nextToken.type() == vtkFoamToken::STRING) // list of strings
2483
      {
2484
      stringListPtr_ = vtkStringArray::New();
2485
      stringListPtr_->InsertNextValue(currToken.toString());
2486
      stringListPtr_->InsertNextValue(nextToken.toString());
2487
      type_ = STRINGLIST;
2488
      }
2489
    // dictionary with the already read stringToken as the first keyword
2490
    else if(nextToken == '{')
2491
      {
2492
      if(currToken.toString() == "")
2493
        {
2494
        throw "Empty string is invalid as a keyword for dictionary entry";
2495
        }
2496
      readDictionary(io, currToken);
2497
      // the dictionary read as list has the entry terminator ';' so
2498
      // we have to skip it
2499
      return;
2500
      }
2501
    else if(nextToken == ')') // list with only one string element
2502
      {
2503
      stringListPtr_ = vtkStringArray::New();
2504
      stringListPtr_->SetNumberOfValues(1);
2505
      stringListPtr_->SetValue(0, currToken.toString());
2506
      type_ = STRINGLIST;
2507
      return;
2508
      }
2509
    else
2510
      {
2511
      throw vtkFoamError() << "Expected string, '{' or ')', found "
2512
        << nextToken;
2513
      }
2514
    }
2515
  else if(currToken == '(') // list of lists: read recursively
2516
    {
2517
    entryValuePtrs_ = new vtkstd::vector<vtkFoamEntryValue*>;
2518
    entryValuePtrs_->push_back(new vtkFoamEntryValue(upperEntryPtr_));
2519
    entryValuePtrs_->back()->readList(io);
2520
    // read all the following values as arbitrary entryValues
2521
    // the alphaContactAngle b.c. in multiphaseInterFoam/damBreak4phase
2522
    // reaquires this treatment (reading by readList() is not enough)
2523
    do
2524
      {
2525
      entryValuePtrs_->push_back(new vtkFoamEntryValue(upperEntryPtr_));
2526
      entryValuePtrs_->back()->read(io);
2527
      }
2528
    while(*entryValuePtrs_->back() != ')' && *entryValuePtrs_->back() != '}'
2529
      && *entryValuePtrs_->back() != ';');
2530
2531
    if(*entryValuePtrs_->back() != ')')
2532
      {
2533
      throw vtkFoamError() << "Expected ')' before "
2534
        << *entryValuePtrs_->back();
2535
      }
2536
2537
    // delete ')'
2538
    delete entryValuePtrs_->back();
2539
    entryValuePtrs_->pop_back();
2540
    type_ = ENTRYVALUELIST;
2541
    return;
2542
    }
2543
  else if(currToken == ')') // empty list
2544
    {
2545
    type_ = EMPTYLIST;
2546
    return;
2547
    }
2548
  // FIXME: may (or may not) need identifier handling
2549
2550
  while(io.read(currToken) && currToken != ')')
2551
    {
2552
    if(type_ == LABELLIST)
2553
      {
2554
      if(currToken.type() == vtkFoamToken::SCALAR) // switch to scalarList
2555
        {
2556
        // labelListPtr_ and scalarListPtr_ are packed into a single union so
2557
        // we need a temprary pointer
2558
        vtkFloatArray* slPtr = vtkFloatArray::New();
2559
        const int size = labelListPtr_->GetNumberOfTuples();
2560
        slPtr->SetNumberOfValues(size + 1);
2561
        for(int i = 0; i < size; i++)
2562
          {
2563
          slPtr->SetValue(i, static_cast<float>(labelListPtr_->GetValue(i)));
2564
          }
2565
        labelListPtr_->Delete();
2566
        slPtr->SetValue(size, currToken.to<float>());
2567
        scalarListPtr_ = slPtr; // copy after labelListPtr_ is deleted
2568
        type_ = SCALARLIST;
2569
        }
2570
      else if(currToken.type() == vtkFoamToken::LABEL)
2571
        {
2572
	labelListPtr_->InsertNextValue(currToken.to<int>());
2573
        }
2574
      else
2575
        {
2576
        throw vtkFoamError() << "Expected a number, found " << currToken;
2577
        }
2578
      }
2579
    else if(type_ == SCALARLIST)
2580
      {
2581
      if(currToken.is<float>())
2582
        {
2583
	scalarListPtr_->InsertNextValue(currToken.to<float>());
2584
        }
2585
      else
2586
        {
2587
        throw vtkFoamError() << "Expected a number, found " << currToken;
2588
        }
2589
      }
2590
    else if(type_ == STRINGLIST)
2591
      {
2592
      if(currToken.type() == vtkFoamToken::STRING)
2593
        {
2594
        stringListPtr_->InsertNextValue(currToken.toString());
2595
        }
2596
      else
2597
        {
2598
        throw vtkFoamError() << "Expected a string, found " << currToken;
2599
        }
2600
      }
2601
    else if(type_ == ENTRYVALUELIST)
2602
      {
2603
      if(currToken.type() == vtkFoamToken::LABEL)
2604
        {
2605
        // skip the number of elements to make things simple
2606
        if(!io.read(currToken))
2607
          {
2608
          throw vtkFoamError() << "Unexpected EOF";
2609
          }
2610
        }
2611
      if(currToken != '(')
2612
        {
2613
        throw vtkFoamError() << "Expected '(', found " << currToken;
2614
        }
2615
      entryValuePtrs_->push_back(new vtkFoamEntryValue(upperEntryPtr_));
2616
      entryValuePtrs_->back()->readList(io);
2617
      }
2618
    else
2619
      {
2620
      throw vtkFoamError() << "Unexpected token " << currToken;
2621
      }
2622
    }
2623
2624
  if(type_ == LABELLIST)
2625
    {
2626
    labelListPtr_->Squeeze();
2627
    }
2628
  else if(type_ == SCALARLIST)
2629
    {
2630
    scalarListPtr_->Squeeze();
2631
    }
2632
  else if(type_ == STRINGLIST)
2633
    {
2634
    stringListPtr_->Squeeze();
2635
    }
2636
}
2637
2638
// a list of dictionaries is actually read as a dictionary
2639
void vtkOpenFOAMReader::vtkFoamEntryValue::readDictionary(vtkFoamIOobject& io,
2640
  const vtkFoamToken& firstKeyword)
2641
{
2642
  dictPtr_ = new vtkFoamDict(upperEntryPtr_->upperDictPtr());
2643
  type_ = DICTIONARY;
2644
  dictPtr_->read(io, true, firstKeyword);
2645
}
2646
2647
// guess the type of the given entry value and read it
2648
void vtkOpenFOAMReader::vtkFoamEntryValue::read(vtkFoamIOobject& io)
2649
{
2650
  vtkFoamToken currToken;
2651
  if(!io.read(currToken))
2652
    {
2653
    throw vtkFoamError() << "Unexpected EOF";
2654
    }
2655
2656
  if(currToken == '{')
2657
    {
2658
    readDictionary(io, vtkFoamToken());
2659
    return;
2660
    }
2661
  // for reading sublist from vtkFoamEntryValue::readList() or there
2662
  // are cases where lists without the (non)uniform keyword appear
2663
  // (e. g. coodles/pitsDaily/0/U, uniformFixedValue b.c.)
2664
  else if(currToken == '(')
2665
    {
2666
    readList(io);
2667
    return;
2668
    }
2669
  else if(currToken == '[')
2670
    {
2671
    readDimensionSet(io);
2672
    return;
2673
    }
2674
  else if(currToken == "uniform")
2675
    {
2676
    if(!io.read(currToken))
2677
      {
2678
      throw vtkFoamError()
2679
        << "Expected a uniform value or a list, found unexpected EOF";
2680
      }
2681
    if(currToken == '(')
2682
      {
2683
      readList(io);
2684
      }
2685
    else if(currToken.type() == vtkFoamToken::LABEL
2686
      || currToken.type() == vtkFoamToken::SCALAR
2687
      || currToken.type() == vtkFoamToken::STRING)
2688
      {
2689
      vtkFoamToken::operator=(currToken);
2690
      }
2691
    else // unexpected punctuation token
2692
      {
2693
      throw vtkFoamError() << "Expected number, string or (, found "
2694
        << currToken;
2695
      }
2696
    isUniform_ = true;
2697
    }
2698
  else if(currToken == "nonuniform")
2699
    {
2700
    if(!io.read(currToken))
2701
      {
2702
      throw vtkFoamError() << "Expected list type specifier, found EOF";
2703
      }
2704
    isUniform_ = false;
2705
    if(currToken == "List<scalar>")
2706
      {
2707
      readNonuniformList<SCALARLIST, listTraits<vtkFloatArray, float> >(io);
2708
      }
2709
    else if(currToken == "List<sphericalTensor>")
2710
      {
2711
      readNonuniformList<VECTORLIST,
2712
        vectorListTraits<vtkFloatArray, float, 1, false> >(io);
2713
      }
2714
    else if(currToken == "List<vector>")
2715
      {
2716
      readNonuniformList<VECTORLIST,
2717
        vectorListTraits<vtkFloatArray, float, 3, false> >(io);
2718
      }
2719
    else if(currToken == "List<symmTensor>")
2720
      {
2721
      readNonuniformList<VECTORLIST,
2722
        vectorListTraits<vtkFloatArray, float, 6, false> >(io);
2723
      }
2724
    else if(currToken == "List<tensor>")
2725
      {
2726
      readNonuniformList<VECTORLIST,
2727
	vectorListTraits<vtkFloatArray, float, 9, false> >(io);
2728
      }
2729
    // List<bool> is read as List<label>
2730
    else if(currToken =="List<label>" || currToken == "List<bool>")
2731
      {
2732
      readNonuniformList<LABELLIST, listTraits<vtkIntArray, int> >(io);
2733
      }
2734
    // an empty list doesn't have a list type specifier
2735
    else if(currToken.type() == vtkFoamToken::LABEL
2736
      && currToken.to<int>() == 0)
2737
      {
2738
      type_ = EMPTYLIST;
2739
      io.readExpecting('(');
2740
      io.readExpecting(')');
2741
      }
2742
    else
2743
      {
2744
      throw vtkFoamError() << "Unsupported nonuniform list type " << currToken;
2745
      }
2746
    }
2747
  // zones have list without a uniform/nonuniform keyword
2748
  // List<bool> is read as List<label>
2749
  // (e. g. flipMap entry in faceZones)
2750
  else if(currToken == "List<label>" || currToken == "List<bool>")
2751
    {
2752
    isUniform_ = false;
2753
    readNonuniformList<LABELLIST, listTraits<vtkIntArray, int> >(io);
2754
    }
2755
  else if(currToken.type() == vtkFoamToken::PUNCTUATION
2756
    || currToken.type() == vtkFoamToken::LABEL
2757
    || currToken.type() == vtkFoamToken::SCALAR
2758
    || currToken.type() == vtkFoamToken::STRING
2759
    || currToken.type() == vtkFoamToken::IDENTIFIER)
2760
    {
2761
    vtkFoamToken::operator=(currToken);
2762
    }
2763
}
2764
2765
// read values of an entry
2766
void vtkOpenFOAMReader::vtkFoamEntry::read(vtkFoamIOobject& io)
2767
{
2768
  for(;;)
2769
    {
2770
    valuePtrs_.push_back(new vtkFoamEntryValue(this));
2771
    valuePtrs_.back()->read(io);
2772
2773
    if(valuePtrs_.size() >= 2)
2774
      {
2775
      vtkFoamEntryValue& secondLastValue
2776
        = *valuePtrs_[valuePtrs_.size() - 2];
2777
      if(secondLastValue.type() == vtkFoamToken::LABEL)
2778
        {
2779
        vtkFoamEntryValue& lastValue = *valuePtrs_.back();
2780
2781
        // a zero-sized nonuniform list without prefixing "nonuniform"
2782
        // keyword nor list type specifier (i. e. `0()';
2783
        // e. g. simpleEngine/0/polyMesh/pointZones) requires special
2784
        // care (one with nonuniform prefix is treated within
2785
        // vtkFoamEntryValue::read()). still this causes errornous
2786
        // behavior for `0 nonuniform 0()' but this should be extremely
2787
        // rare
2788
        if(lastValue.type() == vtkFoamToken::EMPTYLIST
2789
          && secondLastValue == 0)
2790
          {
2791
          delete valuePtrs_.back();
2792
          valuePtrs_.pop_back(); // delete the last value
2793
          valuePtrs_.back()->setEmptyList(); // mark new last value as empty
2794
          }
2795
        // for an exceptional expression of `LABEL{LABELorSCALAR}' without
2796
        // type prefix (e. g. `2{-0}' in mixedRhoE B.C. in
2797
        // rhopSonicFoam/shockTube)
2798
        else if(lastValue.type() == vtkFoamToken::DICTIONARY)
2799
          {
2800
          if(lastValue.dictionary().type() == vtkFoamToken::UNIFORMLABELLIST)
2801
            {
2802
            const int size = secondLastValue.to<int>();
2803
            const int value = lastValue.dictionary().to<int>();
2804
            // delete last two values
2805
            delete valuePtrs_.back();
2806
            valuePtrs_.pop_back();
2807
            delete valuePtrs_.back();
2808
            valuePtrs_.pop_back();
2809
            // make new labelList
2810
            valuePtrs_.push_back(new vtkFoamEntryValue(this));
2811
            valuePtrs_.back()->makeLabelList(value, size);
2812
            }
2813
          else if(lastValue.dictionary().type()
2814
            == vtkFoamToken::UNIFORMSCALARLIST)
2815
            {
2816
	    const int size = secondLastValue.to<int>();
2817
            const float value = lastValue.dictionary().to<float>();
2818
            // delete last two values
2819
            delete valuePtrs_.back();
2820
            valuePtrs_.pop_back();
2821
            delete valuePtrs_.back();
2822
            valuePtrs_.pop_back();
2823
            // make new labelList
2824
            valuePtrs_.push_back(new vtkFoamEntryValue(this));
2825
            valuePtrs_.back()->makeScalarList(value, size);
2826
            }
2827
          }
2828
        }
2829
      }
2830
2831
    if(valuePtrs_.back()->type() == vtkFoamToken::IDENTIFIER)
2832
      {
2833
      // substitute identifier
2834
      const vtkStdString identifier(valuePtrs_.back()->toIdentifier());
2835
      delete valuePtrs_.back();
2836
      valuePtrs_.pop_back();
2837
2838
      for(vtkFoamDict *uDictPtr = upperDictPtr_;;)
2839
        {
2840
        const vtkFoamEntry& identifiedEntry = uDictPtr->lookup(identifier);
2841
2842
        if(identifiedEntry.found())
2843
          {
2844
          for(size_t valueI = 0; valueI < identifiedEntry.size(); valueI++)
2845
            {
2846
            valuePtrs_.push_back(
2847
              new vtkFoamEntryValue(identifiedEntry.value(valueI), this));
2848
            }
2849
          break;
2850
          }
2851
        else
2852
          {
2853
          uDictPtr = uDictPtr->upperDictPtr();
2854
          if(uDictPtr == NULL)
2855
            {
2856
            throw vtkFoamError() << "substituting entry " << identifier
2857
		 << " not found";
2858
            }
2859
          }
2860
        }
2861
      }
2862
    else if(*valuePtrs_.back() == ';')
2863
      {
2864
      delete valuePtrs_.back();
2865
      valuePtrs_.pop_back();
2866
      break;
2867
      }
2868
    else if(valuePtrs_.back()->type() == vtkFoamToken::DICTIONARY)
2869
      {
2870
      // subdictionary is not suffixed by an entry terminator ';'
2871
      break;
2872
      }
2873
    else if(*valuePtrs_.back() == '}' || *valuePtrs_.back() == ')')
2874
      {
2875
      throw vtkFoamError() << "Unmatched " << *valuePtrs_.back();
2876
      }
2877
    }
2878
}
2879
2880
//-----------------------------------------------------------------------------
2881
// constructor
2882
vtkOpenFOAMReader::vtkOpenFOAMReader()
2883
{
2884
  vtkDebugMacro(<<"Constructor");
2885
  this->SetNumberOfInputPorts(0);
2886
2887
  // INTIALIZE FILE NAME
2888
  this->FileName = NULL;
2889
2890
  // VTK CLASSES
2891
  this->PatchDataArraySelection = vtkDataArraySelection::New();
2892
  this->CellDataArraySelection = vtkDataArraySelection::New();
2893
  this->PointDataArraySelection = vtkDataArraySelection::New();
2894
  this->LagrangianDataArraySelection = vtkDataArraySelection::New();
2895
2896
  // Setup the Selection observer for the above selection arrays
2897
  this->SelectionObserver = vtkCallbackCommand::New();
2898
  this->SelectionObserver
2899
    ->SetCallback(&vtkOpenFOAMReader::SelectionModifiedCallback);
2900
  this->SelectionObserver->SetClientData(this);
2901
2902
  this->PatchDataArraySelection
2903
    ->AddObserver(vtkCommand::ModifiedEvent,this->SelectionObserver);
2904
  this->CellDataArraySelection
2905
    ->AddObserver(vtkCommand::ModifiedEvent,this->SelectionObserver);
2906
  this->PointDataArraySelection
2907
    ->AddObserver(vtkCommand::ModifiedEvent,this->SelectionObserver);
2908
  this->LagrangianDataArraySelection
2909
    ->AddObserver(vtkCommand::ModifiedEvent,this->SelectionObserver);
2910
2911
  // Initialise the Selection status arrays
2912
  this->CellSelectionOldStatus = 0xffffffff;
2913
  this->PointSelectionOldStatus = 0xffffffff;
2914
  this->LagrangianSelectionOldStatus = 0xffffffff;
2915
  this->PatchSelectionOldStatus = 0xffffffff;
2916
  this->CellSelectionStatus = 0;
2917
  this->PointSelectionStatus = 0;
2918
  this->LagrangianSelectionStatus = 0;
2919
  this->PatchSelectionStatus = 0;
2920
2921
  // DATA COUNTS
2922
  this->NumCells = 0;
2923
  this->NumPoints = 0;
2924
2925
  this->VolFieldFiles = vtkStringArray::New();
2926
  this->PointFieldFiles = vtkStringArray::New();
2927
  this->LagrangianPaths = vtkStringArray::New();
2928
  this->LagrangianFieldFiles = vtkStringArray::New();
2929
  this->OldFileName = new vtkStdString;
2930
  this->PathPrefix = new vtkStdString;
2931
  this->PolyMeshPointsDir = vtkStringArray::New();
2932
  this->PolyMeshFacesDir = vtkStringArray::New();
2933
2934
  // DATA TIMES
2935
  this->NumberOfTimeSteps = 0;
2936
  this->Steps = NULL;
2937
  this->TimeNames = vtkStringArray::New();
2938
  this->TimeStep = 0;
2939
  this->TimeStepRange[0] = 0;
2940
  this->TimeStepRange[1] = 0;
2941
2942
  // for creating cell-to-point translated data
2943
  this->CreateCellToPoint = 1;
2944
  this->CreateCellToPointOld = 1;
2945
  this->BoundaryPointMap = NULL;
2946
  this->AllBoundaries = NULL;
2947
  this->AllBoundariesPointMap = NULL;
2948
  this->InternalPoints = NULL;
2949
2950
  // for caching mesh
2951
  this->CacheMesh = 1;
2952
  this->TimeStepOld = -1;
2953
  this->InternalMesh = NULL;
2954
  this->BoundaryMesh = NULL;
2955
  this->BoundaryDict = NULL;
2956
  this->BoundaryPointMap = NULL;
2957
  this->FaceOwner = NULL;
2958
  this->PointZoneMesh = NULL;
2959
  this->FaceZoneMesh = NULL;
2960
  this->CellZoneMesh = NULL;
2961
2962
  // for decomposing polyhedra
2963
  this->DecomposePolyhedra = 1;
2964
  this->DecomposePolyhedraOld = 1;
2965
  this->AdditionalCellIds = NULL;
2966
  this->AdditionalCellPoints = NULL;
2967
2968
  // for accumulating patches across time-steps (Turned on by default)
2969
  // As of now, only accumulation of patches is implemented
2970
  this->KeepPatches = 1;
2971
  this->KeepPatchesOld = 1;
2972
2973
  // for reading old binary lagrangian/positions format
2974
  this->PositionsIsIn13Format = 0; // turned off by default
2975
  this->PositionsIsIn13FormatOld = 0;
2976
2977
  // for reading zones
2978
  this->ReadZones = 0; // turned off by default
2979
  this->ReadZonesOld = 0;
2980
2981
  // determine if time directories are to be listed according to controlDict
2982
  this->ListTimeStepsByControlDict = 0;
2983
  this->ListTimeStepsByControlDictOld = 0;
2984
2985
  // add dimensions to array names
2986
  this->AddDimensionsToArrayNames = 0;
2987
  this->AddDimensionsToArrayNamesOld = 0;
2988
}
2989
2990
//-----------------------------------------------------------------------------
2991
// destructor
2992
vtkOpenFOAMReader::~vtkOpenFOAMReader()
2993
{
2994
  vtkDebugMacro(<<"DeConstructor");
2995
2996
  // Delete the Observers before deleting the Selection Arrays !!!
2997
  this->PatchDataArraySelection->RemoveObserver(this->SelectionObserver);
2998
  this->CellDataArraySelection->RemoveObserver(this->SelectionObserver);
2999
  this->PointDataArraySelection->RemoveObserver(this->SelectionObserver);
3000
  this->LagrangianDataArraySelection->RemoveObserver(this->SelectionObserver);
3001
3002
  // Now delete the Selection Observer itself
3003
  this->SelectionObserver->Delete();
3004
3005
  // Finally delete the Selection Arrays
3006
  this->PatchDataArraySelection->Delete();
3007
  this->CellDataArraySelection->Delete();
3008
  this->PointDataArraySelection->Delete();
3009
  this->LagrangianDataArraySelection->Delete();
3010
3011
  this->SetFileName(0);
3012
  delete this->OldFileName;
3013
  delete this->PathPrefix;
3014
  this->PolyMeshPointsDir->Delete();
3015
  this->PolyMeshFacesDir->Delete();
3016
3017
  delete [] this->Steps;
3018
  this->TimeNames->Delete();
3019
  this->VolFieldFiles->Delete();
3020
  this->PointFieldFiles->Delete();
3021
  this->LagrangianPaths->Delete();
3022
  this->LagrangianFieldFiles->Delete();
3023
3024
  this->ClearMeshes();
3025
  delete this->BoundaryDict;
3026
}
3027
3028
void vtkOpenFOAMReader::ClearInternalMeshes()
3029
{
3030
  if(this->FaceOwner != NULL)
3031
    {
3032
    this->FaceOwner->Delete();
3033
    this->FaceOwner = NULL;
3034
    }
3035
  if(this->InternalMesh != NULL)
3036
    {
3037
    this->InternalMesh->Delete();
3038
    this->InternalMesh = NULL;
3039
    }
3040
  if(this->AdditionalCellIds != NULL)
3041
    {
3042
    this->AdditionalCellIds->Delete();
3043
    this->AdditionalCellIds = NULL;
3044
    }
3045
  delete this->AdditionalCellPoints;
3046
  this->AdditionalCellPoints = NULL;
3047
3048
  delete this->PointZoneMesh;
3049
  this->PointZoneMesh = NULL;
3050
  delete this->FaceZoneMesh;
3051
  this->FaceZoneMesh = NULL;
3052
  delete this->CellZoneMesh;
3053
  this->CellZoneMesh = NULL;
3054
}
3055
3056
void vtkOpenFOAMReader::ClearBoundaryMeshes()
3057
{
3058
  delete this->BoundaryMesh;
3059
  this->BoundaryMesh = NULL;
3060
3061
  delete this->BoundaryPointMap;
3062
  this->BoundaryPointMap = NULL;
3063
3064
  if(this->InternalPoints != NULL)
3065
    {
3066
    this->InternalPoints->Delete();
3067
    this->InternalPoints = NULL;
3068
    }
3069
  if(this->AllBoundaries != NULL)
3070
    {
3071
    this->AllBoundaries->Delete();
3072
    this->AllBoundaries = NULL;
3073
    }
3074
  if(this->AllBoundariesPointMap != NULL)
3075
    {
3076
    this->AllBoundariesPointMap->Delete();
3077
    this->AllBoundariesPointMap = NULL;
3078
    }
3079
}
3080
3081
void vtkOpenFOAMReader::ClearMeshes()
3082
{
3083
  this->ClearInternalMeshes();
3084
  this->ClearBoundaryMeshes();
3085
}
3086
3087
//-----------------------------------------------------------------------------
3088
// CanReadFile
3089
int vtkOpenFOAMReader::CanReadFile(const char * /* fileName */)
3090
{
3091
  // so far CanReadFile does nothing.
3092
  return 1;
3093
}
3094
3095
//-----------------------------------------------------------------------------
3096
// RequestInformation
3097
int vtkOpenFOAMReader::RequestInformation(
3098
  vtkInformation *vtkNotUsed(request),
3099
  vtkInformationVector **vtkNotUsed(inputVector),
3100
  vtkInformationVector *outputVector)
3101
{
3102
  if(!this->FileName || strlen(this->FileName) == 0)
3103
    {
3104
    vtkErrorMacro("FileName has to be specified!");
3105
    return 0;
3106
    }
3107
  vtkDebugMacro(<<"Request Info: " <<this->FileName);
3108
3109
  if(*this->OldFileName != vtkStdString(this->FileName)
3110
    || this->ListTimeStepsByControlDict != this->ListTimeStepsByControlDictOld)
3111
    {
3112
    // updated this->OldFileName
3113
    *this->OldFileName = vtkStdString(this->FileName);
3114
3115
    // clear prior case information
3116
    this->TimeStepOld = -1;
3117
    delete [] this->Steps;
3118
    this->Steps = NULL;
3119
3120
    this->ClearMeshes();
3121
    delete this->BoundaryDict;
3122
    this->BoundaryDict = NULL;
3123
3124
    this->CellDataArraySelection->RemoveAllArrays();
3125
    this->PointDataArraySelection->RemoveAllArrays();
3126
    this->LagrangianDataArraySelection->RemoveAllArrays();
3127
    this->PatchDataArraySelection->RemoveAllArrays();
3128
3129
    // make case information
3130
    if(!this->ReadControlDict(this->FileName))
3131
      {
3132
      return 0;
3133
      }
3134
    if(this->NumberOfTimeSteps == 0)
3135
      {
3136
      vtkErrorMacro(<< this->FileName << " contains no timestep data.");
3137
      return 0;
3138
      }
3139
    this->TimeStepRange[0] = 0;
3140
    this->TimeStepRange[1] = this->NumberOfTimeSteps;
3141
    this->PopulatePolyMeshDirArrays();
3142
    outputVector->GetInformationObject(0)->Set(
3143
      vtkStreamingDemandDrivenPipeline::TIME_STEPS(), this->Steps,
3144
      this->NumberOfTimeSteps);
3145
#if PARAVIEW_VERSION_MAJOR >= 3
3146
    double timeRange[2];
3147
    timeRange[0] = this->Steps[0];
3148
    timeRange[1] = this->Steps[this->NumberOfTimeSteps - 1];
3149
    outputVector->GetInformationObject(0)->Set(
3150
      vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2);
3151
#endif
3152
    }
3153
3154
  return this->MakeTimeStepData(true);
3155
}
3156
3157
//-----------------------------------------------------------------------------
3158
// RequestData
3159
int vtkOpenFOAMReader::RequestData(
3160
  vtkInformation *vtkNotUsed(request),
3161
  vtkInformationVector **vtkNotUsed(inputVector),
3162
  vtkInformationVector *outputVector)
3163
{
3164
  vtkDebugMacro(<<"Request Data");
3165
  vtkInformation* outInfo = outputVector->GetInformationObject(0);
3166
  vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::SafeDownCast(
3167
    outInfo->Get(vtkDataObject::DATA_OBJECT()));
3168
3169
  if(!this->FileName)
3170
    {
3171
    vtkErrorMacro("FileName has to be specified!");
3172
    return 0;
3173
    }
3174
3175
  if(this->NumberOfTimeSteps == 0)
3176
    {
3177
    vtkErrorMacro(<< this->FileName << " contains no timestep data.");
3178
    return 0;
3179
    }
3180
3181
  if(this->TimeStep < this->TimeStepRange[0]
3182
     || this->TimeStep > this->TimeStepRange[1])
3183
    {
3184
    vtkErrorMacro("TimeStep out of range");
3185
    return 0;
3186
    }
3187
3188
#if PARAVIEW_VERSION_MAJOR >= 3
3189
  if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS()))
3190
    {
3191
    double* requestedTimeValues
3192
      = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS());
3193
    int nSteps
3194
      = outInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
3195
    double* steps
3196
      = outInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS());
3197
#if 0    
3198
    int timeI = 0;
3199
    while(timeI < nSteps - 1 && steps[timeI] < requestedTimeValues[0])
3200
      {
3201
      timeI++;
3202
      }
3203
    this->TimeStep = timeI;
3204
    outInfo->Set(vtkDataObject::DATA_TIME_STEPS(), &steps[timeI], 1);
3205
#else
3206
    int minTimeI = 0;
3207
    if(nSteps > 0)
3208
      {
3209
      const double requestedTime = requestedTimeValues[0];
3210
      double minTimeDiff = fabs(steps[0] - requestedTime);
3211
      for(int timeI = 1; timeI < nSteps; timeI++)
3212
        {
3213
        const double timeDiff = fabs(steps[timeI] - requestedTime);
3214
        if(timeDiff < minTimeDiff)
3215
          {
3216
          minTimeI = timeI;
3217
          minTimeDiff = timeDiff;
3218
          }
3219
        }
3220
      }
3221
    this->TimeStep = minTimeI;
3222
    outInfo->Set(vtkDataObject::DATA_TIME_STEPS(), &steps[minTimeI], 1);
3223
#endif
3224
    }
3225
#endif
3226
3227
  // find fields in this timestep
3228
  if(!this->MakeTimeStepData(false))
3229
    {
3230
    return 0;
3231
    }
3232
3233
  // create dataset
3234
  const int ret = this->CreateDataSet(output, this->TimeStep);
3235
3236
  if(ret == 0)
3237
    {
3238
    return ret;
3239
    }
3240
3241
  // update selection status
3242
  this->CellSelectionOldStatus = this->CellSelectionStatus;
3243
  this->PointSelectionOldStatus = this->PointSelectionStatus;
3244
  this->LagrangianSelectionOldStatus = this->LagrangianSelectionStatus;
3245
  this->PatchSelectionOldStatus = this->PatchSelectionStatus;
3246
  this->CreateCellToPointOld = this->CreateCellToPoint;
3247
  this->DecomposePolyhedraOld = this->DecomposePolyhedra;
3248
  this->KeepPatchesOld = this->KeepPatches;
3249
  this->PositionsIsIn13FormatOld = this->PositionsIsIn13Format;
3250
  this->ReadZonesOld = this->ReadZones;
3251
  this->ListTimeStepsByControlDictOld = this->ListTimeStepsByControlDict;
3252
  this->AddDimensionsToArrayNamesOld = this->AddDimensionsToArrayNames;
3253
3254
  return ret;
3255
}
3256
3257
//-----------------------------------------------------------------------------
3258
// PrintSelf
3259
void vtkOpenFOAMReader::PrintSelf(ostream& os, vtkIndent indent)
3260
{
3261
  vtkDebugMacro(<<"Print Self");
3262
  this->Superclass::PrintSelf(os,indent);
3263
  os << indent << "File Name: "
3264
     << (this->FileName ? this->FileName : "(none)") << "\n";
3265
//  os << indent << "Number Of Nodes: " << this->NumPoints << "\n";
3266
  os << indent << "Number Of Cells: " << this->NumCells << "\n";
3267
  os << indent << "Number of Time Steps: " << this->NumberOfTimeSteps << endl;
3268
  os << indent << "TimeStepRange: "
3269
     << this->TimeStepRange[0] << " - " << this->TimeStepRange[1]
3270
     << endl;
3271
  os << indent << "TimeStep: " << this->TimeStep << endl;
3272
  return;
3273
}
3274
3275
//-----------------------------------------------------------------------------
3276
// cell selection list handlers
3277
int vtkOpenFOAMReader::GetNumberOfCellArrays()
3278
{
3279
  return this->CellDataArraySelection->GetNumberOfArrays();
3280
}
3281
3282
const char* vtkOpenFOAMReader::GetCellArrayName(int index)
3283
{
3284
  return this->CellDataArraySelection->GetArrayName(index);
3285
}
3286
3287
int vtkOpenFOAMReader::GetCellArrayStatus(const char* name)
3288
{
3289
  return this->CellDataArraySelection->ArrayIsEnabled(name);
3290
}
3291
3292
void vtkOpenFOAMReader::SetCellArrayStatus(const char* name, int status)
3293
{
3294
  if(status)
3295
    {
3296
    this->CellDataArraySelection->EnableArray(name);
3297
    }
3298
  else
3299
    {
3300
    this->CellDataArraySelection->DisableArray(name);
3301
    }
3302
}
3303
3304
void vtkOpenFOAMReader::DisableAllCellArrays()
3305
{
3306
  this->CellDataArraySelection->DisableAllArrays();
3307
}
3308
3309
void vtkOpenFOAMReader::EnableAllCellArrays()
3310
{
3311
  this->CellDataArraySelection->EnableAllArrays();
3312
}
3313
3314
//-----------------------------------------------------------------------------
3315
// point selection list handlers
3316
int vtkOpenFOAMReader::GetNumberOfPointArrays()
3317
{
3318
  return this->PointDataArraySelection->GetNumberOfArrays();
3319
}
3320
3321
const char* vtkOpenFOAMReader::GetPointArrayName(int index)
3322
{
3323
  return this->PointDataArraySelection->GetArrayName(index);
3324
}
3325
3326
int vtkOpenFOAMReader::GetPointArrayStatus(const char* name)
3327
{
3328
  return this->PointDataArraySelection->ArrayIsEnabled(name);
3329
}
3330
3331
void vtkOpenFOAMReader::SetPointArrayStatus(const char* name, int status)
3332
{
3333
  if(status)
3334
    {
3335
    this->PointDataArraySelection->EnableArray(name);
3336
    }
3337
  else
3338
    {
3339
    this->PointDataArraySelection->DisableArray(name);
3340
    }
3341
}
3342
3343
void vtkOpenFOAMReader::DisableAllPointArrays()
3344
{
3345
  this->PointDataArraySelection->DisableAllArrays();
3346
}
3347
3348
void vtkOpenFOAMReader::EnableAllPointArrays()
3349
{
3350
  this->PointDataArraySelection->EnableAllArrays();
3351
}
3352
3353
3354
//-----------------------------------------------------------------------------
3355
// lagrangian selection list handlers
3356
int vtkOpenFOAMReader::GetNumberOfLagrangianArrays()
3357
{
3358
  return this->LagrangianDataArraySelection->GetNumberOfArrays();
3359
}
3360
3361
const char* vtkOpenFOAMReader::GetLagrangianArrayName(int index)
3362
{
3363
  return this->LagrangianDataArraySelection->GetArrayName(index);
3364
}
3365
3366
int vtkOpenFOAMReader::GetLagrangianArrayStatus(const char* name)
3367
{
3368
  return this->LagrangianDataArraySelection->ArrayIsEnabled(name);
3369
}
3370
3371
void vtkOpenFOAMReader::SetLagrangianArrayStatus(const char* name, int status)
3372
{
3373
  if(status)
3374
    {
3375
    this->LagrangianDataArraySelection->EnableArray(name);
3376
    }
3377
  else
3378
    {
3379
    this->LagrangianDataArraySelection->DisableArray(name);
3380
    }
3381
}
3382
3383
void vtkOpenFOAMReader::DisableAllLagrangianArrays()
3384
{
3385
  this->LagrangianDataArraySelection->DisableAllArrays();
3386
}
3387
3388
void vtkOpenFOAMReader::EnableAllLagrangianArrays()
3389
{
3390
  this->LagrangianDataArraySelection->EnableAllArrays();
3391
}
3392
3393
3394
//-----------------------------------------------------------------------------
3395
// patch selection list handlers
3396
int vtkOpenFOAMReader::GetNumberOfPatchArrays()
3397
{
3398
  return this->PatchDataArraySelection->GetNumberOfArrays();
3399
}
3400
3401
const char* vtkOpenFOAMReader::GetPatchArrayName(int index)
3402
{
3403
  return this->PatchDataArraySelection->GetArrayName(index);
3404
}
3405
3406
int vtkOpenFOAMReader::GetPatchArrayStatus(const char* name)
3407
{
3408
  return this->PatchDataArraySelection->ArrayIsEnabled(name);
3409
}
3410
3411
void vtkOpenFOAMReader::SetPatchArrayStatus(const char* name, int status)
3412
{
3413
  if(status)
3414
    {
3415
    this->PatchDataArraySelection->EnableArray(name);
3416
    }
3417
  else
3418
    {
3419
    this->PatchDataArraySelection->DisableArray(name);
3420
    }
3421
}
3422
3423
void vtkOpenFOAMReader::DisableAllPatchArrays()
3424
{
3425
  this->PatchDataArraySelection->DisableAllArrays();
3426
}
3427
3428
void vtkOpenFOAMReader::EnableAllPatchArrays()
3429
{
3430
  this->PatchDataArraySelection->EnableAllArrays();
3431
}
3432
3433
//-----------------------------------------------------------------------------
3434
// selection observer
3435
void vtkOpenFOAMReader::SelectionModifiedCallback(vtkObject*,
3436
  unsigned long, void* clientdata, void*)
3437
{
3438
  static_cast<vtkOpenFOAMReader*>(clientdata)->SelectionModified(true);
3439
}
3440
3441
unsigned long vtkOpenFOAMReader::CreateSelectionStatus(
3442
  vtkDataArraySelection *dataArraySelection, unsigned long selectionOldStatus)
3443
{
3444
  // Change the pipeline modification time to force update
3445
  // Update the selection status to detect changes
3446
3447
  // Cell Selection Arrays
3448
  // we loop from the last element of the selection array since we'd
3449
  // like to place newly added variables to extra higher bits (we
3450
  // wouldn't like to move the locations of already existing variables)
3451
  unsigned long selectionStatus = 0;
3452
  for(int i = dataArraySelection->GetNumberOfArrays() - 1; i >= 0; i--)
3453
    {
3454
    selectionStatus = (selectionStatus << 1)
3455
      + dataArraySelection->GetArraySetting(i);
3456
    }
3457
  // if the status flag overflows we'd like to fall onto the safe side
3458
  // (properly refresh the dataset without mesh caching) so we use the
3459
  // last bit (LSB) as overflow control flag.  if overflow occurs the
3460
  // LSB is negated from the old status
3461
  if(dataArraySelection->GetNumberOfArrays()
3462
    <= static_cast<int>(sizeof(selectionStatus) * 8 - 1))
3463
    {
3464
    selectionStatus = (selectionStatus << 1) + (selectionOldStatus & 0x1);
3465
    }
3466
  else
3467
    {
3468
    selectionStatus = (selectionStatus << 1) + ((~selectionOldStatus) & 0x1);
3469
    }
3470
3471
  return selectionStatus;
3472
}
3473
3474
void vtkOpenFOAMReader::SelectionModified(const bool setModified)
3475
{
3476
  this->CellSelectionStatus = this->CreateSelectionStatus(
3477
    this->CellDataArraySelection, this->CellSelectionOldStatus);
3478
  this->PointSelectionStatus = this->CreateSelectionStatus(
3479
    this->PointDataArraySelection, this->PointSelectionOldStatus);
3480
  this->LagrangianSelectionStatus = this->CreateSelectionStatus(
3481
    this->LagrangianDataArraySelection, this->LagrangianSelectionOldStatus);
3482
  this->PatchSelectionStatus = this->CreateSelectionStatus(
3483
    this->PatchDataArraySelection, this->PatchSelectionOldStatus);
3484
3485
  // Indicate that the pipeline needs to be updated (VTK Command)
3486
  if(setModified)
3487
    {
3488
    this->Modified();
3489
    }
3490
}
3491
3492
3493
//-----------------------------------------------------------------------------
3494
void vtkOpenFOAMReader::GetFieldNames(const char *pathIn,
3495
  const bool isLagrangian, vtkStringArray *cellObjectNames,
3496
  vtkStringArray *pointObjectNames)
3497
{
3498
  const vtkStdString tempPath(pathIn);
3499
3500
  // open the directory and get num of files
3501
  vtkDirectory * directory = vtkDirectory::New();
3502
  if(!directory->Open(tempPath.c_str()))
3503
    {
3504
    // no data
3505
    directory->Delete();
3506
    return;
3507
    }
3508
3509
  // loop over all files and locate valid fields
3510
  int nFieldFiles = directory->GetNumberOfFiles();
3511
  for(int j = 0; j < nFieldFiles; j++)
3512
    {
3513
    const vtkStdString fieldFile(directory->GetFile(j));
3514
    const int len = fieldFile.length();
3515
3516
    // excluded extensions cf. src/OpenFOAM/OSspecific/Unix/Unix.C
3517
    if(!directory->FileIsDirectory(fieldFile.c_str())
3518
      && fieldFile.substr(len - 1) != "~"
3519
      && (len < 4 || (fieldFile.substr(len - 4) != ".bak"
3520
      && fieldFile.substr(len - 4) != ".BAK"
3521
      && fieldFile.substr(len - 4) != ".old"))
3522
      && (len < 5 || fieldFile.substr(len - 5) != ".save"))
3523
      {
3524
      vtkFoamIOobject io(*this->PathPrefix);
3525
      if(io.open(tempPath + "/" + fieldFile)) // file exists and readable
3526
        {
3527
        const vtkStdString& cn = io.className();
3528
        if(isLagrangian)
3529
          {
3530
          if(cn == "scalarField" || cn == "vectorField"
3531
            || cn == "sphericalTensorField" || cn == "symmTensorField"
3532
            || cn == "tensorField")
3533
            {
3534
            // real file name
3535
            this->LagrangianFieldFiles->InsertNextValue(fieldFile);
3536
            // object name
3537
            pointObjectNames->InsertNextValue(io.objectName());
3538
            }
3539
          }
3540
        else
3541
          {
3542
          if(cn == "volScalarField" || cn == "pointScalarField"
3543
            || cn == "volVectorField" || cn == "pointVectorField"
3544
            || cn == "volSphericalTensorField"
3545
            || cn == "pointSphericalTensorField"
3546
            || cn == "volSymmTensorField" || cn == "pointSymmTensorField"
3547
            || cn == "volTensorField" || cn == "pointTensorField")
3548
            {
3549
            if(cn.substr(0, 3) == "vol")
3550
              {
3551
              // real file name
3552
              this->VolFieldFiles->InsertNextValue(fieldFile);
3553
              // object name
3554
              cellObjectNames->InsertNextValue(io.objectName());
3555
              }
3556
            else
3557
              {
3558
              this->PointFieldFiles->InsertNextValue(fieldFile);
3559
              pointObjectNames->InsertNextValue(io.objectName());
3560
              }
3561
            }
3562
          }
3563
        io.close();
3564
        }
3565
      }
3566
    }
3567
  pointObjectNames->Squeeze();
3568
  if(isLagrangian)
3569
    {
3570
    this->LagrangianFieldFiles->Squeeze();
3571
    }
3572
  else
3573
    {
3574
    this->VolFieldFiles->Squeeze();
3575
    this->PointFieldFiles->Squeeze();
3576
    cellObjectNames->Squeeze();
3577
    }
3578
  directory->Delete();
3579
}
3580
3581
//-----------------------------------------------------------------------------
3582
// locate laglangian clouds
3583
void vtkOpenFOAMReader::LocateLagrangianClouds(
3584
  vtkStringArray *lagrangianObjectNames, const vtkStdString &tempPath)
3585
{
3586
  vtkDirectory *directory = vtkDirectory::New();
3587
  if(directory->Open((tempPath + "/lagrangian").c_str()))
3588
    {
3589
    // search for sub-clouds (OF 1.5 format)
3590
    const int nFiles = directory->GetNumberOfFiles();
3591
    bool isSubCloud = false;
3592
    for(int fileI = 0; fileI < nFiles; fileI++)
3593
      {
3594
      const vtkStdString fileNameI(directory->GetFile(fileI));
3595
      const vtkStdString subCloudPath(vtkStdString("lagrangian/") + fileNameI);
3596
      if(fileNameI != "." && fileNameI != ".."
3597
	&& directory->FileIsDirectory(fileNameI.c_str()))
3598
        {
3599
        vtkFoamIOobject io(*this->PathPrefix);
3600
        if(io.open(tempPath + "/" + subCloudPath + "/positions")
3601
          && io.className().find("Cloud") != vtkStdString::npos
3602
          && io.objectName() == "positions")
3603
          {
3604
          isSubCloud = true;
3605
          if(this->LagrangianPaths->LookupValue(subCloudPath) == -1)
3606
            {
3607
            this->LagrangianPaths->InsertNextValue(subCloudPath.c_str());
3608
            }
3609
          this->GetFieldNames((tempPath + "/" + subCloudPath).c_str(), true,
3610
            NULL, lagrangianObjectNames);
3611
          this->PatchDataArraySelection->AddArray(subCloudPath.c_str());
3612
          }
3613
        }
3614
      }
3615
    // if there's no sub-cloud then OF < 1.5 format
3616
    if(!isSubCloud)
3617
      {
3618
      vtkFoamIOobject io(*this->PathPrefix);
3619
      if(io.open(tempPath + "/lagrangian/positions")
3620
        && io.className() == "Cloud" && io.objectName() == "positions")
3621
        {
3622
        if(this->LagrangianPaths->LookupValue("lagrangian") == -1)
3623
          {
3624
          this->LagrangianPaths->InsertNextValue("lagrangian");
3625
          }
3626
        this->GetFieldNames((tempPath + "/lagrangian").c_str(), true, NULL,
3627
          lagrangianObjectNames);
3628
        this->PatchDataArraySelection->AddArray("lagrangian");
3629
        }
3630
      }
3631
    this->LagrangianPaths->Squeeze();
3632
    }
3633
  directory->Delete();
3634
}
3635
3636
//-----------------------------------------------------------------------------
3637
// create field data lists and cell/point array selection lists
3638
int vtkOpenFOAMReader::MakeTimeStepData(const bool listNextTimeStep)
3639
{
3640
  // Read the patches from the boundary file into selection array
3641
  int timeState = this->TimeStep;
3642
3643
  if(this->BoundaryDict == NULL
3644
   || this->PolyMeshFacesDir->GetValue(timeState) != this->BoundaryDict->timeDir
3645
    || this->PatchSelectionStatus != this->PatchSelectionOldStatus)
3646
    {
3647
    delete this->BoundaryDict;
3648
    vtkFoamDict *boundaryDict = this->GatherBlocks("polyMesh/boundary",
3649
      timeState, true);
3650
    if(boundaryDict == NULL)
3651
      {
3652
      return 0;
3653
      }
3654
    this->BoundaryDict = new vtkFoamBoundaryDict;
3655
    this->BoundaryDict->timeDir = this->PolyMeshFacesDir->GetValue(timeState);
3656
3657
    // Add the internal mesh by default always
3658
    this->PatchDataArraySelection->AddArray("Internal Mesh");
3659
3660
    // iterate through each entry in the boundary file
3661
    vtkFoamDict& boundaryDictRef = *boundaryDict;
3662
    int allBoundariesNextStartFace = 0;
3663
    for(size_t i = 0; i < boundaryDictRef.size(); i++)
3664
      {
3665
      vtkFoamEntry& boundaryEntryI = boundaryDictRef.entry(i);
3666
      vtkFoamEntry& nFacesEntry = boundaryEntryI.dictionary().lookup("nFaces");
3667
      if(!nFacesEntry.found())
3668
        {
3669
        vtkErrorMacro(<< "nFaces entry not found in boundary entry "
3670
          << boundaryEntryI.keyword().c_str());
3671
        return 0;
3672
        }
3673
      const int nFaces = nFacesEntry.toInt();
3674
3675
      // extract name of the current patch for insertion
3676
      const vtkStdString& boundaryNameI = boundaryEntryI.keyword();
3677
3678
      // create BoundaryDict entry
3679
      this->BoundaryDict->push_back(vtkFoamBoundaryEntry());
3680
      vtkFoamBoundaryEntry& BoundaryDictRef = this->BoundaryDict->back();
3681
      BoundaryDictRef.nFaces = nFaces;
3682
      BoundaryDictRef.boundaryName = boundaryNameI;
3683
      vtkFoamEntry& startFaceEntry
3684
        = boundaryEntryI.dictionary().lookup("startFace");
3685
      if(!startFaceEntry.found())
3686
        {
3687
        vtkErrorMacro(<< "startFace entry not found in boundary entry "
3688
          << boundaryEntryI.keyword().c_str());
3689
        return 0;
3690
        }
3691
3692
      BoundaryDictRef.startFace = startFaceEntry.toInt();
3693
      vtkFoamEntry& typeEntry = boundaryEntryI.dictionary().lookup("type");
3694
      if(!typeEntry.found())
3695
        {
3696
        vtkErrorMacro(<< "type entry not found in boundary entry "
3697
          << boundaryEntryI.keyword().c_str());
3698
        return 0;
3699
        }
3700
      const vtkStdString& typeNameI = typeEntry.toString();
3701
      BoundaryDictRef.isPhysicalBoundary
3702
	= (typeNameI == "patch" || typeNameI == "wall");
3703
      BoundaryDictRef.allBoundariesStartFace = allBoundariesNextStartFace;
3704
      if(BoundaryDictRef.isPhysicalBoundary)
3705
        {
3706
        allBoundariesNextStartFace += nFaces;
3707
        }
3708
      BoundaryDictRef.isActive = false;
3709
      // If the size of patch becomes zero, but KeepPatches is selected,
3710
      // do not remove from list, else, remove patch from list
3711
      if(this->PatchDataArraySelection->ArrayExists(boundaryNameI.c_str()))
3712
        {
3713
        if(nFaces <= 0 && !this->KeepPatches)
3714
          {
3715
          this->PatchDataArraySelection
3716
            ->RemoveArrayByName(boundaryNameI.c_str());
3717
          }
3718
        // Mark boundary if selected for display
3719
        else if(this->GetPatchArrayStatus(boundaryNameI.c_str()))
3720
          {
3721
          BoundaryDictRef.isActive = true;
3722
          }
3723
        }
3724
      // the patch is added to list even if its size is zero, if
3725
      // KeepPatches is set to true
3726
      else
3727
        {
3728
        this->PatchDataArraySelection->AddArray(boundaryNameI.c_str());
3729
	// patch selections are off by default
3730
        this->PatchDataArraySelection->DisableArray(boundaryNameI.c_str());
3731
        }
3732
      }
3733
3734
    delete boundaryDict;
3735
    }
3736
3737
  // Add scalars and vectors to metadata
3738
  vtkStdString tempPath
3739
    = *this->PathPrefix + this->TimeNames->GetValue(this->TimeStep);
3740
  // do not do "RemoveAllArrays()" to accumulate array selections
3741
  // this->CellDataArraySelection->RemoveAllArrays();
3742
  this->VolFieldFiles->Initialize();
3743
  this->PointFieldFiles->Initialize();
3744
  vtkStringArray *cellObjectNames = vtkStringArray::New();
3745
  vtkStringArray *pointObjectNames = vtkStringArray::New();
3746
  this->GetFieldNames(tempPath.c_str(), false, cellObjectNames,
3747
    pointObjectNames);
3748
3749
  vtkStringArray *lagrangianObjectNames = vtkStringArray::New();
3750
  this->LagrangianFieldFiles->Initialize();
3751
  if(listNextTimeStep)
3752
    {
3753
    this->LagrangianPaths->Initialize();
3754
    }
3755
  this->LocateLagrangianClouds(lagrangianObjectNames, tempPath);
3756
3757
  // if the requested timestep is 0 then we also look at the next
3758
  // timestep to add extra objects that don't exist at timestep 0 into
3759
  // selection lists. Note the ObjectNames array will be recreated in
3760
  // RequestData() so we don't have to worry about duplicated fields.
3761
  if(listNextTimeStep && this->NumberOfTimeSteps >= 2 && this->TimeStep == 0)
3762
    {
3763
    const vtkStdString tempPath
3764
      = *this->PathPrefix + this->TimeNames->GetValue(1);
3765
    this->GetFieldNames(tempPath.c_str(), false, cellObjectNames,
3766
      pointObjectNames);
3767
    // if lagrangian clouds were not found at timestep 0
3768
    if(this->LagrangianPaths->GetNumberOfTuples() == 0)
3769
      {
3770
      this->LocateLagrangianClouds(lagrangianObjectNames, tempPath);
3771
      }
3772
    }
3773
3774
#if PARAVIEW_VERSION_MAJOR >= 3
3775
  // sort array names
3776
  vtkSortDataArray::Sort(cellObjectNames, this->VolFieldFiles);
3777
#endif
3778
  for(int nameI = 0; nameI < cellObjectNames->GetNumberOfValues(); nameI++)
3779
    {
3780
    this->CellDataArraySelection
3781
      ->AddArray(cellObjectNames->GetValue(nameI).c_str());
3782
    }
3783
  cellObjectNames->Delete();
3784
#if PARAVIEW_VERSION_MAJOR >= 3
3785
  vtkSortDataArray::Sort(pointObjectNames, this->PointFieldFiles);
3786
#endif
3787
  for(int nameI = 0; nameI < pointObjectNames->GetNumberOfValues(); nameI++)
3788
    {
3789
    this->PointDataArraySelection
3790
      ->AddArray(pointObjectNames->GetValue(nameI).c_str());
3791
    }
3792
  pointObjectNames->Delete();
3793
#if PARAVIEW_VERSION_MAJOR >= 3
3794
  vtkSortDataArray::Sort(lagrangianObjectNames, this->LagrangianFieldFiles);
3795
#endif
3796
  for(int nameI = 0; nameI < lagrangianObjectNames->GetNumberOfValues();
3797
    nameI++)
3798
    {
3799
    this->LagrangianDataArraySelection
3800
      ->AddArray(lagrangianObjectNames->GetValue(nameI).c_str());
3801
    }
3802
  lagrangianObjectNames->Delete();
3803
3804
  // refresh selection status: should not change the Modified status
3805
  // when called from RequestInformation() nor RequestData().
3806
  this->SelectionModified(false);
3807
  return 1;
3808
}
3809
3810
//-----------------------------------------------------------------------------
3811
// list time directories according to controlDict
3812
bool vtkOpenFOAMReader::ListTimeDirectoriesByControlDict(vtkFoamDict* dictPtr)
3813
{
3814
  vtkFoamDict& dict = *dictPtr;
3815
3816
  vtkFoamEntry& startTimeEntry = dict.lookup("startTime");
3817
  if(!startTimeEntry.found())
3818
    {
3819
    vtkErrorMacro(<< "startTime entry not found in controlDict");
3820
    return false;
3821
    }
3822
  // using double to precisely handle time values
3823
  const double startTime = startTimeEntry.toDouble();
3824
3825
  vtkFoamEntry& endTimeEntry = dict.lookup("endTime");
3826
  if(!endTimeEntry.found())
3827
    {
3828
    vtkErrorMacro(<< "endTime entry not found in controlDict");
3829
    return false;
3830
    }
3831
  const double endTime = endTimeEntry.toDouble();
3832
3833
  vtkFoamEntry& deltaTEntry = dict.lookup("deltaT");
3834
  if(!deltaTEntry.found())
3835
    {
3836
    vtkErrorMacro(<< "deltaT entry not found in controlDict");
3837
    return false;
3838
    }
3839
  const double deltaT = deltaTEntry.toDouble();
3840
3841
  vtkFoamEntry& writeIntervalEntry = dict.lookup("writeInterval");
3842
  if(!writeIntervalEntry.found())
3843
    {
3844
    vtkErrorMacro(<< "writeInterval entry not found in controlDict");
3845
    return false;
3846
    }
3847
  const double writeInterval = writeIntervalEntry.toDouble();
3848
3849
  vtkFoamEntry& timeFormatEntry = dict.lookup("timeFormat");
3850
  if(!timeFormatEntry.found())
3851
    {
3852
    vtkErrorMacro(<< "timeFormat entry not found in controlDict");
3853
    return false;
3854
    }
3855
  const vtkStdString timeFormat(timeFormatEntry.toString());
3856
3857
  vtkFoamEntry& timePrecisionEntry = dict.lookup("timePrecision");
3858
  const int timePrecision  // default is 6
3859
    = (timePrecisionEntry.found() ? timePrecisionEntry.toInt() : 6);
3860
3861
  // calculate the time step increment based on type of run
3862
  const vtkStdString writeControl(dict.lookup("writeControl").toString());
3863
  double timeStepIncrement;
3864
  if(writeControl == "timeStep")
3865
    {
3866
    vtkDebugMacro(<<"Time step type data");
3867
    timeStepIncrement = writeInterval * deltaT;
3868
    }
3869
  else if(writeControl == "runTime" || writeControl == "adjustableRunTime")
3870
    {
3871
    vtkDebugMacro(<<"Run time type data");
3872
    timeStepIncrement = writeInterval;
3873
    }
3874
  else
3875
    {
3876
    vtkErrorMacro(<<"Time step can't be determined because writeControl is"
3877
      " set to " << writeControl.c_str());
3878
    return false;
3879
    }
3880
3881
  // calculate how many timesteps there should be
3882
  const double tempResult = (endTime - startTime) / timeStepIncrement;
3883
  // +0.5 to round up
3884
  const int tempNumTimeSteps = static_cast<int>(tempResult + 0.5) + 1;
3885
3886
  // make sure time step dir exists
3887
  vtkstd::vector<double> tempSteps;
3888
  vtkDirectory *test = vtkDirectory::New();
3889
  this->TimeNames->Initialize();
3890
3891
  // determine time name based on Foam::Time::timeName()
3892
  // cf. src/OpenFOAM/db/Time/Time.C
3893
  vtksys_ios::ostringstream parser;
3894
#ifdef _MSC_VER
3895
  bool correctExponent = true;
3896
#endif
3897
  if(timeFormat == "general")
3898
    {
3899
    // "do not use std:: or vtkstd:: when using anything declared in
3900
    // iostream," according to VTK coding standards, but following
3901
    // the instruction causes errors...
3902
    parser.setf(vtkstd::ios_base::fmtflags(0), vtkstd::ios_base::floatfield);
3903
    }
3904
  else if(timeFormat == "fixed")
3905
    {
3906
    parser.setf(vtkstd::ios_base::fmtflags(vtkstd::ios_base::fixed),
3907
      vtkstd::ios_base::floatfield);
3908
#ifdef _MSC_VER
3909
    correctExponent = false;
3910
#endif
3911
    }
3912
  else if(timeFormat == "scientific")
3913
    {
3914
    parser.setf(vtkstd::ios_base::fmtflags(vtkstd::ios_base::scientific),
3915
      vtkstd::ios_base::floatfield);
3916
    }
3917
  else
3918
    {
3919
    vtkWarningMacro("Warning: unsupported time format. Assuming general.");
3920
    parser.setf(vtkstd::ios_base::fmtflags(0), vtkstd::ios_base::floatfield);
3921
    }
3922
  parser.precision(timePrecision);
3923
3924
  for(int i = 0; i < tempNumTimeSteps; i++)
3925
    {
3926
    parser.str("");
3927
    const double tempStep = i * timeStepIncrement + startTime;
3928
    parser << tempStep; // stringstream doesn't require ends
3929
#ifdef _MSC_VER
3930
    // workaround for format difference in MSVC++:
3931
    // remove an extra 0 from exponent
3932
    if(correctExponent)
3933
      {
3934
      vtkStdString tempStr(parser.str());
3935
      size_t pos = tempStr.find('e');
3936
      if(pos != vtkStdString::npos && tempStr.length() >= pos + 3
3937
        && tempStr[pos + 2] == '0')
3938
        {
3939
        tempStr.erase(pos + 2, 1);
3940
        parser.str(tempStr);
3941
        }
3942
      }
3943
#endif
3944
    if(test->Open((*this->PathPrefix + parser.str()).c_str()))
3945
      {
3946
      tempSteps.push_back(tempStep);
3947
      this->TimeNames->InsertNextValue(parser.str());
3948
      }
3949
    // necessary for reading the case/0 directory whatever the timeFormat is
3950
    // based on Foam::Time::operator++() cf. src/OpenFOAM/db/Time/Time.C
3951
    else if((fabs(tempStep) < 1.0e-14L) // 10*SMALL
3952
      && test->Open((*this->PathPrefix + vtkStdString("0")).c_str()))
3953
      {
3954
      tempSteps.push_back(tempStep);
3955
      this->TimeNames->InsertNextValue(vtkStdString("0"));
3956
      }
3957
    }
3958
  test->Delete();
3959
  this->TimeNames->Squeeze();
3960
3961
  // Add the time steps that actually exist to steps
3962
  // allows the run to be stopped short of controlDict spec
3963
  // allows for removal of timesteps
3964
  this->NumberOfTimeSteps = tempSteps.size();
3965
  if(this->NumberOfTimeSteps > 0)
3966
    {
3967
    this->Steps = new double[this->NumberOfTimeSteps];
3968
    for(int i = 0; i < this->NumberOfTimeSteps; i++)
3969
      {
3970
      this->Steps[i] = tempSteps[i];
3971
      }
3972
    }
3973
  else
3974
    {
3975
    // dummy for safely deleting later
3976
    this->Steps = new double[1];
3977
    this->Steps[0] = startTime;
3978
3979
    // set the number of timesteps to 1 if the constant subdirectory exists
3980
    test = vtkDirectory::New();
3981
    if(test->Open((*this->PathPrefix + "constant").c_str()))
3982
      {
3983
      parser.str("");
3984
      parser << startTime;
3985
      this->TimeNames->InsertNextValue(parser.str());
3986
      this->TimeNames->Squeeze();
3987
      this->NumberOfTimeSteps = 1;
3988
      }
3989
    test->Delete();
3990
    }
3991
  return true;
3992
}
3993
3994
//-----------------------------------------------------------------------------
3995
// list time directories by searching all valid time instances in a
3996
// case directory
3997
bool vtkOpenFOAMReader::ListTimeDirectoriesByInstances()
3998
{
3999
  // open the case directory
4000
  vtkDirectory* test = vtkDirectory::New();
4001
  if(!test->Open(this->PathPrefix->c_str()))
4002
    {
4003
    test->Delete();
4004
    vtkErrorMacro(<< "Can't open directory " << this->PathPrefix->c_str());
4005
    return false;
4006
    }
4007
4008
  // search all the directories in the case directory and detect
4009
  // directories with names convertible to numbers
4010
  this->TimeNames->Initialize();
4011
  vtkDoubleArray* timeValues = vtkDoubleArray::New();
4012
  const int nFiles = test->GetNumberOfFiles();
4013
  for(int i = 0; i < nFiles; i++)
4014
    {
4015
    const vtkStdString dir = test->GetFile(i);
4016
    if(test->FileIsDirectory(dir.c_str()))
4017
      {
4018
      // check if the name is convertible to a number
4019
      bool isTimeDir = true;
4020
      for(size_t j = 0; j < dir.length(); j++)
4021
        {
4022
        const char c = dir[j];
4023
        if(!isdigit(c) && c != '+' && c != '-' && c != '.' && c != 'e'
4024
          && c != 'E')
4025
          {
4026
          isTimeDir = false;
4027
          break;
4028
          }
4029
        }
4030
      if(!isTimeDir)
4031
        {
4032
        continue;
4033
        }
4034
4035
      // convert to a number
4036
      char *endptr;
4037
      double timeValue = strtod(dir.c_str(), &endptr);
4038
      // check if the value really was converted to a number
4039
      if(timeValue == 0.0 && endptr == dir.c_str())
4040
        {
4041
        continue;
4042
        }
4043
4044
      // add to the instance list
4045
      timeValues->InsertNextValue(timeValue);
4046
      this->TimeNames->InsertNextValue(dir);
4047
      }
4048
    }
4049
  test->Delete();
4050
  timeValues->Squeeze();
4051
  this->TimeNames->Squeeze();
4052
4053
  // sort the detected time directories and set as timesteps
4054
  this->NumberOfTimeSteps = this->TimeNames->GetSize();
4055
  if(this->NumberOfTimeSteps > 0)
4056
    {
4057
    if(this->NumberOfTimeSteps > 1)
4058
      {
4059
      vtkSortDataArray::Sort(timeValues, this->TimeNames);
4060
      }
4061
    this->Steps = new double[this->NumberOfTimeSteps];
4062
    for(int i = 0; i < this->NumberOfTimeSteps; i++)
4063
      {
4064
      this->Steps[i] = timeValues->GetValue(i);
4065
      }
4066
    }
4067
  else
4068
    {
4069
    // dummy for safely deleting later
4070
    this->Steps = new double[1];
4071
    this->Steps[0] = 0.0;
4072
4073
    // set the number of timesteps to 1 if the constant subdirectory exists
4074
    test = vtkDirectory::New();
4075
    if(test->Open((*this->PathPrefix + "constant").c_str()))
4076
      {
4077
      this->TimeNames->InsertNextValue("0");
4078
      this->TimeNames->Squeeze();
4079
      this->NumberOfTimeSteps = 1;
4080
      }
4081
    test->Delete();
4082
    }
4083
  timeValues->Delete();
4084
4085
  return true;
4086
}
4087
4088
//-----------------------------------------------------------------------------
4089
// reads the controlDict file
4090
// gather the necessary information to create a path to the data
4091
bool vtkOpenFOAMReader::ReadControlDict(const char* pathIn)
4092
{
4093
#if defined(_WIN32) && PARAVIEW_VERSION_MAJOR >= 3
4094
  const vtkStdString pathFindSeparator = "/\\", pathSeparator = "\\";
4095
#else
4096
  const vtkStdString pathFindSeparator = "/", pathSeparator = "/";
4097
#endif
4098
  vtkStdString path(pathIn);
4099
4100
  // determine the case directory and path to controlDict
4101
  size_t pos = path.find_last_of(pathFindSeparator);
4102
  if(pos == vtkStdString::npos)
4103
    {
4104
    // if there's no prepending path, prefix with the current directory
4105
    path = "." + pathSeparator + path;
4106
    pos = 1;
4107
    }
4108
  if(path.substr(pos + 1, 11) == "controlDict")
4109
    {
4110
    // remove trailing "/controlDict*"
4111
    *this->PathPrefix = path.substr(0, pos - 1);
4112
    if(*this->PathPrefix == ".")
4113
      {
4114
      *this->PathPrefix = ".." + pathSeparator;
4115
      }
4116
    else
4117
      {
4118
      pos = this->PathPrefix->find_last_of(pathFindSeparator);
4119
      if(pos == vtkStdString::npos)
4120
        {
4121
        *this->PathPrefix = "." + pathSeparator;
4122
        }
4123
      else
4124
        {
4125
        // remove trailing "system" (or any other directory name)
4126
        this->PathPrefix->erase(pos + 1); // preserve the last "/"
4127
        }
4128
      }
4129
    }
4130
  else
4131
    {
4132
    // if the file is named other than controlDict*, use the directory
4133
    // containing the file as case directory
4134
    *this->PathPrefix = path.substr(0, pos + 1);
4135
    path = *this->PathPrefix + "system" + pathSeparator + "controlDict";
4136
    }
4137
4138
  // list timesteps (skip parsing controlDict entirely if
4139
  // ListTimeStepsByControlDict is set to 0)
4140
  if(this->ListTimeStepsByControlDict)
4141
    {
4142
    vtkFoamIOobject io(*this->PathPrefix);
4143
4144
    // open and check if controlDict is readable
4145
    if(!io.open(path))
4146
      {
4147
      vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": "
4148
        << io.error().c_str());
4149
      return false;
4150
      }
4151
    vtkFoamDict dict;
4152
    if(!dict.read(io))
4153
      {
4154
      vtkErrorMacro(<<"Error reading line " << io.lineNumber()
4155
        << " of " << io.fileName().c_str() << ": " << io.error().c_str());
4156
      return false;
4157
      }
4158
    if(dict.type() != vtkFoamToken::DICTIONARY)
4159
      {
4160
      vtkErrorMacro(<<"The file type of " << io.fileName().c_str()
4161
        << " is not a dictionary");
4162
      return false;
4163
      }
4164
4165
    vtkFoamEntry& writeControlEntry = dict.lookup("writeControl");
4166
    if(!writeControlEntry.found())
4167
      {
4168
      vtkErrorMacro(<< "writeControl entry not found in " << pathIn);
4169
      return false;
4170
      }
4171
    const vtkStdString writeControl(writeControlEntry.toString());
4172
4173
    // empty if not found
4174
    const vtkStdString adjustTimeStep(dict.lookup("adjustTimeStep").toString());
4175
4176
    // list time directories according to controlDict if (adjustTimeStep
4177
    // writeControl) == (off, timeStep) or (on, adjustableRunTime); list
4178
    // by time instances in the case directory otherwise (different behavior
4179
    // from paraFoam)
4180
    // valid switching words cf. src/OpenFOAM/db/Switch/Switch.C
4181
    if((((adjustTimeStep == "off" || adjustTimeStep == "no"
4182
      || adjustTimeStep == "n" || adjustTimeStep == "false"
4183
      || adjustTimeStep == "") && writeControl == "timeStep")
4184
      || ((adjustTimeStep == "on" || adjustTimeStep == "yes"
4185
      || adjustTimeStep == "y" || adjustTimeStep == "true")
4186
      && writeControl == "adjustableRunTime")))
4187
      {
4188
      return this->ListTimeDirectoriesByControlDict(&dict);
4189
      }
4190
    else
4191
      {
4192
      return this->ListTimeDirectoriesByInstances();
4193
      }
4194
    }
4195
4196
  return this->ListTimeDirectoriesByInstances();
4197
}
4198
4199
//-----------------------------------------------------------------------------
4200
void vtkOpenFOAMReader::AppendMeshDirToArray(vtkStringArray* polyMeshDir,
4201
  const char *pathIn, const int timeI)
4202
{
4203
  vtkStdString path(pathIn);
4204
  vtkFoamIOobject io(*this->PathPrefix);
4205
4206
  if(io.open(path) || io.open(path + ".gz"))
4207
    {
4208
    io.close();
4209
    // set points/faces location to current timesteps value
4210
    polyMeshDir->SetValue(timeI, this->TimeNames->GetValue(timeI));
4211
    }
4212
  else
4213
    {
4214
    if(timeI != 0)
4215
      {
4216
      // set points/faces location to previous timesteps value
4217
      polyMeshDir->SetValue(timeI, polyMeshDir->GetValue(timeI - 1));
4218
      }
4219
    else
4220
      {
4221
      // set points/faces to constant
4222
      polyMeshDir->SetValue(timeI, "constant");
4223
      }
4224
    }
4225
}
4226
4227
//-----------------------------------------------------------------------------
4228
// create a Lookup Table containing the location of the points
4229
// and faces files for each time steps mesh
4230
void vtkOpenFOAMReader::PopulatePolyMeshDirArrays()
4231
{
4232
  vtkDebugMacro(<<"Create list of points/faces file directories");
4233
4234
  // intialize size to number of timesteps
4235
  this->PolyMeshPointsDir->SetNumberOfValues(this->NumberOfTimeSteps);
4236
  this->PolyMeshFacesDir->SetNumberOfValues(this->NumberOfTimeSteps);
4237
4238
  // loop through each timestep
4239
  for(int i = 0; i < this->NumberOfTimeSteps; i++)
4240
    {
4241
    // create the path to the timestep
4242
    vtkStdString polyMeshPath
4243
      = *this->PathPrefix + this->TimeNames->GetValue(i) + "/polyMesh/";
4244
    AppendMeshDirToArray(this->PolyMeshPointsDir,
4245
      (polyMeshPath + "points").c_str(), i);
4246
    AppendMeshDirToArray(this->PolyMeshFacesDir,
4247
      (polyMeshPath + "faces").c_str(), i);
4248
    }
4249
  vtkDebugMacro(<<"Points/faces list created");
4250
  return;
4251
}
4252
4253
//-----------------------------------------------------------------------------
4254
// read the points file into a vtkFloatArray
4255
vtkFloatArray* vtkOpenFOAMReader::ReadPointsFile(int timeState)
4256
{
4257
  // path to points file
4258
  vtkStdString pointPath = *this->PathPrefix +
4259
    this->PolyMeshPointsDir->GetValue(timeState) + "/polyMesh/points";
4260
  vtkDebugMacro(<<"Read points file: "<<pointPath.c_str());
4261
4262
  vtkFoamIOobject io(*this->PathPrefix);
4263
  if(!(io.open(pointPath) || io.open(pointPath + ".gz")))
4264
    {
4265
    vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": "
4266
      << io.error().c_str());
4267
    return NULL;
4268
    }
4269
  vtkFoamDict dict;
4270
  if(!dict.read(io))
4271
    {
4272
    vtkErrorMacro(<<"Error reading line " << io.lineNumber()
4273
      << " of " << io.fileName().c_str() << ": " << io.error().c_str());
4274
    return NULL;
4275
    }
4276
  if(dict.type() != vtkFoamToken::VECTORLIST)
4277
    {
4278
    vtkErrorMacro(<<"The file type of " << io.fileName().c_str()
4279
      << " is not a vectorList");
4280
    return NULL;
4281
    }
4282
4283
  vtkFloatArray *pointArray = static_cast<vtkFloatArray *>(dict.ptr());
4284
4285
  // set the number of points
4286
  this->NumPoints = pointArray->GetNumberOfTuples();
4287
4288
  vtkDebugMacro(<<"Point file read");
4289
  return pointArray;
4290
}
4291
4292
//-----------------------------------------------------------------------------
4293
// read the faces into a intVectorVector
4294
vtkOpenFOAMReader::intVectorVector* vtkOpenFOAMReader::ReadFacesFile(
4295
  const char* facePathIn)
4296
{
4297
  const vtkStdString facePath(facePathIn);
4298
  vtkDebugMacro(<<"Read faces file: "<<facePath.c_str());
4299
4300
  vtkFoamIOobject io(*this->PathPrefix);
4301
  if(!(io.open(facePath) || io.open(facePath + ".gz")))
4302
    {
4303
    vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": "
4304
      << io.error().c_str());
4305
    return NULL;
4306
    }
4307
  vtkFoamDict dict;
4308
  if(!dict.read(io))
4309
    {
4310
    vtkErrorMacro(<<"Error reading line " << io.lineNumber()
4311
      << " of " << io.fileName().c_str() << ": " << io.error().c_str());
4312
    return NULL;
4313
    }
4314
  if(dict.type() != vtkFoamToken::LABELLISTLIST)
4315
    {
4316
    vtkErrorMacro(<<"The file type of " << io.fileName().c_str()
4317
      << " is not a labelListList");
4318
    return NULL;
4319
    }
4320
4321
  vtkDebugMacro(<<"Faces read");
4322
  return static_cast<intVectorVector *>(dict.ptr());
4323
}
4324
4325
//-----------------------------------------------------------------------------
4326
// read the owner and neighbor file and create cellFaces
4327
bool vtkOpenFOAMReader::ReadOwnerNeighborFiles(vtkIntArray *cellFacesList,
4328
  vtkIntArray *cellFacesIndices, const char* ownerPathIn,
4329
  const char* neighborPathIn)
4330
{
4331
  const vtkStdString ownerPath(ownerPathIn);
4332
  vtkDebugMacro(<<"Read owner file: "<<ownerPath.c_str());
4333
4334
  vtkFoamIOobject io(*this->PathPrefix);
4335
  if(!(io.open(ownerPath) || io.open(ownerPath + ".gz")))
4336
    {
4337
    vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": "
4338
      << io.error().c_str());
4339
    return false;
4340
    }
4341
  vtkFoamDict ownerDict;
4342
  if(!ownerDict.read(io))
4343
    {
4344
    vtkErrorMacro(<<"Error reading line " << io.lineNumber()
4345
      << " of " << io.fileName().c_str() << ": " << io.error().c_str());
4346
    return false;
4347
    }
4348
  if(ownerDict.type() != vtkFoamToken::LABELLIST)
4349
    {
4350
    vtkErrorMacro(<<"The file type of " << io.fileName().c_str()
4351
      << " is not a labelList");
4352
    return false;
4353
    }
4354
  io.close();
4355
4356
  const vtkStdString neighborPath(neighborPathIn);
4357
  vtkDebugMacro(<<"Read neighbor file: "<<neighborPath.c_str());
4358
4359
  if(!(io.open(neighborPath) || io.open(neighborPath + ".gz")))
4360
    {
4361
    vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": "
4362
      << io.error().c_str());
4363
    return false;
4364
    }
4365
  vtkFoamDict neighborDict;
4366
  if(!neighborDict.read(io))
4367
    {
4368
    vtkErrorMacro(<<"Error reading line " << io.lineNumber()
4369
      << " of " << io.fileName().c_str() << ": " << io.error().c_str());
4370
    return false;
4371
    }
4372
  if(neighborDict.type() != vtkFoamToken::LABELLIST)
4373
    {
4374
    vtkErrorMacro(<<"The file type of " << io.fileName().c_str()
4375
      << " is not a labelList");
4376
    return false;
4377
    }
4378
4379
  this->FaceOwner = static_cast<vtkIntArray *>(ownerDict.ptr());
4380
  vtkIntArray &faceOwner = *this->FaceOwner;
4381
  vtkIntArray &faceNeighbor = neighborDict.labelList();
4382
4383
  const int nFaces = faceOwner.GetNumberOfTuples();
4384
  const int nNeiFaces = faceNeighbor.GetNumberOfTuples();
4385
4386
  if(nFaces < nNeiFaces)
4387
    {
4388
    vtkErrorMacro(<<"Numbers of owner faces (" << nFaces
4389
      << ") must be equal or larger than number of neighbor faces ("
4390
      << nNeiFaces << ")");
4391
    return false;
4392
    }
4393
4394
  if(nFaces == 0)
4395
    {
4396
    vtkWarningMacro(<<"The mesh contains no faces");
4397
    }
4398
4399
  // add the face numbers to the correct cell
4400
  // cf. Terry's code and src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCells.C
4401
4402
  // find the number of cells
4403
  int nCells = -1;
4404
  for(int faceI = 0; faceI < nNeiFaces; faceI++)
4405
    {
4406
    const int ownerCell = faceOwner.GetValue(faceI);
4407
    if(nCells < ownerCell) // max(nCells, faceOwner[i])
4408
      {
4409
      nCells = ownerCell;
4410
      }
4411
    // we do need to take neighbor faces into account since all the
4412
    // surrounding faces of a cell can be neighbors for a valid mesh
4413
    const int neighborCell = faceNeighbor.GetValue(faceI);
4414
    if(nCells < neighborCell) // max(nCells, faceNeighbor[i])
4415
      {
4416
      nCells = neighborCell;
4417
      }
4418
    }
4419
  for(int faceI = nNeiFaces; faceI < nFaces; faceI++)
4420
    {
4421
    const int ownerCell = faceOwner.GetValue(faceI);
4422
    if(nCells < ownerCell) // max(nCells, faceOwner[i])
4423
      {
4424
      nCells = ownerCell;
4425
      }
4426
    }
4427
  nCells++;
4428
4429
  if(nCells == 0)
4430
    {
4431
    vtkWarningMacro(<<"The mesh contains no cells");
4432
    }
4433
4434
  // set the number of cells
4435
  this->NumCells = nCells;
4436
4437
  // count number of faces for each cell
4438
  cellFacesIndices->SetNumberOfValues(nCells + 1);
4439
  int *cfiPtr = cellFacesIndices->GetPointer(0);
4440
  for(int cellI = 0; cellI <= nCells; cellI++)
4441
    {
4442
    cfiPtr[cellI] = 0;
4443
    }
4444
  int nTotalCellFaces = 0;
4445
  cfiPtr++; // offset +1
4446
  for(int faceI = 0; faceI < nNeiFaces; faceI++)
4447
    {
4448
    const int ownerCell = faceOwner.GetValue(faceI);
4449
    // simpleFoam/pitzDaily3Blocks has faces with owner cell number -1
4450
    if(ownerCell >= 0)
4451
      {
4452
      cfiPtr[ownerCell]++;
4453
      nTotalCellFaces++;
4454
      }
4455
    const int neighborCell=faceNeighbor.GetValue(faceI);
4456
    if(neighborCell >= 0)
4457
      {
4458
      cfiPtr[neighborCell]++;
4459
      nTotalCellFaces++;
4460
      }
4461
    }
4462
  for(int faceI = nNeiFaces; faceI < nFaces; faceI++)
4463
    {
4464
    const int ownerCell = faceOwner.GetValue(faceI);
4465
    if(ownerCell >= 0)
4466
      {
4467
      cfiPtr[ownerCell]++;
4468
      nTotalCellFaces++;
4469
      }
4470
    }
4471
  cfiPtr--; // revert offset +1
4472
4473
  // allocate cellFaces. To reduce the numbers of new/delete operations we
4474
  // allocate memory space for all faces linearly
4475
  cellFacesList->SetNumberOfValues(nTotalCellFaces);
4476
4477
  // accumulate the number of cellFaces to create cellFaces indices
4478
  // and copy them to a temporary array
4479
  vtkIntArray *tmpFaceIndices = vtkIntArray::New();
4480
  tmpFaceIndices->SetNumberOfValues(nCells + 1);
4481
  int *tfiPtr = tmpFaceIndices->GetPointer(0);
4482
  tfiPtr[0] = 0;
4483
  for(int cellI = 1; cellI <= nCells; cellI++)
4484
    {
4485
    tfiPtr[cellI] = (cfiPtr[cellI] += cfiPtr[cellI - 1]);
4486
    }
4487
4488
  // add face numbers to cell-faces list
4489
  for(int faceI = 0; faceI < nNeiFaces; faceI++)
4490
    {
4491
    const int ownerCell = faceOwner.GetValue(faceI); // must be a signed int
4492
    // simpleFoam/pitzDaily3Blocks has faces with owner cell number -1
4493
    if(ownerCell >= 0)
4494
      {
4495
      cellFacesList->SetValue(tfiPtr[ownerCell]++, faceI);
4496
      }
4497
    const int neighborCell = faceNeighbor.GetValue(faceI);
4498
    if(neighborCell >= 0)
4499
      {
4500
      cellFacesList->SetValue(tfiPtr[neighborCell]++, faceI);
4501
      }
4502
    }
4503
  for(int faceI = nNeiFaces; faceI < nFaces; faceI++)
4504
    {
4505
    const int ownerCell = faceOwner.GetValue(faceI); // must be a signed int
4506
    // simpleFoam/pitzDaily3Blocks has faces with owner cell number -1
4507
    if(ownerCell >= 0)
4508
      {
4509
      cellFacesList->SetValue(tfiPtr[ownerCell]++, faceI);
4510
      }
4511
    }
4512
  tmpFaceIndices->Delete();
4513
4514
  vtkDebugMacro(<<"Owner and neighbour files read");
4515
  return true;
4516
}
4517
4518
//-----------------------------------------------------------------------------
4519
// determine cell shape and insert the cell into the mesh
4520
// hexahedron, prism, pyramid, tetrahedron and decompose polyhedron
4521
void vtkOpenFOAMReader::InsertCellsToGrid(vtkUnstructuredGrid* internalMesh,
4522
  vtkIntArray *cellFacesList, vtkIntArray *cellFacesIndices,
4523
  const intVectorVector *facesPoints, vtkFloatArray *pointArray,
4524
  vtkIdTypeArray *additionalCells, vtkIntArray *cellList)
4525
{
4526
  const int maxNPoints = 128; // assume max number of points per cell
4527
  vtkIdList* cellPoints = vtkIdList::New();
4528
  cellPoints->SetNumberOfIds(maxNPoints);
4529
  const int nCells
4530
    = (cellList == NULL ? this->NumCells : cellList->GetNumberOfTuples());
4531
  int nAdditionalPoints = 0;
4532
4533
  // alias
4534
  const intVectorVector& facePoints = *facesPoints;
4535
4536
  for(int cellI = 0; cellI < nCells ; cellI++)
4537
    {
4538
    int cellId;
4539
    if(cellList == NULL)
4540
      {
4541
      cellId = cellI;
4542
      }
4543
    else
4544
      {
4545
      cellId = cellList->GetValue(cellI);
4546
      if(cellId >= this->NumCells)
4547
        {
4548
        vtkWarningMacro(<<"cellLabels id " << cellId
4549
          << " exceeds the number of cells " << nCells);
4550
        internalMesh->InsertNextCell(VTK_EMPTY_CELL, 0,
4551
          cellPoints->GetPointer(0));
4552
        continue;
4553
        }
4554
      }
4555
    const int cfi = cellFacesIndices->GetValue(cellId);
4556
    const int *cellFaces = cellFacesList->GetPointer(cfi);
4557
    const int nCellFaces = cellFacesIndices->GetValue(cellId + 1) - cfi;
4558
4559
    // determine type of the cell
4560
    // cf. src/OpenFOAM/meshes/meshShapes/cellMatcher/{hex|prism|pyr|tet}-
4561
    // Matcher.C
4562
    int cellType = VTK_CONVEX_POINT_SET;
4563
    if(nCellFaces == 6)
4564
      {
4565
      int j = 0;
4566
      for(; j < nCellFaces; j++)
4567
        {
4568
        if(facePoints.size(cellFaces[j]) != 4)
4569
          {
4570
          break;
4571
          }
4572
        }
4573
      if(j == nCellFaces)
4574
        {
4575
        cellType = VTK_HEXAHEDRON;
4576
        }
4577
      }
4578
    else if(nCellFaces == 5)
4579
      {
4580
      int nTris = 0, nQuads = 0;
4581
      for(int j = 0; j < nCellFaces; j++)
4582
        {
4583
        const int nPoints = facePoints.size(cellFaces[j]);
4584
        if(nPoints == 3)
4585
          {
4586
          nTris++;
4587
          }
4588
        else if(nPoints == 4)
4589
          {
4590
          nQuads++;
4591
          }
4592
        else
4593
          {
4594
          break;
4595
          }
4596
        }
4597
      if(nTris == 2 && nQuads == 3)
4598
        {
4599
        cellType = VTK_WEDGE;
4600
        }
4601
      else if(nTris == 4 && nQuads == 1)
4602
        {
4603
        cellType = VTK_PYRAMID;
4604
        }
4605
      }
4606
    else if(nCellFaces == 4)
4607
      {
4608
      int j = 0;
4609
      for(; j < nCellFaces; j++)
4610
        {
4611
        if(facePoints.size(cellFaces[j]) != 3)
4612
          {
4613
          break;
4614
          }
4615
        }
4616
      if(j == nCellFaces)
4617
        {
4618
        cellType = VTK_TETRA;
4619
        }
4620
      }
4621
4622
    // not an Hex/Wedge/Pyramid/Tetra
4623
    if(cellType == VTK_CONVEX_POINT_SET)
4624
      {
4625
      int nPoints = 0;
4626
      for(int j = 0; j < nCellFaces; j++)
4627
        {
4628
        nPoints += facePoints.size(cellFaces[j]);
4629
        }
4630
      if(nPoints == 0)
4631
        {
4632
        cellType = VTK_EMPTY_CELL;
4633
        }
4634
      }
4635
4636
    // Cell shape constructor based on the one implementd by Terry
4637
    // Jordan, with lots of improvements. Not as elegant as the one in
4638
    // OpenFOAM but it's simple and works reasonably fast.
4639
4640
    // OFhex | vtkHexahedron || OFprism | vtkWedge
4641
    if (cellType == VTK_HEXAHEDRON || cellType == VTK_WEDGE)
4642
      {
4643
      // find the base face number
4644
      int baseFaceId = 8, nPoints;
4645
      if(cellType == VTK_HEXAHEDRON)
4646
        {
4647
        nPoints = 8;
4648
        baseFaceId = 0;
4649
        }
4650
      else // VTK_WEDGE
4651
        {
4652
        nPoints = 6;
4653
        for(int j = 0; j < nCellFaces; j++)
4654
          {
4655
          if(facePoints.size(cellFaces[j]) == 3)
4656
            {
4657
            baseFaceId = j;
4658
            break;
4659
            }
4660
          }
4661
        }
4662
4663
      // get first face in correct order
4664
      const int cellBaseFaceId = cellFaces[baseFaceId];
4665
      const int *face0Points = facePoints[cellBaseFaceId];
4666
      const int nBaseFacePoints = facePoints.size(cellBaseFaceId);
4667
4668
      if(this->FaceOwner->GetValue(cellBaseFaceId) == cellId)
4669
        {
4670
        for(int j = 0; j < nBaseFacePoints; j++)
4671
          {
4672
          cellPoints->SetId(j, face0Points[j]);
4673
          }
4674
        }
4675
      else
4676
        {
4677
        // patch: if it is a neighbor face flip the points
4678
        for(int j = 0; j < nBaseFacePoints; j++)
4679
          {
4680
          // add base face to cell points
4681
          cellPoints->SetId(j, face0Points[nBaseFacePoints - 1 - j]);
4682
          }
4683
        }
4684
      const int baseFacePoint0 = cellPoints->GetId(0);
4685
      const int baseFacePoint2 = cellPoints->GetId(2);
4686
      int oppositeFaceI = -1, pivotPoint = -1;
4687
      bool dupPoint2 = false;
4688
      for(int faceI = 0; faceI < nCellFaces; faceI++)
4689
        {
4690
        if(faceI == baseFaceId)
4691
          {
4692
          continue;
4693
          }
4694
        const int cellFaceI = cellFaces[faceI];
4695
        const int *faceIPoints = facePoints[cellFaceI];
4696
        const int nFaceIPoints = facePoints.size(cellFaceI);
4697
        bool found0Dup = false, found2Dup = false;
4698
        int pointI = 0;
4699
        for(; pointI < nFaceIPoints; pointI++) // each point
4700
            {
4701
            const int faceIPointI = faceIPoints[pointI];
4702
            // matching two points in base face is enough to find a
4703
            // duplicated point since neighboring faces share two
4704
            // neighboring points (i. e. an edge)
4705
            if(baseFacePoint0 == faceIPointI)
4706
              {
4707
              found0Dup = true;
4708
              break;
4709
              }
4710
            else if(baseFacePoint2 == faceIPointI)
4711
              {
4712
              found2Dup = true;
4713
              break;
4714
              }
4715
            }
4716
        if(found0Dup || found2Dup)
4717
          {
4718
          // find the pivot point if still haven't
4719
          if(pivotPoint == -1)
4720
            {
4721
            int baseFacePrevPoint, baseFaceNextPoint;
4722
            if(found0Dup)
4723
              {
4724
              baseFacePrevPoint = cellPoints->GetId(nBaseFacePoints - 1);
4725
              baseFaceNextPoint = cellPoints->GetId(1);
4726
              }
4727
            else
4728
              {
4729
              baseFacePrevPoint = cellPoints->GetId(1);
4730
              baseFaceNextPoint
4731
                = cellPoints->GetId(nBaseFacePoints == 3 ? 0 : 3);
4732
              dupPoint2 = true;
4733
              }
4734
4735
            const int faceINextPoint = faceIPoints[(pointI + 1) % nFaceIPoints];
4736
            const int faceIPrevPoint
4737
              = faceIPoints[(nFaceIPoints + pointI - 1) % nFaceIPoints];
4738
4739
            // if the next point of the faceI-th face matches the
4740
            // previous point of the base face use the previous point
4741
            // of the faceI-th face as the pivot point; or use the
4742
            // next point otherwise
4743
            if(faceINextPoint == (this->FaceOwner->GetValue(cellFaceI)
4744
              == cellId ? baseFacePrevPoint : baseFaceNextPoint))
4745
              {
4746
              pivotPoint = faceIPrevPoint;
4747
              }
4748
            else
4749
              {
4750
              pivotPoint = faceINextPoint;
4751
              }
4752
            }
4753
          }
4754
        else
4755
          {
4756
          // if no duplicated point found, faceI is the opposite face
4757
          if(oppositeFaceI == -1)
4758
            {
4759
            oppositeFaceI = faceI;
4760
            }
4761
          }
4762
4763
        // break when both of opposite face and pivot point are found
4764
        if(oppositeFaceI >= 0 && pivotPoint >= 0)
4765
          {
4766
          break;
4767
          }
400
        }
4768
        }
401
4769
402
      //patch: if it is a neighbor face flip the points
4770
      // find the pivot point in opposite face
403
      if(this->FacesOfCell->value[i][0].neighborFace)
4771
      const int cellOppositeFaceI = cellFaces[oppositeFaceI];
4772
      const int *oppositeFacePoints = facePoints[cellOppositeFaceI];
4773
      const int nOppositeFacePoints = facePoints.size(cellOppositeFaceI);
4774
      int pivotPointI = 0;
4775
      for(; pivotPointI < nOppositeFacePoints; pivotPointI++)
404
        {
4776
        {
405
        int tempPop;
4777
        if(oppositeFacePoints[pivotPointI] == pivotPoint)
406
        for(k = 0; k < (int)firstFace.size() - 1; k++)
407
          {
4778
          {
408
          tempPop = firstFace[firstFace.size()-1];
4779
          break;
409
          firstFace.pop_back();
410
          firstFace.insert(firstFace.begin()+1+k, tempPop);
411
          }
4780
          }
412
        }
4781
        }
413
4782
414
      //add first face to cell points
4783
      if(this->FaceOwner->GetValue(cellOppositeFaceI) == cellId)
415
      for(j =0; j < (int)firstFace.size(); j++)
416
        {
4784
        {
417
        cellPoints.push_back(firstFace[j]);
4785
        if(dupPoint2)
4786
          {
4787
          pivotPointI = (pivotPointI + 2) % nOppositeFacePoints;
4788
          }
4789
        int basePointI = nBaseFacePoints;
4790
        for(int pointI = pivotPointI; pointI >= 0; pointI--)
4791
          {
4792
          cellPoints->SetId(basePointI++, oppositeFacePoints[pointI]);
4793
          }
4794
        for(int pointI = nOppositeFacePoints - 1; pointI > pivotPointI;
4795
          pointI--)
4796
          {
4797
          cellPoints->SetId(basePointI++, oppositeFacePoints[pointI]);
4798
          }
418
        }
4799
        }
419
4800
      else
420
      //find the opposite face and order the points correctly
421
      for(int pointCount = 0; pointCount < (int)firstFace.size(); pointCount++)
422
        {
4801
        {
423
4802
        // shift the pivot point if the point corresponds to point 2
424
        //find the other 2 faces containing each point
4803
        // of the base face
425
        for(j = 1; j < (int)this->FacesOfCell->value[i].size(); j++) //each face
4804
        if(dupPoint2)
426
          {
4805
          {
427
          for(k = 0; k < (int)this->FacePoints->value[
4806
          pivotPointI = (nOppositeFacePoints + pivotPointI - 2)
428
            this->FacesOfCell->value[i][j].faceIndex].size(); k++) //each point
4807
            % nOppositeFacePoints;
429
            {
430
            if(firstFace[pointCount] == this->FacePoints->value[
431
              this->FacesOfCell->value[i][j].faceIndex][k])
432
              {
433
              //ANOTHER FACE WITH THE POINT
434
              for(l = 0; l < (int)this->FacePoints->value[
435
                this->FacesOfCell->value[i][j].faceIndex].size(); l++)
436
                {
437
                tempFaces[faceCount].push_back(this->FacePoints->value[
438
                  this->FacesOfCell->value[i][j].faceIndex][l]);
439
                }
440
              faceCount++;
441
              }
442
            }
443
          }
4808
          }
444
4809
        // copy the face-point list of the opposite face to cell-point list
445
        //locate the pivot point contained in faces 0 & 1
4810
        int basePointI = nBaseFacePoints;
446
        for(j = 0; j < (int)tempFaces[0].size(); j++)
4811
        for(int pointI = pivotPointI; pointI < nOppositeFacePoints; pointI++)
447
          {
4812
          {
448
          for(k = 0; k < (int)tempFaces[1].size(); k++)
4813
          cellPoints->SetId(basePointI++, oppositeFacePoints[pointI]);
449
            {
4814
          }
450
            if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] !=
4815
        for(int pointI = 0; pointI < pivotPointI; pointI++)
451
              firstFace[pointCount])
4816
          {
452
              {
4817
          cellPoints->SetId(basePointI++, oppositeFacePoints[pointI]);
453
              pivotPoint = tempFaces[0][j];
454
              break;
455
              }
456
            }
457
          }
4818
          }
458
        cellPoints.push_back(pivotPoint);
459
        tempFaces[0].clear();
460
        tempFaces[1].clear();
461
        faceCount=0;
462
        }
4819
        }
463
4820
464
      //create the hex cell and insert it into the mesh
4821
      // create the hex cell and insert it into the mesh
465
      vtkHexahedron * hexahedron= vtkHexahedron::New();
4822
      internalMesh->InsertNextCell(cellType, nPoints,
466
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
4823
        cellPoints->GetPointer(0));
467
        {
468
        hexahedron->GetPointIds()->SetId(pCount, cellPoints[pCount]);
469
        }
470
      internalMesh->InsertNextCell(hexahedron->GetCellType(),
471
        hexahedron->GetPointIds());
472
      hexahedron->Delete();
473
      cellPoints.clear();
474
      firstFace.clear();
475
      }
4824
      }
476
4825
477
    //OFprism | vtkWedge
4826
    // OFpyramid | vtkPyramid || OFtet | vtkTetrahedron
478
    else if (totalPointCount == 18)
4827
    else if (cellType == VTK_PYRAMID || cellType == VTK_TETRA)
479
      {
4828
      {
480
      faceCount = 0;
4829
      int baseFaceId = -1, nPoints;
481
      int index = 0;
4830
      if(cellType == VTK_PYRAMID)
482
483
      //find first triangular face
484
      for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++)  //each face
485
        {
4831
        {
486
        if((int)this->FacePoints->
4832
        for(int j = 0; j < nCellFaces; j++)
487
            value[this->FacesOfCell->value[i][j].faceIndex].size() == 3)
488
          {
4833
          {
489
          for(k = 0; k < (int)this->FacePoints->value[
4834
          if(facePoints.size(cellFaces[j]) == 4)
490
              this->FacesOfCell->value[i][j].faceIndex].size(); k++)
491
            {
4835
            {
492
            firstFace.push_back(this->FacePoints->value[
4836
            baseFaceId = j;
493
              this->FacesOfCell->value[i][j].faceIndex][k]);
4837
            break;
494
            index = j;
495
            }
4838
            }
496
          break;
497
          }
4839
          }
4840
        nPoints = 5;
4841
        }
4842
      else // VTK_TETRA
4843
        {
4844
        baseFaceId = 0;
4845
        nPoints = 4;
498
        }
4846
        }
499
4847
500
      //patch: if it is a neighbor face flip the points
4848
      // add first face to cell points
501
      if(this->FacesOfCell->value[i][0].neighborFace)
4849
      const int cellBaseFaceId = cellFaces[baseFaceId];
4850
      const int *baseFacePoints = facePoints[cellBaseFaceId];
4851
      const size_t nBaseFacePoints = facePoints.size(cellBaseFaceId);
4852
      if(this->FaceOwner->GetValue(cellBaseFaceId) == cellId)
502
        {
4853
        {
503
        int tempPop;
4854
        for(size_t j = 0; j < nBaseFacePoints; j++)
504
        for(k = 0; k < (int)firstFace.size() - 1; k++)
505
          {
4855
          {
506
          tempPop = firstFace[firstFace.size()-1];
4856
          cellPoints->SetId(j, baseFacePoints[j]);
507
          firstFace.pop_back();
4857
          }
508
          firstFace.insert(firstFace.begin()+1+k, tempPop);
4858
        }
4859
      else
4860
        {
4861
        // if it is a neighbor face flip the points
4862
        for(size_t j = 0; j < nBaseFacePoints; j++)
4863
          {
4864
          cellPoints->SetId(j, baseFacePoints[nBaseFacePoints - 1 - j]);
509
          }
4865
          }
510
        }
4866
        }
511
4867
512
      //add first face to cell points
4868
      // compare an adjacent face (any non base face is ok) point 1 to
513
      for(j =0; j < (int)firstFace.size(); j++)
4869
      // base face points
4870
      const int adjacentFaceId = (baseFaceId == 0) ? 1 : baseFaceId - 1;
4871
      const int cellAdjacentFaceId = cellFaces[adjacentFaceId];
4872
      const int *adjacentFacePoints = facePoints[cellAdjacentFaceId];
4873
      const int adjacentFacePoint1 = adjacentFacePoints[1];
4874
      bool foundDup = false;
4875
      for(size_t j = 0; j < nBaseFacePoints; j++)
4876
        {
4877
        // if point 1 of the adjacent face matches point j of the base face...
4878
        if(cellPoints->GetId(j) == adjacentFacePoint1)
4879
          {
4880
          // if point 2 of the adjacent face matches the previous point
4881
          // of the base face use point 0 of the adjacent face as the
4882
          // pivot point; use point 2 otherwise
4883
          cellPoints->SetId(nBaseFacePoints, (adjacentFacePoints[2]
4884
            == cellPoints->GetId((this->FaceOwner->GetValue(cellAdjacentFaceId)
4885
            == cellId ? (nBaseFacePoints + j - 1) : (j + 1)) % nBaseFacePoints))
4886
            ? adjacentFacePoints[0] : adjacentFacePoints[2]);
4887
          foundDup = true;
4888
          break;
4889
          }
4890
        }
4891
      // if point 1 of the adjacent face does not match any points of
4892
      // the base face, it's the pivot point
4893
      if(!foundDup)
514
        {
4894
        {
515
        cellPoints.push_back(firstFace[j]);
4895
        cellPoints->SetId(nBaseFacePoints, adjacentFacePoint1);
516
        }
4896
        }
517
4897
518
      //find the opposite face and order the points correctly
4898
      // create the tetra cell and insert it into the mesh
519
      for(int pointCount = 0; pointCount < (int)firstFace.size(); pointCount++)
4899
      internalMesh->InsertNextCell(cellType, nPoints,
4900
        cellPoints->GetPointer(0));
4901
      }
4902
4903
    // erronous cells
4904
    else if(cellType == VTK_EMPTY_CELL)
4905
      {
4906
      vtkWarningMacro("Warning: No points in cellId " << cellId);
4907
      internalMesh->InsertNextCell(VTK_EMPTY_CELL, 0,
4908
        cellPoints->GetPointer(0));
4909
      }
4910
4911
    // OFpolyhedron || vtkConvexPointSet
4912
    else
4913
      {
4914
      if(additionalCells != NULL) // decompose into tets and pyramids
520
        {
4915
        {
521
        //find the 2 other faces containing each point
4916
        // calculate cell centroid and insert it to point list
522
        for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++) //each face
4917
        this->AdditionalCellPoints->push_back(vtkIntArray::New());
4918
        vtkIntArray *polyCellPoints = this->AdditionalCellPoints->back();
4919
        float centroid[3];
4920
        centroid[0] = centroid[1] = centroid[2] = 0.0F;
4921
        for(int j = 0; j < nCellFaces; j++)
523
          {
4922
          {
524
          for(k = 0; k < (int)this->FacePoints->value[
4923
          // remove duplicate points from faces
525
              this->FacesOfCell->value[i][j].faceIndex].size(); k++)
4924
          const int cellFacesJ = cellFaces[j];
4925
          const int *faceJPoints = facePoints[cellFacesJ];
4926
          const size_t nFaceJPoints = facePoints.size(cellFacesJ);
4927
          for(size_t k = 0; k < nFaceJPoints; k++)
526
            {
4928
            {
527
            if(firstFace[pointCount] == this->FacePoints->value[
4929
            const int faceJPointK = faceJPoints[k];
528
               this->FacesOfCell->value[i][j].faceIndex][k] && j != index)
4930
            bool foundDup = false;
4931
            for(size_t l = 0; l < polyCellPoints->GetDataSize(); l++)
529
              {
4932
              {
530
              //ANOTHER FACE WITH POINT
4933
              if(polyCellPoints->GetValue(l) == faceJPointK)
531
              for(l = 0; l < (int)this->FacePoints->value[
532
                  this->FacesOfCell->value[i][j].faceIndex].size(); l++)
533
                {
4934
                {
534
                tempFaces[faceCount].push_back(this->FacePoints->value[
4935
                foundDup = true;
535
                  this->FacesOfCell->value[i][j].faceIndex][l]);
4936
                break; // look no more
536
                }
4937
                }
537
              faceCount++;
4938
              }
4939
            if(!foundDup)
4940
              {
4941
              polyCellPoints->InsertNextValue(faceJPointK);
4942
              float *pointK = pointArray->GetPointer(3 * faceJPointK);
4943
              centroid[0] += pointK[0];
4944
              centroid[1] += pointK[1];
4945
              centroid[2] += pointK[2];
538
              }
4946
              }
539
            }
4947
            }
540
          }
4948
          }
541
4949
        polyCellPoints->Squeeze();
542
        //locate the pivot point of faces 0 & 1
4950
        float weight = 1.0F / static_cast<float>(polyCellPoints->GetDataSize());
543
        for(j = 0; j < (int)tempFaces[0].size(); j++)
4951
        centroid[0] *= weight;
4952
        centroid[1] *= weight;
4953
        centroid[2] *= weight;
4954
        pointArray->InsertNextTuple(centroid);
4955
4956
        // polyhedron decomposition.
4957
        // a tweaked algorithm based on applications/utilities/postProcessing/
4958
        // graphics/PVFoamReader/vtkFoam/vtkFoamAddInternalMesh.C
4959
        bool insertDecomposedCell = true;
4960
        for(int j = 0; j < nCellFaces; j++)
544
          {
4961
          {
545
          for(k = 0; k < (int)tempFaces[1].size(); k++)
4962
          const int cellFacesJ = cellFaces[j];
4963
          const int *faceJPoints = facePoints[cellFacesJ];
4964
          const int nFaceJPoints = facePoints.size(cellFacesJ);
4965
          const int flipNeighbor
4966
            = (this->FaceOwner->GetValue(cellFacesJ) == cellId ? 1 : -1);
4967
          const int nTris = nFaceJPoints % 2;
4968
4969
          int vertI = 2;
4970
4971
          // shift the start and end of the vertex loop if the
4972
          // triangle of a decomposed face is going to be flat. Far
4973
          // from perfect but better than nothing to avoid flat cells
4974
          // which stops time integration of Stream Tracer especially
4975
          // for split-hex unstructured meshes created by
4976
          // e. g. autoRefineMesh
4977
          if(nFaceJPoints >= 5 && nTris)
546
            {
4978
            {
547
            if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] !=
4979
            float *point0, *point1, *point2;
548
              firstFace[pointCount])
4980
            point0 = pointArray->GetPointer(3 * faceJPoints[nFaceJPoints - 1]);
4981
            point1 = pointArray->GetPointer(3 * faceJPoints[0]);
4982
            point2 = pointArray->GetPointer(3 * faceJPoints[nFaceJPoints - 2]);
4983
            float vsizeSqr1 = 0.0F, vsizeSqr2 = 0.0F, dotProduct = 0.0F;
4984
            for(int i = 0; i < 3; i++)
549
              {
4985
              {
550
              pivotPoint = tempFaces[0][j];
4986
              const float v1 = point1[i] - point0[i],
551
              break;
4987
                v2 = point2[i] - point0[i];
4988
              vsizeSqr1 += v1 * v1;
4989
              vsizeSqr2 += v2 * v2;
4990
              dotProduct += v1 * v2;
4991
              }
4992
            // compare in squared representation to avoid using sqrt()
4993
            if(dotProduct * fabsf(dotProduct) / (vsizeSqr1 * vsizeSqr2)
4994
              < -1.0F + 1.0e-3F)
4995
              {
4996
              vertI = 1;
552
              }
4997
              }
553
            }
4998
            }
554
          }
555
        cellPoints.push_back(pivotPoint);
556
        tempFaces[0].clear();
557
        tempFaces[1].clear();
558
        faceCount=0;
559
        }
560
561
      //create the wedge cell and insert it into the mesh
562
      vtkWedge * wedge= vtkWedge::New();
563
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
564
        {
565
        wedge->GetPointIds()->SetId(pCount, cellPoints[pCount]);
566
        }
567
      internalMesh->InsertNextCell(wedge->GetCellType(),
568
        wedge->GetPointIds());
569
      cellPoints.clear();
570
      wedge->Delete();
571
      firstFace.clear();
572
      }
573
4999
574
    //OFpyramid | vtkPyramid
5000
          cellPoints->SetId(0, faceJPoints[vertI == 2 ? 0 : nFaceJPoints - 1]);
575
    else if (totalPointCount == 16)
5001
          cellPoints->SetId(4, this->NumPoints + nAdditionalPoints);
576
      {
577
      foundDup = false;
578
5002
579
      //find the quadratic face
5003
          // decompose a face into quads in order (flipping the
580
      for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++)  //each face
5004
          // decomposed face if neighbor)
581
        {
5005
          const int nQuadVerts = nFaceJPoints - 1 - nTris;
582
        if((int)this->FacePoints->
5006
          for(; vertI < nQuadVerts; vertI += 2)
583
            value[this->FacesOfCell->value[i][j].faceIndex].size() == 4)
584
          {
585
          for(k = 0; k < (int)this->FacePoints->value[
586
              this->FacesOfCell->value[i][j].faceIndex].size(); k++)
587
            {
5007
            {
588
            cellPoints.push_back(this->FacePoints->value[
5008
            cellPoints->SetId(1, faceJPoints[vertI - flipNeighbor]);
589
              this->FacesOfCell->value[i][j].faceIndex][k]);
5009
            cellPoints->SetId(2, faceJPoints[vertI]);
5010
            cellPoints->SetId(3, faceJPoints[vertI + flipNeighbor]);
5011
5012
            // if the decomposed cell is the first one insert it to
5013
            // the original position; or append to the decomposed cell
5014
            // list otherwise
5015
            if(insertDecomposedCell)
5016
              {
5017
              internalMesh->InsertNextCell(VTK_PYRAMID, 5,
5018
                cellPoints->GetPointer(0));
5019
              insertDecomposedCell = false;
5020
              }
5021
            else
5022
              {
5023
              this->AdditionalCellIds->InsertNextValue(cellId);
5024
              additionalCells->InsertNextTupleValue(cellPoints->GetPointer(0));
5025
              }
590
            }
5026
            }
591
          break;
592
          }
593
        }
594
5027
595
      //compare first face points to other faces
5028
          // if the number of vertices is odd there's a triangle
596
      for(j = 0; j < (int)cellPoints.size(); j++) //each point
5029
          if(nTris)
597
        {
598
        for(k = 0; k < (int)this->FacePoints->value[
599
          this->FacesOfCell->value[i][1].faceIndex].size(); k++)
600
          {
601
          if(cellPoints[j] == this->FacePoints->value[
602
            this->FacesOfCell->value[i][1].faceIndex][k])
603
            {
5030
            {
604
            foundDup = true;
5031
            if(flipNeighbor == -1)
5032
              {
5033
              cellPoints->SetId(1, faceJPoints[vertI]);
5034
              cellPoints->SetId(2, faceJPoints[vertI - 1]);
5035
              }
5036
            else
5037
              {
5038
              cellPoints->SetId(1, faceJPoints[vertI - 1]);
5039
              cellPoints->SetId(2, faceJPoints[vertI]);
5040
              }
5041
            cellPoints->SetId(3, this->NumPoints + nAdditionalPoints);
5042
5043
            if(insertDecomposedCell)
5044
              {
5045
              internalMesh->InsertNextCell(VTK_TETRA, 4,
5046
                cellPoints->GetPointer(0));
5047
              insertDecomposedCell = false;
5048
              }
5049
            else
5050
              {
5051
              // set the 5th vertex number to -1 to distinguish a tetra cell
5052
              cellPoints->SetId(4, -1);
5053
              this->AdditionalCellIds->InsertNextValue(cellId);
5054
              additionalCells->InsertNextTupleValue(cellPoints->GetPointer(0));
5055
              }
605
            }
5056
            }
606
          }
5057
          }
607
        if(!foundDup)
5058
        nAdditionalPoints++;
608
          {
609
          cellPoints.push_back(this->FacePoints->value[
610
            this->FacesOfCell->value[i][j].faceIndex][k]);
611
          break;
612
          }
613
        }
614
615
      //create the pyramid cell and insert it into the mesh
616
      vtkPyramid * pyramid = vtkPyramid::New();
617
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
618
        {
619
        pyramid->GetPointIds()->SetId(pCount, cellPoints[pCount]);
620
        }
5059
        }
621
      internalMesh->InsertNextCell(pyramid->GetCellType(),
5060
      else // don't decompose; use VTK_CONVEX_PONIT_SET
622
        pyramid->GetPointIds());
623
      cellPoints.clear();
624
      pyramid->Delete();
625
      }
626
627
    //OFtet | vtkTetrahedron
628
    else if (totalPointCount == 12)
629
      {
630
      foundDup = false;
631
632
      //add first face to cell points
633
      for(j = 0; j < (int)this->FacePoints->value[
634
        this->FacesOfCell->value[i][0].faceIndex].size(); j++)
635
        {
5061
        {
636
        cellPoints.push_back(this->FacePoints->value[
5062
        // get first face
637
          this->FacesOfCell->value[i][0].faceIndex][j]);
5063
        const int cellFaces0 = cellFaces[0];
638
        }
5064
        const int *baseFacePoints = facePoints[cellFaces0];
639
5065
        const int nBaseFacePoints = facePoints.size(cellFaces0);
640
      //compare first face to the points of second face
5066
        int nPoints = nBaseFacePoints;
641
      for(j = 0; j < (int)cellPoints.size(); j++) //each point
5067
        if(nPoints > maxNPoints)
642
        {
5068
          {
643
        for(k = 0; k < (int)this->FacePoints->value[
5069
          vtkErrorMacro(<< "Too large polyhedron at cellId = " << cellId);
644
          this->FacesOfCell->value[i][1].faceIndex].size(); k++)
5070
          return;
5071
          }
5072
        // add first face to cell points
5073
        // not sure if flipping is necessary but do it anyway
5074
        if(this->FaceOwner->GetValue(cellFaces0) == cellId)
645
          {
5075
          {
646
          if(cellPoints[j] == this->FacePoints->value[
5076
          for(int j = 0; j < nBaseFacePoints; j++)
647
            this->FacesOfCell->value[i][1].faceIndex][k])
648
            {
5077
            {
649
            foundDup = true;
5078
            cellPoints->SetId(j, baseFacePoints[j]);
650
            }
5079
            }
651
          }
5080
          }
652
        if(!foundDup)
5081
        else
653
          {
5082
          {
654
          cellPoints.push_back(this->FacePoints->value[
5083
          // if it is a neighbor face flip the points
655
            this->FacesOfCell->value[i][j].faceIndex][k]);
5084
          for(int j = 0; j < nBaseFacePoints; j++)
656
          break;
5085
            {
5086
            cellPoints->SetId(j, baseFacePoints[nBaseFacePoints - 1 - j]);
5087
            }
657
          }
5088
          }
658
        }
659
660
      //create the wedge cell and insert it into the mesh
661
      vtkTetra * tetra = vtkTetra::New();
662
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
663
        {
664
        tetra->GetPointIds()->SetId(pCount, cellPoints[pCount]);
665
        }
666
      internalMesh->InsertNextCell(tetra->GetCellType(),
667
        tetra->GetPointIds());
668
      cellPoints.clear();
669
      tetra->Delete();
670
      }
671
672
    //erronous cells
673
    else if(totalPointCount == 0)
674
      {
675
      vtkWarningMacro("Warning: No points in cell.");
676
      }
677
678
    //OFpolyhedron || vtkConvexPointSet
679
    else
680
      {
681
      vtkWarningMacro("Warning: Polyhedral Data is very Slow!");
682
      foundDup = false;
683
5089
684
      //get first face
5090
        // loop through faces and create a list of all points
685
      for(j = 0; j < (int)this->FacePoints->value[
5091
        // j = 1 skip baseFace
686
        this->FacesOfCell->value[i][0].faceIndex].size(); j++)
5092
        for(int j = 1; j < nCellFaces; j++)
687
        {
688
        firstFace.push_back(this->FacePoints->value[
689
          this->FacesOfCell->value[i][0].faceIndex][j]);
690
        }
691
692
      //add first face to cell points
693
      for(j =0; j < (int)firstFace.size(); j++)
694
        {
695
        cellPoints.push_back(firstFace[j]);
696
        }
697
698
      //loop through faces and create a list of all points
699
      //j = 1 skip firstFace
700
      for(j = 1; j < (int)this->FacesOfCell->value[i].size(); j++)
701
        {
702
        //remove duplicate points from faces
703
        for(k = 0; k < (int)this->FacePoints->value[
704
          this->FacesOfCell->value[i][j].faceIndex].size(); k++)
705
          {
5093
          {
706
          for(l = 0; l < (int)cellPoints.size(); l++);
5094
          // remove duplicate points from faces
5095
          const int cellFacesJ = cellFaces[j];
5096
          const int *faceJPoints = facePoints[cellFacesJ];
5097
          const size_t nFaceJPoints = facePoints.size(cellFacesJ);
5098
          for(size_t k = 0; k < nFaceJPoints; k++)
707
            {
5099
            {
708
            if(cellPoints[l] == this->FacePoints->value[
5100
            const int faceJPointK = faceJPoints[k];
709
              this->FacesOfCell->value[i][j].faceIndex][k])
5101
            bool foundDup = false;
5102
            for(int l = 0; l < nPoints; l++)
5103
              {
5104
              if(cellPoints->GetId(l) == faceJPointK)
5105
                {
5106
                foundDup = true;
5107
                break; // look no more
5108
                }
5109
              }
5110
            if(!foundDup)
710
              {
5111
              {
711
              foundDup = true;
5112
              if(nPoints >= maxNPoints)
5113
                {
5114
                vtkErrorMacro(<< "Too large polyhedron at cellId = " << cellId);
5115
                return;
5116
                }
5117
              cellPoints->SetId(nPoints++, faceJPointK);
712
              }
5118
              }
713
            }
5119
            }
714
          if(!foundDup)
715
            {
716
            cellPoints.push_back(this->FacePoints->value[
717
              this->FacesOfCell->value[i][j].faceIndex][k]);
718
            foundDup = false;
719
            }
720
          }
5120
          }
721
        }
722
5121
723
      //create the poly cell and insert it into the mesh
5122
        // create the poly cell and insert it into the mesh
724
      vtkConvexPointSet * poly = vtkConvexPointSet::New();
5123
        internalMesh->InsertNextCell(VTK_CONVEX_POINT_SET, nPoints,
725
      poly->GetPointIds()->SetNumberOfIds(cellPoints.size());
5124
          cellPoints->GetPointer(0));
726
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
727
        {
728
        poly->GetPointIds()->SetId(pCount, cellPoints[pCount]);
729
        }
5125
        }
730
      internalMesh->InsertNextCell(poly->GetCellType(),
731
        poly->GetPointIds());
732
      cellPoints.clear();
733
      firstFace.clear();
734
      poly->Delete();
735
      }
5126
      }
736
    }
5127
    }
737
5128
  cellPoints->Delete();
738
  //set the internal mesh points
739
  internalMesh->SetPoints(Points);
740
  vtkDebugMacro(<<"Internal mesh made");
741
  return internalMesh;
742
}
5129
}
743
5130
744
// ****************************************************************************
5131
//-----------------------------------------------------------------------------
745
//  Method: vtkOpenFOAMReader::ControlDictDataParser
5132
void vtkOpenFOAMReader::SetDataObjectName(vtkDataObject *dataset,
746
//
5133
  const char *name)
747
//  Purpose:
748
//  parse out double values for controlDict entries
749
//  utility function
750
//
751
// ****************************************************************************
752
double vtkOpenFOAMReader::ControlDictDataParser(const char * lineIn)
753
{
5134
{
754
  double value;
5135
  vtkCharArray* nmArray = vtkCharArray::New();
755
  vtkstd::string line(lineIn);
5136
  nmArray->SetName("Name");
756
  line.erase(line.begin()+line.find(";"));
5137
  const size_t len = strlen(name);
757
  vtkstd::string token;
5138
  nmArray->SetNumberOfTuples(static_cast<vtkIdType>(len)+1);
758
  vtksys_ios::stringstream tokenizer(line);
5139
  char* copy = nmArray->GetPointer(0);
759
5140
  memcpy(copy, name, len);
760
  //parse to the final entry - double
5141
  copy[len] = '\0';
761
  //while(tokenizer>>token);
5142
  dataset->GetFieldData()->AddArray(nmArray);
762
  while(!tokenizer.eof())
5143
  nmArray->Delete();
763
    {
764
    tokenizer >> token;
765
    }
766
767
  vtksys_ios::stringstream conversion(token);
768
  conversion >> value;
769
  return value;
770
}
5144
}
771
5145
772
// ****************************************************************************
5146
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
773
//  Method: vtkOpenFOAMReader::ReadControlDict
5147
//-----------------------------------------------------------------------------
774
//
5148
void vtkOpenFOAMReader::SetBlockName(vtkMultiBlockDataSet *blocks,
775
//  Pupose:
5149
  unsigned int blockI, const char *name)
776
//  reads the controlDict File
777
//  gather the necessary information to create a path to the data
778
//
779
// ****************************************************************************
780
void vtkOpenFOAMReader::ReadControlDict ()
781
{
5150
{
782
  vtkDebugMacro(<<"Read controlDict");
5151
  blocks->GetMetaData(blockI)->Set(vtkCompositeDataSet::NAME(), name);
783
  //create variables
784
  vtkstd::string temp;
785
  double startTime;
786
  double endTime;
787
  double deltaT;
788
  double writeInterval;
789
  double timeStepIncrement;
790
  vtkstd::string writeControl;
791
  vtkstd::string timeFormat;
792
  stdString* tempStringStruct;
793
794
  ifstream * input = new ifstream(this->Path->value.c_str(), ios::in VTK_IOS_NOCREATE);
795
796
  //create the path to the data directory
797
  this->PathPrefix->value = this->Path->value;
798
  this->PathPrefix->value.erase(this->PathPrefix->value.begin()+
799
    this->PathPrefix->value.find("system"),this->PathPrefix->value.end());
800
  vtkDebugMacro(<<"Path: "<<this->PathPrefix->value.c_str());
801
802
  //find Start Time
803
  tempStringStruct = this->GetLine(input);
804
  temp = tempStringStruct->value;
805
  delete tempStringStruct;
806
807
  //while(!(temp.compare(0,8,"startTime",0,8) == 0))
808
  while (strcmp(temp.substr(0,9).c_str(), "startTime"))
809
    {
810
    tempStringStruct = this->GetLine(input);
811
    temp = tempStringStruct->value;
812
    delete tempStringStruct;
813
    }
814
  startTime = this->ControlDictDataParser(temp.c_str());
815
  vtkDebugMacro(<<"Start time: "<<startTime);
816
817
  //find End Time
818
  //while(!(temp.compare(0,6,"endTime",0,6) == 0))
819
  while (strcmp(temp.substr(0,7).c_str(), "endTime"))
820
    {
821
    tempStringStruct = this->GetLine(input);
822
    temp = tempStringStruct->value;
823
    delete tempStringStruct;
824
    }
825
  endTime = this->ControlDictDataParser(temp.c_str());
826
  vtkDebugMacro(<<"End time: "<<endTime);
827
828
  //find Delta T
829
  //while(!(temp.compare(0,5,"deltaT",0,5) == 0))
830
  while (strcmp(temp.substr(0,6).c_str(), "deltaT"))
831
    {
832
    tempStringStruct = this->GetLine(input);
833
    temp = tempStringStruct->value;
834
    delete tempStringStruct;
835
    }
836
  deltaT = this->ControlDictDataParser(temp.c_str());
837
  vtkDebugMacro(<<"deltaT: "<<deltaT);
838
839
  //find write control
840
  //while(!(temp.compare(0,11,"writeControl",0,11) == 0))
841
  while (strcmp(temp.substr(0,12).c_str(), "writeControl"))
842
    {
843
    tempStringStruct = this->GetLine(input);
844
    temp = tempStringStruct->value;
845
    delete tempStringStruct;
846
    }
847
848
  temp.erase(temp.begin()+temp.find(";"));
849
  vtkstd::string token;
850
  vtksys_ios::stringstream tokenizer(temp);
851
852
  //while(tokenizer >> token);
853
  while(!tokenizer.eof())
854
    {
855
    tokenizer >> token;
856
    }
857
  writeControl = token;
858
  vtkDebugMacro(<<"Write control: "<<writeControl.c_str());
859
860
  //find write interval
861
  //while(!(temp.compare(0,12,"writeInterval",0,12) == 0))
862
  while (strcmp(temp.substr(0,13).c_str(), "writeInterval"))
863
    {
864
    tempStringStruct = this->GetLine(input);
865
    temp = tempStringStruct->value;
866
    delete tempStringStruct;
867
    }
868
  writeInterval = this->ControlDictDataParser(temp.c_str());
869
  vtkDebugMacro(<<"Write interval: "<<writeInterval);
870
871
  //calculate the time step increment based on type of run
872
  //if(writeControl.compare(0,7,"timeStep",0,7) == 0)
873
  if(!strcmp(writeControl.substr(0,8).c_str(), "timeStep"))
874
    {
875
    vtkDebugMacro(<<"Time step type data");
876
    timeStepIncrement = writeInterval * deltaT;
877
    }
878
  else
879
    {
880
    vtkDebugMacro(<<"Run time type data");
881
    timeStepIncrement = writeInterval;
882
    }
883
884
  //find time format
885
  while(temp.find("timeFormat") == vtkstd::string::npos)
886
    {
887
    tempStringStruct = this->GetLine(input);
888
    temp = tempStringStruct->value;
889
    delete tempStringStruct;
890
    }
891
  timeFormat = temp;
892
893
  //calculate how many timesteps there should be
894
  float tempResult = ((endTime-startTime)/timeStepIncrement);
895
  int tempNumTimeSteps = (int)(tempResult+0.5)+1;  //+0.1 to round up
896
  //make sure time step dir exists
897
  vtkstd::vector< double > tempSteps;
898
  vtkDirectory * test = vtkDirectory::New();
899
  vtksys_ios::stringstream parser;
900
  double tempStep;
901
  for(int i = 0; i < tempNumTimeSteps; i++)
902
    {
903
    tempStep = i*timeStepIncrement + startTime;
904
    parser.clear();
905
    if(timeFormat.find("general") != vtkstd::string::npos)
906
      {
907
      parser << tempStep;
908
      }
909
    else
910
      {
911
      parser << ios::scientific <<tempStep;
912
      }
913
    if(test->Open((this->PathPrefix->value+parser.str().c_str()).c_str()))
914
      {
915
      tempSteps.push_back(tempStep);
916
      }
917
    }
918
  test->Delete();
919
920
  //Add the time steps that actually exist to steps
921
  //allows the run to be stopped short of controlDict spec
922
  //allows for removal of timesteps
923
  this->NumberOfTimeSteps = static_cast<int>(tempSteps.size());
924
  this->Steps = new double[this->NumberOfTimeSteps];
925
  for(int i = 0; i < this->NumberOfTimeSteps; i++)
926
    {
927
    this->Steps[i] =tempSteps[i];
928
    }
929
930
  input->close();
931
  delete input;
932
  vtkDebugMacro(<<"controlDict read");
933
  return;
934
}
5152
}
935
5153
936
// ****************************************************************************
5154
//-----------------------------------------------------------------------------
937
//  Method: vtkOpenFOAMReader::GetPoints
5155
void vtkOpenFOAMReader::SetBlockName(vtkMultiBlockDataSet *blocks,
938
//
5156
  unsigned int blockI, vtkDataObject *dataset)
939
//  Purpose:
940
//  read the points file into a vtkPoints
941
//
942
// ****************************************************************************
943
void vtkOpenFOAMReader::GetPoints (int timeState)
944
{
5157
{
945
  //path to points file
5158
  vtkCharArray *blockNameArray = vtkCharArray::SafeDownCast(dataset
946
  vtkstd::string pointPath = this->PathPrefix->value +
5159
    ->GetFieldData()->GetArray("Name"));
947
                             this->PolyMeshPointsDir->value[timeState] +
5160
  this->SetBlockName(blocks, blockI, blockNameArray->GetPointer(0));
948
                             "/polyMesh/points";
949
  vtkDebugMacro(<<"Read points file: "<<pointPath.c_str());
950
951
  vtkstd::string temp;
952
  bool binaryWriteFormat;
953
  stdString* tempStringStruct;
954
  ifstream * input = new ifstream(pointPath.c_str(), ios::in VTK_IOS_NOCREATE);
955
  //make sure file exists
956
  if(input->fail())
957
    {
958
    input->close();
959
    delete input;
960
    return;
961
    }
962
963
  //determine if file is binary or ascii
964
  while(temp.find("format") == vtkstd::string::npos)
965
    {
966
    tempStringStruct = this->GetLine(input);
967
    temp = tempStringStruct->value;
968
    delete tempStringStruct;
969
    }
970
  input->close();
971
972
  //reopen file in correct format
973
  if(temp.find("binary") != vtkstd::string::npos)
974
    {
975
#ifdef _WIN32
976
    input->open(pointPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
977
#else
978
    input->open(pointPath.c_str(), ios::in VTK_IOS_NOCREATE);
979
#endif
980
    binaryWriteFormat = true;
981
    }
982
  else
983
    {
984
    input->open(pointPath.c_str(),ios::in);
985
    binaryWriteFormat = false;
986
    }
987
988
  double x,y,z;
989
  vtksys_ios::stringstream tokenizer;
990
991
  //instantiate the points class
992
  this->Points->Reset();
993
994
  //find end of header
995
  //while(temp.compare(0,4, "// *", 0, 4) != 0)
996
  while (strcmp(temp.substr(0,4).c_str(), "// *"))
997
    {
998
    tempStringStruct = this->GetLine(input);
999
    temp = tempStringStruct->value;
1000
    delete tempStringStruct;
1001
    }
1002
1003
  //find number of points
1004
  tempStringStruct = this->GetLine(input);
1005
  temp = tempStringStruct->value;
1006
  delete tempStringStruct;
1007
  while(temp.empty())
1008
    {
1009
    tempStringStruct = this->GetLine(input);
1010
    temp = tempStringStruct->value;
1011
    delete tempStringStruct;
1012
    }
1013
1014
  //read number of points
1015
  tokenizer << temp;
1016
  tokenizer >> NumPoints;
1017
  //binary data
1018
  if(binaryWriteFormat)
1019
    {
1020
    input->get(); //parenthesis
1021
    for(int i = 0; i < NumPoints; i++)
1022
      {
1023
      input->read((char *)&x,sizeof(double));
1024
      input->read((char *)&y,sizeof(double));
1025
      input->read((char *)&z,sizeof(double));
1026
      this->Points->InsertPoint(i,x,y,z);
1027
      }
1028
    }
1029
1030
  //ascii data
1031
  else
1032
    {
1033
    tempStringStruct = this->GetLine(input);
1034
    temp = tempStringStruct->value;
1035
    delete tempStringStruct;
1036
    for(int i = 0; i < this->NumPoints; i++)
1037
      {
1038
      tempStringStruct = this->GetLine(input);
1039
      temp = tempStringStruct->value;
1040
      delete tempStringStruct;
1041
      temp.erase(temp.begin()+temp.find("("));
1042
      temp.erase(temp.begin()+temp.find(")"));
1043
      tokenizer.clear();
1044
      tokenizer << temp;
1045
      tokenizer >> x;
1046
      tokenizer >> y;
1047
      tokenizer >> z;
1048
      this->Points->InsertPoint(i,x,y,z);
1049
      }
1050
    }
1051
1052
  input->close();
1053
  delete input;
1054
  vtkDebugMacro(<<"Point file read");
1055
  return;
1056
}
5161
}
1057
1058
// ****************************************************************************
1059
//  Method: vtkOpenFOAMReader::ReadFacesFile
1060
//
1061
//  Purpose:
1062
//  read the faces into a vtkstd::vector
1063
//
1064
// ****************************************************************************
1065
void vtkOpenFOAMReader::ReadFacesFile (const char * facePathIn)
1066
{
1067
  vtkstd::string facePath(facePathIn);
1068
  vtkDebugMacro(<<"Read faces file: "<<facePath.c_str());
1069
  vtkstd::string temp;
1070
  stdString* tempStringStruct;
1071
  bool binaryWriteFormat;
1072
  ifstream * input = new ifstream(facePath.c_str(), ios::in VTK_IOS_NOCREATE);
1073
  //make sure file exists
1074
  if(input->fail())
1075
    {
1076
    input->close();
1077
    delete input;
1078
    return;
1079
    }
1080
1081
  //determine if file is binary or ascii
1082
  while(temp.find("format") == vtkstd::string::npos)
1083
    {
1084
    tempStringStruct = this->GetLine(input);
1085
    temp = tempStringStruct->value;
1086
    delete tempStringStruct;
1087
    }
1088
  input->close();
1089
1090
  //reopen file in correct format
1091
  if(temp.find("binary") != vtkstd::string::npos)
1092
    {
1093
#ifdef _WIN32
1094
    input->open(facePath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
1095
#else
1096
    input->open(facePath.c_str(), ios::in VTK_IOS_NOCREATE);
1097
#endif
5162
#endif
1098
    binaryWriteFormat = true;
1099
    }
1100
  else
1101
    {
1102
    input->open(facePath.c_str(),ios::in);
1103
    binaryWriteFormat = false;
1104
    }
1105
5163
1106
  vtksys_ios::stringstream tokenizer;
5164
//-----------------------------------------------------------------------------
1107
  size_t pos;
5165
// derive cell types and create the internal mesh
1108
  int numFacePoints;
5166
vtkUnstructuredGrid * vtkOpenFOAMReader::MakeInternalMesh(
1109
  this->FacePoints->value.clear();
5167
  vtkIntArray *cellFacesList, vtkIntArray *cellFacesIndices,
5168
  const intVectorVector *facesPoints, vtkFloatArray *pointArray)
5169
{
5170
  vtkDebugMacro(<<"Make internal mesh");
1110
5171
1111
  //find end of header
5172
  // Create Mesh
1112
  //while(temp.compare(0,4, "// *", 0, 4) != 0)
5173
  vtkUnstructuredGrid* internalMesh = vtkUnstructuredGrid::New();
1113
  while (strcmp(temp.substr(0,4).c_str(), "// *"))
5174
  internalMesh->Allocate(this->NumCells);
1114
    {
1115
    tempStringStruct = this->GetLine(input);
1116
    temp = tempStringStruct->value;
1117
    delete tempStringStruct;
1118
    }
1119
5175
1120
  //find number of faces
5176
  if(this->DecomposePolyhedra)
1121
  tempStringStruct = this->GetLine(input);
1122
  temp = tempStringStruct->value;
1123
  delete tempStringStruct;
1124
  while(temp.empty())
1125
    {
5177
    {
1126
    tempStringStruct = this->GetLine(input);
5178
    // for polyhedral decomposition
1127
    temp = tempStringStruct->value;
5179
    this->AdditionalCellIds = vtkIntArray::New();
1128
    delete tempStringStruct;
5180
    this->AdditionalCellPoints = new intArrayVector;
1129
    }
1130
1131
  //read number of faces
1132
  tokenizer << temp;
1133
  tokenizer >> this->NumFaces;
1134
  this->FacePoints->value.resize(this->NumFaces);
1135
5181
1136
  tempStringStruct = this->GetLine(input);
5182
    vtkIdTypeArray *additionalCells = vtkIdTypeArray::New();
1137
  temp = tempStringStruct->value;
5183
    additionalCells->SetNumberOfComponents(5); // accommodates tetra or pyramid
1138
  delete tempStringStruct;//THROW OUT "("
1139
5184
1140
  //binary data
5185
    this->InsertCellsToGrid(internalMesh, cellFacesList, cellFacesIndices,
1141
  if(binaryWriteFormat)
5186
      facesPoints, pointArray, additionalCells, NULL);
1142
    {
1143
    //char paren;
1144
    int tempPoint;
1145
    for(int i = 0; i < NumFaces; i++)
1146
      {
1147
      tempStringStruct = this->GetLine(input);
1148
      temp = tempStringStruct->value;
1149
      delete tempStringStruct;//THROW OUT blankline
1150
5187
1151
      tempStringStruct = this->GetLine(input);
5188
    // for polyhedral decomposition
1152
      temp = tempStringStruct->value;
5189
    pointArray->Squeeze();
1153
      delete tempStringStruct; //grab point count
5190
    this->AdditionalCellIds->Squeeze();
5191
    additionalCells->Squeeze();
1154
5192
1155
      tokenizer.clear();
5193
    // insert decomposed cells into mesh
1156
      tokenizer << temp;
5194
    const int nComponents = additionalCells->GetNumberOfComponents();
1157
      tokenizer >> numFacePoints;
5195
    const int nAdditionalCells = additionalCells->GetNumberOfTuples();
1158
      this->FacePoints->value[i].resize(numFacePoints);
5196
    for(int i = 0; i < nAdditionalCells; i++)
1159
      //paren = input->get();  //grab (
5197
      {
1160
      input->get();  //grab (
5198
      if(additionalCells->GetComponent(i, 4) == -1)
1161
      for(int j = 0; j < numFacePoints; j++)
1162
        {
5199
        {
1163
        input->read((char *) &tempPoint, sizeof(int));
5200
        internalMesh->InsertNextCell(VTK_TETRA, 4,
1164
        this->FacePoints->value[i][j] = tempPoint;
5201
          additionalCells->GetPointer(i * nComponents));
1165
        }
5202
        }
1166
        tempStringStruct = this->GetLine(input);
5203
      else
1167
        temp = tempStringStruct->value;
1168
        delete tempStringStruct; //throw out ) and rest of line
1169
      }
1170
    }
1171
1172
  //ascii data
1173
  else
1174
    {
1175
    //create vtkstd::vector of points in each face
1176
    for(int i = 0; i < this->NumFaces; i++)
1177
      {
1178
      tempStringStruct = this->GetLine(input);
1179
      temp = tempStringStruct->value;
1180
      delete tempStringStruct;
1181
1182
      pos = temp.find("(");
1183
      vtksys_ios::stringstream ascTokenizer;
1184
      ascTokenizer << temp.substr(0, pos);
1185
      temp.erase(0, pos+1);
1186
      ascTokenizer >> numFacePoints;
1187
      this->FacePoints->value[i].resize(numFacePoints);
1188
      for(int j = 0; j < numFacePoints; j++)
1189
        {
5204
        {
1190
        pos = temp.find(" ");
5205
        internalMesh->InsertNextCell(VTK_PYRAMID, 5,
1191
        vtksys_ios::stringstream lineTokenizer;
5206
          additionalCells->GetPointer(i * nComponents));
1192
        lineTokenizer << temp.substr(0, pos);
1193
        temp.erase(0, pos+1);
1194
        lineTokenizer >> this->FacePoints->value[i][j];
1195
        }
5207
        }
1196
      }
5208
      }
1197
    }
5209
    internalMesh->Squeeze();
1198
5210
    additionalCells->Delete();
1199
  input->close();
1200
  delete input;
1201
  vtkDebugMacro(<<"Faces read");
1202
  return;
1203
}
1204
1205
// ****************************************************************************
1206
//  Method: vtkOpenFOAMReader::ReadOwnerFile
1207
//
1208
//  Purpose:
1209
//  read the owner file into a vtkstd::vector
1210
//
1211
// ****************************************************************************
1212
void vtkOpenFOAMReader::ReadOwnerFile(const char * ownerPathIn)
1213
{
1214
  vtkstd::string ownerPath(ownerPathIn);
1215
  vtkDebugMacro(<<"Read owner file: "<<ownerPath.c_str());
1216
  vtkstd::string temp;
1217
  stdString* tempStringStruct;
1218
  bool binaryWriteFormat;
1219
  ifstream * input = new ifstream(ownerPath.c_str(), ios::in VTK_IOS_NOCREATE);
1220
  //make sure file exists
1221
  if(input->fail())
1222
    {
1223
    input->close();
1224
    delete input;
1225
    return;
1226
    }
1227
1228
  //determine if file is binary or ascii
1229
  while(temp.find("format") == vtkstd::string::npos)
1230
    {
1231
    tempStringStruct = this->GetLine(input);
1232
    temp = tempStringStruct->value;
1233
    delete tempStringStruct;
1234
    }
1235
  input->close();
1236
1237
  //reopen file in correct format
1238
  if(temp.find("binary") != vtkstd::string::npos)
1239
    {
1240
#ifdef _WIN32
1241
    input->open(ownerPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
1242
#else
1243
    input->open(ownerPath.c_str(), ios::in VTK_IOS_NOCREATE);
1244
#endif
1245
    binaryWriteFormat = true;
1246
    }
5211
    }
1247
  else
5212
  else
1248
    {
5213
    {
1249
    input->open(ownerPath.c_str(),ios::in);
5214
    this->InsertCellsToGrid(internalMesh, cellFacesList, cellFacesIndices,
1250
    binaryWriteFormat = false;
5215
      facesPoints, pointArray, NULL, NULL);
1251
    }
5216
    }
1252
5217
1253
  vtkstd::string numFacesStr;
5218
  // set the internal mesh points
1254
  int faceValue;
5219
  vtkPoints *points = vtkPoints::New();
1255
5220
  points->SetData(pointArray);
1256
  this->FaceOwner = vtkIntArray::New();
5221
  internalMesh->SetPoints(points);
5222
  points->Delete();
5223
  this->SetDataObjectName(internalMesh, "Internal Mesh");
1257
5224
1258
  vtksys_ios::stringstream tokenizer;
5225
  vtkDebugMacro(<<"Internal mesh made");
1259
  tokenizer << this->NumFaces;
5226
  return internalMesh;
1260
  tokenizer >> numFacesStr;
5227
}
1261
  //find end of header & number of faces
1262
  //while(temp.compare(0,numFacesStr.size(),numFacesStr,
1263
  //0,numFacesStr.size())!=0)
1264
  while(strcmp(temp.substr(0,numFacesStr.size()).c_str(), numFacesStr.c_str()))
1265
    {
1266
    tempStringStruct = this->GetLine(input);
1267
    temp = tempStringStruct->value;
1268
    delete tempStringStruct;
1269
    }
1270
5228
1271
  this->FaceOwner->SetNumberOfValues(this->NumFaces);
5229
//-----------------------------------------------------------------------------
5230
// insert faces to grid
5231
void vtkOpenFOAMReader::InsertFacesToGrid(vtkUnstructuredGrid *boundaryMesh,
5232
  const intVectorVector *facesPoints, int startFace, int endFace,
5233
  vtkIntArray *boundaryPointMap, vtkIdList *facePointsVtkId,
5234
  vtkIntArray *labels, bool isLookupValue)
5235
{
5236
  vtkUnstructuredGrid &bm = *boundaryMesh;
1272
5237
1273
  //binary data
5238
  for(int j = startFace; j < endFace; j++)
1274
  if(binaryWriteFormat)
1275
    {
5239
    {
1276
    input->get(); //parenthesis
5240
    int faceId;
1277
    for(int i = 0; i < NumFaces; i++)
5241
    if(labels == NULL)
1278
      {
5242
      {
1279
      input->read((char *) &faceValue, sizeof(int));
5243
      faceId = j;
1280
      this->FaceOwner->SetValue(i, faceValue);
1281
      }
5244
      }
1282
    }
5245
    else
1283
1284
  //ascii data
1285
  else
1286
    {
1287
    tempStringStruct = this->GetLine(input);
1288
    temp = tempStringStruct->value;
1289
    delete tempStringStruct;
1290
1291
    //read face owners into int array
1292
    for(int i = 0; i < this->NumFaces; i++)
1293
      {
5246
      {
1294
      tempStringStruct = this->GetLine(input);
5247
      faceId = labels->GetValue(j);
1295
      temp = tempStringStruct->value;
5248
      if(faceId >= this->FaceOwner->GetNumberOfTuples())
1296
      delete tempStringStruct;
5249
        {
1297
5250
        vtkWarningMacro(<<"faceLabels id " << faceId
1298
      tokenizer.clear();
5251
          << " exceeds the number of faces "
1299
      tokenizer << temp;
5252
          << this->FaceOwner->GetNumberOfTuples());
1300
      tokenizer >> faceValue;
5253
        bm.InsertNextCell(VTK_EMPTY_CELL, 0, facePointsVtkId->GetPointer(0));
1301
      this->FaceOwner->SetValue(i, faceValue);
5254
        continue;
5255
        }
1302
      }
5256
      }
1303
    }
5257
    const int *facePoints = facesPoints->operator[](faceId);
5258
    size_t nFacePoints = facesPoints->size(faceId);
1304
5259
1305
  //find the number of cells
5260
    if(isLookupValue)
1306
  double  * range;
5261
      {
1307
  range = this->FaceOwner->GetRange();
5262
      for(size_t k = 0; k < nFacePoints; k++)
1308
  this->NumCells = (int)range[1]+1;
5263
        {
5264
        facePointsVtkId->SetId(k, boundaryPointMap->LookupValue(facePoints[k]));
5265
        }
5266
      }
5267
    else
5268
      {
5269
      if(boundaryPointMap)
5270
        {
5271
        for(size_t k = 0; k < nFacePoints; k++)
5272
          {
5273
          facePointsVtkId->SetId(k, boundaryPointMap->GetValue(facePoints[k]));
5274
          }
5275
        }
5276
      else
5277
        {
5278
        for(size_t k = 0; k < nFacePoints; k++)
5279
          {
5280
          facePointsVtkId->SetId(k, facePoints[k]);
5281
          }
5282
        }
5283
      }
1309
5284
1310
  //add the face number to the correct cell
5285
    // triangle
1311
  //according to owner
5286
    if(nFacePoints == 3)
1312
  this->FacesOwnerCell->value.resize(this->NumCells);
5287
      {
1313
  int tempCellId;
5288
      bm.InsertNextCell(VTK_TRIANGLE, 3, facePointsVtkId->GetPointer(0));
1314
  for(int j = 0; j < this->NumFaces; j++)
5289
      }
1315
    {
5290
    // quad
1316
    tempCellId = this->FaceOwner->GetValue(j);
5291
    else if(nFacePoints == 4)
1317
    if(tempCellId != -1)
5292
      {
5293
      bm.InsertNextCell(VTK_QUAD, 4, facePointsVtkId->GetPointer(0));
5294
      }
5295
    // polygon
5296
    else
1318
      {
5297
      {
1319
      this->FacesOwnerCell->value[tempCellId].push_back(j);
5298
      bm.InsertNextCell(VTK_POLYGON, nFacePoints,
5299
        facePointsVtkId->GetPointer(0));
1320
      }
5300
      }
1321
    }
5301
    }
1322
1323
  input->close();
1324
  delete input;
1325
  vtkDebugMacro(<<"Owner file read");
1326
  return;
1327
}
5302
}
1328
5303
1329
// ****************************************************************************
5304
//-----------------------------------------------------------------------------
1330
//  Method: vtkOpenFOAMReader::ReadNeighborFile
5305
// returns requested boundary meshes
1331
//
5306
unstructuredGridVector* vtkOpenFOAMReader::MakeBoundaryMesh(
1332
//  Purpose:
5307
  vtkFoamBoundaryDict* boundaryDictPtr, const intVectorVector *facesPoints,
1333
//  read the neighbor file into a vtkstd::vector
5308
  vtkFloatArray* pointArray)
1334
//
1335
// ****************************************************************************
1336
void vtkOpenFOAMReader::ReadNeighborFile(const char * neighborPathIn)
1337
{
5309
{
1338
  vtkstd::string neighborPath(neighborPathIn);
5310
  vtkFoamBoundaryDict& boundaryDict = *boundaryDictPtr;
1339
  vtkDebugMacro(<<"Read neighbor file: "<<neighborPath.c_str());
5311
  const int nBoundaries = boundaryDict.size();
1340
  vtkstd::string temp;
5312
  unstructuredGridVector *boundaryMesh = new unstructuredGridVector;
1341
  stdString* tempStringStruct;
1342
  bool binaryWriteFormat;
1343
  ifstream * input = new ifstream(neighborPath.c_str(), ios::in VTK_IOS_NOCREATE);
1344
  //make sure file exists
1345
  if(input->fail())
1346
    {
1347
    input->close();
1348
    delete input;
1349
    return;
1350
    }
1351
1352
  //determine if file is binary or ascii
1353
  while(temp.find("format") == vtkstd::string::npos)
1354
    {
1355
    tempStringStruct = this->GetLine(input);
1356
    temp = tempStringStruct->value;
1357
    delete tempStringStruct;
1358
    }
1359
  input->close();
1360
5313
1361
  //reopen file in correct format
5314
  if(this->CreateCellToPoint)
1362
  if(temp.find("binary") != vtkstd::string::npos)
1363
    {
1364
#ifdef _WIN32
1365
    input->open(neighborPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
1366
#else
1367
    input->open(neighborPath.c_str(), ios::in VTK_IOS_NOCREATE);
1368
#endif
1369
    binaryWriteFormat = true;
1370
    }
1371
  else
1372
    {
5315
    {
1373
    input->open(neighborPath.c_str(),ios::in);
5316
    this->AllBoundaries = vtkUnstructuredGrid::New();
1374
    binaryWriteFormat = false;
5317
    this->AllBoundaries->Allocate(facesPoints->nElements()
5318
      - boundaryDict[0].startFace);
1375
    }
5319
    }
5320
  this->BoundaryPointMap = new intArrayVector;
1376
5321
1377
  vtkstd::string numFacesStr;
5322
  vtkIntArray *nBoundaryPointsList = vtkIntArray::New();
1378
  int faceValue;
5323
  nBoundaryPointsList->SetNumberOfValues(nBoundaries);
1379
  vtkIntArray * faceNeighbor = vtkIntArray::New();
1380
5324
1381
  vtksys_ios::stringstream tokenizer;
5325
  // count the max number of points per face and the number of points
1382
  tokenizer << this->NumFaces;
5326
  // (with duplicates) in mesh
1383
  tokenizer >> numFacesStr;
5327
  int maxNFacePoints = 0;
1384
  //find end of header & number of faces
5328
  for(int boundaryI = 0; boundaryI < nBoundaries; boundaryI++)
1385
  //while(temp.compare(0,numFacesStr.size(),numFacesStr,0,
1386
  //numFacesStr.size())!=0)
1387
  while (strcmp(temp.substr(0,numFacesStr.size()).c_str(), numFacesStr.c_str()))
1388
    {
5329
    {
1389
    tempStringStruct = this->GetLine(input);
5330
    const int startFace = boundaryDict[boundaryI].startFace;
1390
    temp = tempStringStruct->value;
5331
    const int endFace = startFace + boundaryDict[boundaryI].nFaces;
1391
    delete tempStringStruct;
5332
    int nPoints = 0;
5333
    for(int j = startFace; j < endFace; j++)
5334
      {
5335
      const int nFacePoints = facesPoints->size(j);
5336
      nPoints += nFacePoints;
5337
      if(nFacePoints > maxNFacePoints)
5338
        {
5339
        maxNFacePoints = nFacePoints;
5340
        }
5341
      }
5342
    nBoundaryPointsList->SetValue(boundaryI, nPoints);
1392
    }
5343
    }
1393
5344
1394
  //read face owners into int array
5345
  // aloocate array for converting int vector to vtkIdType List:
1395
  faceNeighbor->SetNumberOfValues(this->NumFaces);
5346
  // workaround for 64bit machines
5347
  vtkIdList *facePointsVtkId = vtkIdList::New();
5348
  facePointsVtkId->SetNumberOfIds(maxNFacePoints);
1396
5349
1397
  //binary data
5350
  // create initial internal point list: set all points to -1
1398
  if(binaryWriteFormat)
5351
  if(this->CreateCellToPoint)
1399
    {
5352
    {
1400
    input->get(); //parenthesis
5353
    this->InternalPoints = vtkIntArray::New();
1401
    for(int i = 0; i < this->NumFaces; i++)
5354
    this->InternalPoints->SetNumberOfValues(this->NumPoints);
5355
    for(int pointI = 0; pointI < this->NumPoints; pointI++)
1402
      {
5356
      {
1403
      input->read((char *) &faceValue, sizeof(int));
5357
      this->InternalPoints->SetValue(pointI, -1);
1404
      faceNeighbor->SetValue(i, faceValue);
1405
      }
5358
      }
1406
    }
1407
5359
1408
  //ascii data
5360
    // mark boundary points as 0
1409
  else
5361
    for(int boundaryI = 0; boundaryI < nBoundaries; boundaryI++)
1410
    {
1411
    tempStringStruct = this->GetLine(input);
1412
    temp = tempStringStruct->value;
1413
    delete tempStringStruct;//throw away (
1414
    //read face owners into int array
1415
    for(int i = 0; i < this->NumFaces; i++)
1416
      {
5362
      {
1417
      tempStringStruct = this->GetLine(input);
5363
      if(boundaryDict[boundaryI].isPhysicalBoundary)
1418
      temp = tempStringStruct->value;
5364
        {
1419
      delete tempStringStruct;
5365
        const int startFace = boundaryDict[boundaryI].startFace;
5366
        const int endFace = startFace + boundaryDict[boundaryI].nFaces;
1420
5367
1421
      tokenizer.clear();
5368
        for(int j = startFace; j < endFace; j++)
1422
      tokenizer << temp;
5369
          {
1423
      tokenizer >> faceValue;
5370
          const int *facePoints = facesPoints->operator[](j);
1424
      faceNeighbor->SetValue(i, faceValue);
5371
          const int nFacePoints = facesPoints->size(j);
5372
          for(int k = 0; k < nFacePoints; k++)
5373
            {
5374
            this->InternalPoints->SetValue(facePoints[k], 0);
5375
            }
5376
          }
5377
        }
1425
      }
5378
      }
1426
    }
5379
    }
1427
  //No need to recalulate the Number of Cells
1428
  this->FacesNeighborCell->value.resize(this->NumCells);
1429
5380
1430
  //add face number to correct cell
5381
  // create global to AllBounaries point map
1431
  int tempCellId;
5382
  int nAllBoundaryPoints = 0;
1432
  for(int j = 0; j < this->NumFaces; j++)
5383
  if(this->CreateCellToPoint)
1433
    {
5384
    {
1434
    tempCellId = faceNeighbor->GetValue(j);
5385
    for(int pointI = 0; pointI < this->NumPoints; pointI++)
1435
    if(tempCellId != -1)
1436
      {
5386
      {
1437
      this->FacesNeighborCell->value[tempCellId].push_back(j);
5387
      if(this->InternalPoints->GetValue(pointI) == 0)
5388
        {
5389
        this->InternalPoints->SetValue(pointI, nAllBoundaryPoints);
5390
        nAllBoundaryPoints++;
5391
        }
1438
      }
5392
      }
1439
    }
5393
    }
1440
5394
1441
  faceNeighbor->Delete();
5395
  for(int boundaryI = 0; boundaryI < nBoundaries; boundaryI++)
1442
  input->close();
5396
  {
1443
  delete input;
5397
    const int nFaces = boundaryDict[boundaryI].nFaces;
1444
  vtkDebugMacro(<<"Neighbor file read");
5398
    const int startFace = boundaryDict[boundaryI].startFace;
1445
  return;
5399
    const int endFace = startFace + nFaces;
1446
}
1447
5400
1448
// ****************************************************************************
5401
    if(this->CreateCellToPoint && boundaryDict[boundaryI].isPhysicalBoundary)
1449
//  Method: vtkOpenFOAMReader::PopulatePolyMeshDirArrays
5402
      {
1450
//
5403
      // add faces to AllBoundaries
1451
//  Purpose:
5404
      this->InsertFacesToGrid(this->AllBoundaries, facesPoints, startFace,
1452
//  create a Lookup Table containing the location of the points
5405
        endFace, this->InternalPoints, facePointsVtkId, NULL, false);
1453
//  and faces files for each time steps mesh
5406
      }
1454
//
1455
// ****************************************************************************
1456
void vtkOpenFOAMReader::PopulatePolyMeshDirArrays()
1457
{
1458
  vtkDebugMacro(<<"Create list of points/faces file directories");
1459
  vtksys_ios::stringstream path;
1460
  vtksys_ios::stringstream timeStep;
1461
  bool facesFound;
1462
  bool pointsFound;
1463
  bool polyMeshFound;
1464
1465
  //intialize size to number of timesteps
1466
  this->PolyMeshPointsDir->value.resize(this->NumberOfTimeSteps);
1467
  this->PolyMeshFacesDir->value.resize(this->NumberOfTimeSteps);
1468
5407
1469
  //loop through each timestep
5408
    // skip below if inactive
1470
  for(int i = 0; i < this->NumberOfTimeSteps; i++)
5409
    if(!boundaryDict[boundaryI].isActive)
1471
    {
5410
      {
1472
    polyMeshFound = false;
5411
      continue;
1473
    facesFound = false;
5412
      }
1474
    pointsFound = false;
1475
5413
1476
    //create the path to the timestep
5414
    // create the mesh
1477
    path.clear();
5415
    boundaryMesh->push_back(vtkUnstructuredGrid::New());
1478
    timeStep.clear();
5416
    vtkUnstructuredGrid& bm = *boundaryMesh->back();
1479
    timeStep << Steps[i];
5417
    bm.Allocate(nFaces);
1480
    path << this->PathPrefix->value <<timeStep.str() << "/";
5418
    const int nBoundaryPoints = nBoundaryPointsList->GetValue(boundaryI);
1481
5419
1482
    //get the number of files
5420
    // create global to boundary-local point map and boundary points
1483
    vtkDirectory * directory = vtkDirectory::New();
5421
    vtkIntArray *boundaryPointList = vtkIntArray::New();
1484
    directory->Open(path.str().c_str());
5422
    boundaryPointList->SetNumberOfValues(nBoundaryPoints);
1485
    int numFiles = directory->GetNumberOfFiles();
5423
    int pointI = 0;
1486
    //Look for polyMesh Dir
5424
    for(int j = startFace; j < endFace; j++)
1487
    for(int j = 0; j < numFiles; j++)
1488
      {
5425
      {
1489
      vtkstd::string tempFile(directory->GetFile(j));
5426
      const int *facePoints = facesPoints->operator[](j);
1490
      if(tempFile.find("polyMesh") != vtkstd::string::npos)
5427
      int nFacePoints = facesPoints->size(j);
5428
      for(int k = 0; k < nFacePoints; k++)
1491
        {
5429
        {
1492
        polyMeshFound = true;
5430
        boundaryPointList->SetValue(pointI, facePoints[k]);
1493
5431
        pointI++;
1494
        path << "polyMesh/";
1495
1496
        //get number of files in the polyMesh dir
1497
        vtkDirectory * polyMeshDirectory = vtkDirectory::New();
1498
        polyMeshDirectory->Open(path.str().c_str());
1499
        int numPolyMeshFiles = polyMeshDirectory->GetNumberOfFiles();
1500
        //Look for points/faces files
1501
        for(int k = 0; k < numPolyMeshFiles; k++)
1502
          {
1503
          vtkstd::string tempFile2 = vtkstd::string(polyMeshDirectory->
1504
                                                    GetFile(k));
1505
          if(tempFile2.find("points") != vtkstd::string::npos)
1506
            {
1507
            this->PolyMeshPointsDir->value[i] = timeStep.str();
1508
            pointsFound = true;
1509
            }
1510
          else if(tempFile2.find("faces") != vtkstd::string::npos)
1511
            {
1512
            this->PolyMeshFacesDir->value[i] = timeStep.str();
1513
            facesFound = true;
1514
            }
1515
          }
1516
1517
        //if there is no points or faces found in this timestep
1518
        //set it equal to previous time step if no previous
1519
        //set it equal to "constant" dir
1520
        if(!pointsFound)
1521
          {
1522
          if(i != 0)
1523
            {
1524
            this->PolyMeshPointsDir->value[i] =
1525
              this->PolyMeshPointsDir->value[i-1];
1526
            }
1527
          else
1528
            {
1529
            this->PolyMeshPointsDir->value[i] = vtkstd::string("constant");
1530
            }
1531
          }
1532
        if(!facesFound)
1533
          {
1534
          if(i != 0)
1535
            {
1536
            this->PolyMeshFacesDir->value[i] =
1537
              this->PolyMeshFacesDir->value[i-1];
1538
            }
1539
          else
1540
            {
1541
            this->PolyMeshFacesDir->value[i] = vtkstd::string("constant");
1542
            }
1543
          }
1544
1545
        polyMeshDirectory->Delete();
1546
        break;  //found - stop looking
1547
        }
5432
        }
1548
      }
5433
      }
1549
5434
    vtkSortDataArray::Sort(boundaryPointList);
1550
    //if there is no polyMesh dir
5435
    this->BoundaryPointMap->push_back(vtkIntArray::New());
1551
    //set  it equal to prev timestep
5436
    vtkIntArray& bpMap = *this->BoundaryPointMap->back();
1552
    //if no prev set to "constant" dir
5437
    vtkFloatArray *boundaryPointArray = vtkFloatArray::New();
1553
    if(!polyMeshFound)
5438
    boundaryPointArray->SetNumberOfComponents(3);
5439
    int oldPointJ = -1;
5440
    for(int j = 0; j < nBoundaryPoints; j++)
1554
      {
5441
      {
1555
      if(i != 0)
5442
      const int pointJ = boundaryPointList->GetValue(j);
1556
        {
5443
      if(pointJ != oldPointJ)
1557
        //set points/faces location to previous timesteps value
1558
        this->PolyMeshPointsDir->value[i] = this->PolyMeshPointsDir->value[i-1];
1559
        this->PolyMeshFacesDir->value[i] = this->PolyMeshFacesDir->value[i-1];
1560
        }
1561
      else
1562
        {
5444
        {
1563
        //set points/faces to constant
5445
        oldPointJ = pointJ;
1564
        this->PolyMeshPointsDir->value[i] = vtkstd::string("constant");
5446
        boundaryPointArray->InsertNextTuple(pointArray->GetPointer(3 * pointJ));
1565
        this->PolyMeshFacesDir->value[i] = vtkstd::string("constant");
5447
        bpMap.InsertNextValue(pointJ);
1566
        }
5448
        }
1567
      }
5449
      }
1568
    directory->Delete();
5450
    boundaryPointArray->Squeeze();
1569
    }
5451
    bpMap.Squeeze();
5452
    boundaryPointList->Delete();
5453
    vtkPoints *boundaryPoints = vtkPoints::New();
5454
    boundaryPoints->SetData(boundaryPointArray);
5455
    boundaryPointArray->Delete();
1570
5456
1571
  vtkDebugMacro(<<"Points/faces list created");
5457
    // set points for boundary
1572
  return;
5458
    bm.SetPoints(boundaryPoints);
1573
}
5459
    boundaryPoints->Delete();
1574
5460
1575
// ****************************************************************************
5461
    // set the name of boundary
1576
//  Method: vtkOpenFOAMReader::GetDataType
5462
    this->SetDataObjectName(&bm, boundaryDict[boundaryI].boundaryName.c_str());
1577
//
1578
//  Purpose:
1579
//  determines whether a variable is a volume scalar, vector or neither
1580
//  for meta data
1581
//
1582
// ****************************************************************************
1583
const char * vtkOpenFOAMReader::GetDataType(const char * pathIn,
1584
                                      const char * fileNameIn)
1585
{
1586
  vtkstd::string path(pathIn);
1587
  vtkstd::string fileName(fileNameIn);
1588
  vtkstd::string filePath = path+"/"+fileName;
1589
  vtkDebugMacro(<<"Get data type of: "<<filePath.c_str());
1590
  stdString* tempStringStruct;
1591
  ifstream * input = new ifstream(filePath.c_str(), ios::in VTK_IOS_NOCREATE);
1592
  //make sure file exists
1593
  if(input->fail())
1594
    {
1595
    input->close();
1596
    delete input;
1597
    return "Null";
1598
    }
1599
1600
  vtkstd::string temp;
1601
  vtkstd::string foamClass;
1602
  vtksys_ios::stringstream tokenizer;
1603
  int opened;
1604
5463
1605
  //see if fileName is a file or directory
5464
    // insert faces to boundary mesh
1606
  vtkDirectory * directory = vtkDirectory::New();
5465
    this->InsertFacesToGrid(&bm, facesPoints, startFace, endFace, &bpMap,
1607
  opened = directory->Open(filePath.c_str());
5466
      facePointsVtkId, NULL, true);
1608
  directory->Delete();
5467
    bpMap.ClearLookup();
1609
  if(opened)
1610
    {
1611
    input->close();
1612
    delete input;
1613
    return "Directory";
1614
    }
5468
    }
1615
5469
1616
  //find class entry
5470
  nBoundaryPointsList->Delete();
1617
  tempStringStruct = this->GetLine(input);
5471
  facePointsVtkId->Delete();
1618
  temp = tempStringStruct->value;
1619
  delete tempStringStruct;
1620
  while(temp.find("class") == vtkstd::string::npos && !input->eof())
1621
    {
1622
    tempStringStruct = this->GetLine(input);
1623
    temp = tempStringStruct->value;
1624
    delete tempStringStruct;
1625
    }
1626
5472
1627
  //return type
5473
  if(this->CreateCellToPoint)
1628
  if(!input->eof())
1629
    {
5474
    {
1630
    temp.erase(temp.begin()+temp.find(";"));
5475
    this->AllBoundariesPointMap = vtkIntArray::New();
1631
    //PARSE OUT CLASS TYPE
5476
    vtkIntArray &abpMap = *this->AllBoundariesPointMap;
1632
    tokenizer << temp;
5477
    abpMap.SetNumberOfValues(nAllBoundaryPoints);
1633
    //while(tokenizer >> foamClass);
5478
1634
    while(!tokenizer.eof())
5479
    // create lists of internal points and AllBoundaries points
1635
      {
5480
    int nInternalPoints = 0;
1636
      tokenizer >> foamClass;
5481
    for(int pointI = 0, allBoundaryPointI = 0; pointI < this->NumPoints;
1637
      }
5482
      pointI++)
1638
    //return scalar, vector, or invalid
1639
    if(foamClass =="volScalarField")
1640
      {
5483
      {
1641
      input->close();
5484
      const int globalPointId = this->InternalPoints->GetValue(pointI);
1642
      delete input;
5485
      if(globalPointId == -1)
1643
      return "Scalar";
5486
        {
5487
        this->InternalPoints->SetValue(nInternalPoints, pointI);
5488
        nInternalPoints++;
5489
        }
5490
      else
5491
        {
5492
        abpMap.SetValue(allBoundaryPointI, pointI);
5493
        allBoundaryPointI++;
5494
        }
1644
      }
5495
      }
1645
    else if (foamClass =="volVectorField")
5496
    // shrink to the number of internal points
5497
    if(nInternalPoints > 0)
1646
      {
5498
      {
1647
      input->close();
5499
      this->InternalPoints->Resize(nInternalPoints);
1648
      delete input;
1649
      return "Vector";
1650
      }
5500
      }
1651
    else
5501
    else
1652
      {
5502
      {
1653
      input->close();
5503
      this->InternalPoints->Delete();
1654
      delete input;
5504
      this->InternalPoints = NULL;
1655
      return "Invalid";
1656
      }
5505
      }
5506
5507
    // set dummy vtkPoints to tell the grid the number of points
5508
    // (otherwise GetPointCells will crash)
5509
    vtkPoints *allBoundaryPoints = vtkPoints::New();
5510
    allBoundaryPoints->SetNumberOfPoints(abpMap.GetNumberOfTuples());
5511
    this->AllBoundaries->SetPoints(allBoundaryPoints);
5512
    allBoundaryPoints->Delete();
1657
    }
5513
    }
1658
5514
1659
  //if the file format is wrong return invalid
5515
  vtkDebugMacro(<<"Boundary mesh created");
1660
  else
5516
  return boundaryMesh;
5517
}
5518
5519
//-----------------------------------------------------------------------------
5520
// truncate face owner to have only boundary face info
5521
void vtkOpenFOAMReader::TruncateFaceOwner()
5522
{
5523
  const int boundaryStartFace = this->BoundaryDict->operator[](0).startFace;
5524
  // all the boundary faces
5525
  const int nBoundaryFaces
5526
    = this->FaceOwner->GetNumberOfTuples() - boundaryStartFace;
5527
  memmove(this->FaceOwner->GetPointer(0),
5528
    this->FaceOwner->GetPointer(boundaryStartFace),
5529
    sizeof(int) * nBoundaryFaces);
5530
  this->FaceOwner->Resize(nBoundaryFaces);
5531
}
5532
5533
//-----------------------------------------------------------------------------
5534
// move polyhedral cell centroids
5535
vtkPoints * vtkOpenFOAMReader::MoveInternalMesh(
5536
  vtkUnstructuredGrid *internalMesh, vtkFloatArray *pointArray)
5537
{
5538
  if(this->DecomposePolyhedra)
1661
    {
5539
    {
1662
    input->close();
5540
    const int nAdditionalCells = this->AdditionalCellPoints->size();
1663
    delete input;
5541
    pointArray->Resize(this->NumPoints + nAdditionalCells);
1664
    return "invalid";
5542
    for(int i = 0; i < nAdditionalCells; i++)
1665
    }
5543
      {
5544
      vtkIntArray *polyCellPoints = this->AdditionalCellPoints->operator[](i);
5545
      float centroid[3];
5546
      centroid[0] = centroid[1] = centroid[2] = 0.0F;
5547
      const int nCellPoints = polyCellPoints->GetDataSize();
5548
      for(int j = 0; j < nCellPoints; j++)
5549
        {
5550
        float *pointK = pointArray->GetPointer(3 * polyCellPoints->GetValue(j));
5551
        centroid[0] += pointK[0];
5552
        centroid[1] += pointK[1];
5553
        centroid[2] += pointK[2];
5554
        }
5555
      float weight
5556
        = (nCellPoints ? 1.0F / static_cast<float>(nCellPoints) : 0.0F);
5557
      centroid[0] *= weight;
5558
      centroid[1] *= weight;
5559
      centroid[2] *= weight;
5560
      pointArray->InsertTuple(this->NumPoints + i, centroid);
5561
      }
5562
    }
5563
  // instantiate the points class
5564
  vtkPoints* points = vtkPoints::New();
5565
  points->SetData(pointArray);
5566
  internalMesh->SetPoints(points);
5567
  return points;
1666
}
5568
}
1667
5569
1668
// ****************************************************************************
5570
//-----------------------------------------------------------------------------
1669
//  Method: vtkOpenFOAMReader::GetInternalVariableAtTimestep
5571
// move boundary points
1670
//
5572
void vtkOpenFOAMReader::MoveBoundaryMesh(unstructuredGridVector *boundaryMesh,
1671
//  Purpose:
5573
  vtkFloatArray *pointArray)
1672
//  returns the values for a request variable for the internal mesh
1673
//
1674
// ****************************************************************************
1675
vtkDoubleArray * vtkOpenFOAMReader::GetInternalVariableAtTimestep
1676
                 (const char * varNameIn, int timeState)
1677
{
5574
{
1678
  vtkstd::string varName(varNameIn);
5575
  const vtkFoamBoundaryDict& bDict = *this->BoundaryDict;
1679
  vtksys_ios::stringstream varPath;
1680
  varPath << this->PathPrefix->value << this->Steps[timeState] << "/" << varName;
1681
  vtkDebugMacro(<<"Get internal variable: "<<varPath.str().c_str());
1682
  vtkDoubleArray *data = vtkDoubleArray::New();
1683
5576
1684
  vtkstd::string temp;
5577
  for(size_t boundaryI = 0, activeBoundaryI = 0;
1685
  stdString* tempStringStruct;
5578
    boundaryI < bDict.size(); boundaryI++)
1686
  bool binaryWriteFormat;
1687
  ifstream * input = new ifstream(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE);
1688
  //make sure file exists
1689
  if(input->fail())
1690
    {
5579
    {
1691
    input->close();
5580
    if(bDict[boundaryI].isActive)
1692
    delete input;
5581
      {
1693
    return data;
5582
      vtkUnstructuredGrid& bm
5583
        = *boundaryMesh->operator[](activeBoundaryI);
5584
      vtkIntArray& bpMap = *this->BoundaryPointMap->operator[](activeBoundaryI);
5585
      const int nBoundaryPoints = bpMap.GetNumberOfTuples();
5586
      vtkFloatArray *boundaryPointArray = vtkFloatArray::New();
5587
      boundaryPointArray->SetNumberOfComponents(3);
5588
      boundaryPointArray->SetNumberOfTuples(nBoundaryPoints);
5589
      for(int pointI = 0; pointI < nBoundaryPoints; pointI++)
5590
        {
5591
        boundaryPointArray->SetTuple(pointI, bpMap.GetValue(pointI),
5592
          pointArray);
5593
        }
5594
      vtkPoints *boundaryPoints = vtkPoints::New();
5595
      boundaryPoints->SetData(boundaryPointArray);
5596
      boundaryPointArray->Delete();
5597
      bm.SetPoints(boundaryPoints);
5598
      boundaryPoints->Delete();
5599
      activeBoundaryI++;
5600
      }
1694
    }
5601
    }
5602
}
1695
5603
1696
  //determine if file is binary or ascii
5604
//-----------------------------------------------------------------------------
1697
  while(temp.find("format") == vtkstd::string::npos)
5605
// as of now the function does not do interpolation, but do just averaging.
5606
void vtkOpenFOAMReader:: InterpolateCellToPoint(vtkFloatArray *pData,
5607
  vtkFloatArray *iData, vtkUnstructuredGrid *mesh, vtkIntArray *pointList,
5608
  const int nPoints)
5609
{
5610
  if(nPoints == 0)
1698
    {
5611
    {
1699
    tempStringStruct = this->GetLine(input);
5612
    return;
1700
    temp = tempStringStruct->value;
1701
    delete tempStringStruct;
1702
    }
5613
    }
1703
  input->close();
1704
5614
1705
  //reopen file in correct format
5615
  // a dummy call to let GetPointCells() build the cell links
1706
  if(temp.find("binary") != vtkstd::string::npos)
5616
  vtkIdList *pointCells = vtkIdList::New();
1707
    {
5617
  mesh->GetPointCells(0, pointCells);
1708
#ifdef _WIN32
5618
  pointCells->Delete();
1709
    input->open(varPath.str().c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
5619
1710
#else
5620
  vtkCellLinks *cl = mesh->GetCellLinks();
1711
    input->open(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE);
5621
  const int nComponents = iData->GetNumberOfComponents();
1712
#endif
5622
1713
    binaryWriteFormat = true;
5623
  if(nComponents == 1)
5624
    {
5625
    // a special case with the innermost componentI loop unrolled
5626
    float *tuples = iData->GetPointer(0);
5627
    for(int pointI = 0; pointI < nPoints; pointI++)
5628
      {
5629
      const int pI = (pointList ? pointList->GetValue(pointI) : pointI);
5630
      const vtkCellLinks::Link &l = cl->GetLink(pI);
5631
      const int nCells = static_cast<int>(l.ncells);
5632
      const vtkIdType *cells = l.cells;
5633
      // use double intermediate variables for precision
5634
      double interpolatedValue = 0.0;
5635
      for(int cellI = 0; cellI < nCells; cellI++)
5636
        {
5637
        interpolatedValue += tuples[cells[cellI]];
5638
        }
5639
      interpolatedValue
5640
        = (nCells ? interpolatedValue / static_cast<double>(nCells) : 0.0);
5641
      pData->SetValue(pI, interpolatedValue);
5642
      }
5643
    }
5644
  else if(nComponents == 3)
5645
    {
5646
    // a special case with the innermost componentI loop unrolled
5647
    float *pDataPtr = pData->GetPointer(0);
5648
    for(int pointI = 0; pointI < nPoints; pointI++)
5649
      {
5650
      const int pI = (pointList ? pointList->GetValue(pointI) : pointI);
5651
      const vtkCellLinks::Link &l = cl->GetLink(pI);
5652
      const int nCells = static_cast<int>(l.ncells);
5653
      const vtkIdType *cells = l.cells;
5654
      // use double intermediate variables for precision
5655
      const double weight = (nCells ? 1.0 / static_cast<double>(nCells) : 0.0);
5656
      double summedValue0 = 0.0, summedValue1 = 0.0, summedValue2 = 0.0;
5657
5658
      // hand unrolling
5659
      for(int cellI = 0; cellI < nCells; cellI++)
5660
        {
5661
        const float *tuple = iData->GetPointer(3 * cells[cellI]);
5662
        summedValue0 += tuple[0];
5663
        summedValue1 += tuple[1];
5664
        summedValue2 += tuple[2];
5665
        }
5666
5667
      float *interpolatedValue = &pDataPtr[3 * pI];
5668
      interpolatedValue[0] = weight * summedValue0;
5669
      interpolatedValue[1] = weight * summedValue1;
5670
      interpolatedValue[2] = weight * summedValue2;
5671
      }
1714
    }
5672
    }
1715
  else
5673
  else
1716
    {
5674
    {
1717
    input->open(varPath.str().c_str(),ios::in);
5675
    float *pDataPtr = pData->GetPointer(0);
1718
    binaryWriteFormat = false;
5676
    for(int pointI = 0; pointI < nPoints; pointI++)
5677
      {
5678
      const int pI = (pointList ? pointList->GetValue(pointI) : pointI);
5679
      const vtkCellLinks::Link &l = cl->GetLink(pI);
5680
      const int nCells = static_cast<int>(l.ncells);
5681
      const vtkIdType *cells = l.cells;
5682
      // use double intermediate variables for precision
5683
      const double weight = (nCells ? 1.0 / static_cast<double>(nCells) : 0.0);
5684
      float *interpolatedValue = &pDataPtr[nComponents * pI];
5685
      // a bit strange loop order but this works fastest
5686
      for(int componentI = 0; componentI < nComponents; componentI++)
5687
        {
5688
        const float *tuple = iData->GetPointer(componentI);
5689
        double summedValue = 0.0;
5690
        for(int cellI = 0; cellI < nCells; cellI++)
5691
          {
5692
          summedValue += tuple[nComponents * cells[cellI]];
5693
          }
5694
        interpolatedValue[componentI] = weight * summedValue;
5695
        }
5696
      }
1719
    }
5697
    }
5698
}
1720
5699
1721
  vtkstd::string foamClass;
5700
//-----------------------------------------------------------------------------
1722
  vtksys_ios::stringstream tokenizer;
5701
bool vtkOpenFOAMReader::ReadFieldFile(vtkFoamIOobject *ioPtr,
1723
  double value;
5702
  vtkFoamDict *dictPtr, const char *varNameIn, int timeState,
1724
5703
  vtkDataArraySelection *selection)
1725
  //find class
5704
{
1726
  tempStringStruct = this->GetLine(input);
5705
  vtkStdString varPath = *this->PathPrefix
1727
  temp = tempStringStruct->value;
5706
    + this->TimeNames->GetValue(timeState) + "/" + vtkStdString(varNameIn);
1728
  delete tempStringStruct;
5707
  vtkDebugMacro(<<"Get variable: "<<varPath.c_str());
1729
5708
1730
  while(temp.find("class") == vtkstd::string::npos)
5709
  // open the file
5710
  vtkFoamIOobject &io = *ioPtr;
5711
  if(!io.open(varPath))
1731
    {
5712
    {
1732
    tempStringStruct = this->GetLine(input);
5713
    vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": "
1733
    temp = tempStringStruct->value;
5714
      << io.error().c_str());
1734
    delete tempStringStruct;
5715
    return false;
1735
    }
5716
    }
1736
  temp.erase(temp.begin()+temp.find(";"));
5717
1737
  tokenizer << temp;
5718
  // if the variable is disabled on selection panel then skip it
1738
  //while(tokenizer >> foamClass);
5719
  if(selection->ArrayExists(io.objectName().c_str())
1739
  while(!tokenizer.eof())
5720
    && !selection->ArrayIsEnabled(io.objectName().c_str()))
1740
    {
5721
    {
1741
    tokenizer >> foamClass;
5722
    return false;
1742
    }
5723
    }
1743
  temp="";
5724
1744
  //create scalar arrays
5725
  // read the field file into dictionary
1745
  if(foamClass =="volScalarField")
5726
  vtkFoamDict &dict = *dictPtr;
5727
  if(!dict.read(io))
1746
    {
5728
    {
1747
    while(temp.find("internalField") == vtkstd::string::npos)
5729
    vtkErrorMacro(<<"Error reading line " << io.lineNumber()
1748
      {
5730
      << " of " << io.fileName().c_str() << ": " << io.error().c_str());
1749
      tempStringStruct = this->GetLine(input);
5731
    return false;
1750
      temp = tempStringStruct->value;
5732
    }
1751
      delete tempStringStruct;
1752
      }
1753
    //nonuniform
1754
    if(!(temp.find("nonuniform") == vtkstd::string::npos))
1755
      {
1756
      //create an array
1757
      tempStringStruct = this->GetLine(input);
1758
      temp = tempStringStruct->value;
1759
      delete tempStringStruct;
1760
5733
1761
      int scalarCount;
5734
  if(dict.type() != vtkFoamToken::DICTIONARY)
1762
      tokenizer.clear();
5735
    {
1763
      tokenizer << temp;
5736
    vtkErrorMacro(<<"File " << io.fileName().c_str()
1764
      tokenizer >> scalarCount;
5737
      << "is not valid as a field file");
1765
      data->SetNumberOfValues(NumCells);
5738
    return false;
5739
    }
5740
  return true;
5741
}
1766
5742
1767
      //binary data
5743
//-----------------------------------------------------------------------------
1768
      if(binaryWriteFormat)
5744
vtkFloatArray *vtkOpenFOAMReader::FillField(vtkFoamEntry *entryPtr,
5745
  int nElements, vtkFoamIOobject *ioPtr, const vtkStdString *fieldType)
5746
{
5747
  vtkFloatArray *data;
5748
  vtkFoamEntry &entry = *entryPtr;
5749
  const vtkStdString &className = ioPtr->className();
5750
5751
  // "uniformValue" keyword is for uniformFixedValue B.C.
5752
  if(entry.firstValue().isUniform() || entry.keyword() == "uniformValue")
5753
    {
5754
    if(entry.firstValue().type() == vtkFoamToken::SCALAR
5755
      || entry.firstValue().type() == vtkFoamToken::LABEL)
5756
      {
5757
      const float num = entry.toFloat();
5758
      data = vtkFloatArray::New();
5759
      data->SetNumberOfValues(nElements);
5760
      for(int i = 0; i < nElements; i++)
1769
        {
5761
        {
1770
        //add values to array
5762
        data->SetValue(i, num);
1771
        input->get(); //parenthesis
5763
        }
1772
        for(int i = 0; i < scalarCount; i++)
5764
      }
5765
    else
5766
      {
5767
      float tupleBuffer[9], *tuple;
5768
      int nComponents;
5769
      // have to determine the type of vector
5770
      if(entry.firstValue().type() == vtkFoamToken::LABELLIST)
5771
        {
5772
        vtkIntArray &ll = entry.labelList();
5773
        nComponents = ll.GetNumberOfTuples();
5774
        for(int componentI = 0; componentI < nComponents; componentI++)
1773
          {
5775
          {
1774
          input->read((char *) &value, sizeof(double));
5776
          tupleBuffer[componentI] = static_cast<float>(ll.GetValue(componentI));
1775
          data->SetValue(i, value);
1776
          }
5777
          }
5778
        tuple = tupleBuffer;
5779
        }
5780
      else if(entry.firstValue().type() == vtkFoamToken::SCALARLIST)
5781
        {
5782
        vtkFloatArray& sl = entry.scalarList();
5783
        nComponents = sl.GetSize();
5784
        tuple =  sl.GetPointer(0);
1777
        }
5785
        }
1778
1779
      //ascii data
1780
      else
5786
      else
1781
        {
5787
        {
1782
        //add values to array
5788
        vtkErrorMacro(<<"Wrong list type for uniform field");
1783
        tempStringStruct = this->GetLine(input);
5789
        return NULL;
1784
        temp = tempStringStruct->value;
5790
        }
1785
        delete tempStringStruct; //discard (
1786
5791
1787
        for(int i = 0; i < scalarCount; i++)
5792
      if((*fieldType == "SphericalTensorField" && nComponents == 1)
5793
        || (*fieldType == "VectorField" && nComponents == 3)
5794
        || (*fieldType == "SymmTensorField" && nComponents == 6)
5795
        || (*fieldType == "TensorField" && nComponents == 9))
5796
        {
5797
        data = vtkFloatArray::New();
5798
        data->SetNumberOfComponents(nComponents);
5799
        data->SetNumberOfTuples(nElements);
5800
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
5801
#if vtksys_DATE_STAMP_FULL >= 20080620
5802
	// swap the components of symmTensor to match the component
5803
	// names in paraview
5804
	if(nComponents == 6)
5805
	  {
5806
	  const float symxy = tuple[1], symxz = tuple[2], symyy = tuple[3];
5807
	  const float symyz = tuple[4], symzz = tuple[5];
5808
	  tuple[1] = symyy;
5809
	  tuple[2] = symzz;
5810
	  tuple[3] = symxy;
5811
	  tuple[4] = symyz;
5812
	  tuple[5] = symxz;
5813
	  }
5814
#endif
5815
#endif
5816
        for(int i = 0; i < nElements; i++)
1788
          {
5817
          {
1789
          tempStringStruct = this->GetLine(input);
5818
          data->SetTuple(i, tuple);
1790
          temp = tempStringStruct->value;
1791
          delete tempStringStruct;
1792
          tokenizer.clear();
1793
          tokenizer << temp;
1794
          tokenizer >> value;
1795
          data->SetValue(i, value);
1796
          }
5819
          }
1797
        }
5820
        }
5821
      else
5822
        {
5823
        vtkErrorMacro(<< "Number of components and field class doesn't match "
5824
          << "for " << ioPtr->objectName() << ". class = " << className
5825
          << ", nComponents = " << nComponents);
5826
        return NULL;
5827
        }
1798
      }
5828
      }
1799
5829
    }
1800
    //uniform
5830
  else // nonuniform
1801
    else if(!(temp.find("uniform") == vtkstd::string::npos))
5831
    {
5832
    if((*fieldType == "ScalarField"
5833
      && entry.firstValue().type() == vtkFoamToken::SCALARLIST)
5834
      || ((*fieldType == "VectorField" || *fieldType == "SphericalTensorField"
5835
      || *fieldType == "SymmTensorField" || *fieldType == "TensorField")
5836
      && entry.firstValue().type() == vtkFoamToken::VECTORLIST))
5837
      {
5838
      const int nTuples = entry.scalarList().GetNumberOfTuples();
5839
      if(nTuples != nElements)
5840
        {
5841
        vtkErrorMacro(<<"Number of cells/points in mesh and field don't match: "
5842
          << "mesh = " << nElements << ", field = " << nTuples);
5843
        return NULL;
5844
        }
5845
      data = static_cast<vtkFloatArray *>(entry.ptr());
5846
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
5847
#if vtksys_DATE_STAMP_FULL >= 20080620
5848
      // swap the components of symmTensor to match the component
5849
      // names in paraview
5850
      const int nComponents = data->GetNumberOfComponents();
5851
      if(nComponents == 6)
5852
	{
5853
	for(int tupleI = 0; tupleI < nTuples; tupleI++)
5854
	  {
5855
	  float *tuple = data->GetPointer(nComponents * tupleI);
5856
	  const float symxy = tuple[1], symxz = tuple[2], symyy = tuple[3];
5857
	  const float symyz = tuple[4], symzz = tuple[5];
5858
	  tuple[1] = symyy;
5859
	  tuple[2] = symzz;
5860
	  tuple[3] = symxy;
5861
	  tuple[4] = symyz;
5862
	  tuple[5] = symxz;
5863
	  }
5864
	}
5865
#endif
5866
#endif
5867
      }
5868
    else if(entry.firstValue().type() == vtkFoamToken::EMPTYLIST &&
5869
      nElements <= 0)
1802
      {
5870
      {
1803
      //parse out the uniform value
5871
      data = vtkFloatArray::New();
1804
      vtkstd::string token;
5872
      // set the number of components as appropriate if the list is empty
1805
      temp.erase(temp.begin()+temp.find(";"));
5873
      if(*fieldType == "ScalarField" || *fieldType == "SphericalTensorField")
1806
      tokenizer.clear();
1807
      tokenizer << temp;
1808
      //while(tokenizer>>token);
1809
      while(!tokenizer.eof())
1810
        {
5874
        {
1811
        tokenizer >> token;
5875
        data->SetNumberOfComponents(1);
1812
        }
5876
        }
1813
      tokenizer.clear();
5877
      else if(*fieldType == "VectorField")
1814
      tokenizer << token;
5878
        {
1815
      tokenizer >> value;
5879
        data->SetNumberOfComponents(3);
1816
      data->SetNumberOfValues(NumCells);
5880
        }
1817
5881
      else if(*fieldType == "SymmTensorField")
1818
      //create array of uniform values
5882
        {
1819
      for(int i = 0; i < NumCells; i++)
5883
        data->SetNumberOfComponents(6);
5884
        }
5885
      else if(*fieldType == "TensorField")
1820
        {
5886
        {
1821
        data->SetValue(i, value);
5887
        data->SetNumberOfComponents(9);
1822
        }
5888
        }
1823
      }
5889
      }
1824
1825
    //no data
1826
    else
5890
    else
1827
      {
5891
      {
1828
      input->close();
5892
      vtkErrorMacro(<< ioPtr->objectName().c_str() << " is not a valid "
1829
      delete input;
5893
        << ioPtr->className().c_str());
1830
      return data;
5894
      return NULL;
1831
      }
5895
      }
1832
    }
5896
    }
5897
  return data;
5898
}
1833
5899
1834
  //create vector arrays
5900
//-----------------------------------------------------------------------------
1835
  else if(foamClass == "volVectorField")
5901
// convert OpenFOAM's dimension array representation to string
5902
void vtkOpenFOAMReader::ConstructDimensions(vtkStdString *dimString,
5903
  vtkFoamDict *dictPtr)
5904
{
5905
  if(!AddDimensionsToArrayNames)
1836
    {
5906
    {
1837
    tempStringStruct = this->GetLine(input);
5907
    return;
1838
    temp = tempStringStruct->value;
5908
    }
1839
    delete tempStringStruct;
5909
  vtkFoamEntry &dimEntry = dictPtr->lookup("dimensions");
1840
    while(temp.find("internalField") == vtkstd::string::npos)
5910
  if(dimEntry.found()
1841
      {
5911
    && dimEntry.firstValue().type() == vtkFoamToken::LABELLIST)
1842
      tempStringStruct = this->GetLine(input);
5912
    {
1843
      temp = tempStringStruct->value;
5913
    vtkIntArray &dims = dimEntry.labelList();
1844
      delete tempStringStruct;
5914
    if(dims.GetNumberOfTuples() == 7)
1845
      }
1846
    if(!(temp.find("nonuniform") == vtkstd::string::npos))
1847
      {
5915
      {
1848
      //create an array
5916
      int dimSet[7];
1849
      tempStringStruct = this->GetLine(input);
5917
      for(int dimI = 0; dimI < 7; dimI++)
1850
      temp = tempStringStruct->value;
5918
        {
1851
      delete tempStringStruct;
5919
        dimSet[dimI] = dims.GetValue(dimI);
1852
5920
        }
1853
      int vectorCount;
5921
      static const char *units[7] = { "kg", "m", "s", "K", "mol", "A", "cd" };
1854
      tokenizer.clear();
5922
      vtksys_ios::ostringstream posDim, negDim;
1855
      tokenizer << temp;
5923
      int posSpc = 0, negSpc = 0;
1856
      tokenizer >> vectorCount;
5924
      if(dimSet[0] == 1 && dimSet[1] == -1 && dimSet[2] == -2)
1857
      data->SetNumberOfComponents(3);
5925
        {
1858
5926
        posDim << "Pa";
1859
      //binary data
5927
        dimSet[0] = dimSet[1] = dimSet[2] = 0;
1860
      if(binaryWriteFormat)
5928
        posSpc = 1;
5929
        }
5930
      for(int dimI = 0; dimI < 7; dimI++)
5931
        {
5932
        const int dimDim = dimSet[dimI];
5933
        if(dimDim > 0)
5934
          {
5935
          if(posSpc)
5936
            {
5937
            posDim << " ";
5938
            }
5939
          posDim << units[dimI];
5940
          if(dimDim > 1)
5941
            {
5942
            posDim << dimDim;
5943
            }
5944
          posSpc++;
5945
          }
5946
        else if(dimDim < 0)
5947
          {
5948
          if(negSpc)
5949
            {
5950
            negDim << " ";
5951
            }
5952
          negDim << units[dimI];
5953
          if(dimDim < -1)
5954
            {
5955
            negDim << -dimDim;
5956
            }
5957
          negSpc++;
5958
          }
5959
        }
5960
      *dimString += " [" + posDim.str();
5961
      if(negSpc > 0)
1861
        {
5962
        {
1862
        //add values to the array
5963
        if(posSpc == 0)
1863
        input->get(); //parenthesis
5964
          {
1864
        for(int i = 0; i < vectorCount; i++)
5965
          *dimString += "1";
5966
          }
5967
        if(negSpc > 1)
1865
          {
5968
          {
1866
          input->read((char *) &value, sizeof(double));
5969
          *dimString += "/(" + negDim.str() + ")";
1867
          data->InsertComponent(i, 0, value);
1868
          input->read((char *) &value, sizeof(double));
1869
          data->InsertComponent(i, 1, value);
1870
          input->read((char *) &value, sizeof(double));
1871
          data->InsertComponent(i, 2, value);
1872
          }
5970
          }
1873
        }
5971
        else
1874
1875
      //ascii data
1876
      else
1877
        {
1878
        //add values to the array
1879
        tempStringStruct = this->GetLine(input);
1880
        temp = tempStringStruct->value;
1881
        delete tempStringStruct; //discard (
1882
        for(int i = 0; i < vectorCount; i++)
1883
          {
5972
          {
1884
          tempStringStruct = this->GetLine(input);
5973
          *dimString += "/" + negDim.str();
1885
          temp = tempStringStruct->value;
1886
          delete tempStringStruct;
1887
1888
          //REMOVE BRACKETS
1889
          temp.erase(temp.begin()+temp.find("("));
1890
          temp.erase(temp.begin()+temp.find(")"));
1891
1892
          //GRAB X,Y,&Z VALUES
1893
          tokenizer.clear();
1894
          tokenizer << temp;
1895
          tokenizer >> value;
1896
          data->InsertComponent(i, 0, value);
1897
          tokenizer >> value;
1898
          data->InsertComponent(i, 1, value);
1899
          tokenizer >> value;
1900
          data->InsertComponent(i, 2, value);
1901
          }
5974
          }
1902
        }
5975
        }
1903
      }
5976
      else if(posSpc == 0)
1904
    else if(!(temp.find("uniform") == vtkstd::string::npos))
1905
      {
1906
      //create an array of uniform values
1907
      double value1, value2, value3;
1908
1909
      //parse out the uniform values
1910
      temp.erase(temp.begin(), temp.begin()+temp.find("(")+1);
1911
      temp.erase(temp.begin()+temp.find(")"), temp.end());
1912
      tokenizer.clear();
1913
      tokenizer << temp;
1914
      tokenizer >> value1;
1915
      tokenizer >> value2;
1916
      tokenizer >> value3;
1917
      data->SetNumberOfComponents(3);
1918
      for(int i = 0; i < NumCells; i++)
1919
        {
5977
        {
1920
        data->InsertComponent(i, 0, value1);
5978
        *dimString += "-";
1921
        data->InsertComponent(i, 1, value2);
1922
        data->InsertComponent(i, 2, value3);
1923
        }
5979
        }
1924
      }
5980
      *dimString += "]";
1925
1926
    //no data
1927
    else
1928
      {
1929
      input->close();
1930
      delete input;
1931
      return data;
1932
      }
5981
      }
1933
    }
5982
    }
1934
  input->close();
1935
  delete input;
1936
  vtkDebugMacro(<<"Internal variable data read");
1937
  return data;
1938
}
5983
}
1939
5984
1940
// ****************************************************************************
5985
//-----------------------------------------------------------------------------
1941
//  Method: vtkOpenFOAMReader::GetBoundaryVariableAtTimestep
5986
void vtkOpenFOAMReader::GetVolFieldAtTimestep(
1942
//
5987
  vtkUnstructuredGrid* internalMesh, unstructuredGridVector* boundaryMesh,
1943
//  Purpose:
5988
  vtkFoamBoundaryDict* boundaryDictPtr, const char* varNameIn, int timeState)
1944
//  returns the values for a request variable for a bondary region
1945
//
1946
// ****************************************************************************
1947
vtkDoubleArray * vtkOpenFOAMReader::GetBoundaryVariableAtTimestep
1948
                (int boundaryIndex, const char * varNameIn, int timeState,
1949
                 vtkUnstructuredGrid * internalMesh)
1950
{
5989
{
1951
  vtkstd::string varName(varNameIn);
5990
  vtkFoamIOobject io(*this->PathPrefix);
1952
  vtksys_ios::stringstream varPath;
5991
  vtkFoamDict dict;
1953
  varPath << this->PathPrefix->value << this->Steps[timeState] << "/" << varName;
5992
  if(!this->ReadFieldFile(&io, &dict, varNameIn, timeState,
1954
  vtkDebugMacro(<<"Get boundary variable: "<<varPath.str().c_str());
5993
    this->CellDataArraySelection))
1955
  vtkDoubleArray *data = vtkDoubleArray::New();
1956
1957
  vtkstd::string temp;
1958
  stdString* tempStringStruct;
1959
  bool binaryWriteFormat;
1960
  ifstream * input = new ifstream(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE);
1961
  //make sure file exists
1962
  if(input->fail())
1963
    {
5994
    {
1964
    input->close();
5995
    return;
1965
    delete input;
1966
    return data;
1967
    }
5996
    }
1968
5997
1969
  //determine if file is binary or ascii
5998
  if(io.className().substr(0, 3) != "vol")
1970
  while(temp.find("format") == vtkstd::string::npos)
1971
    {
5999
    {
1972
    tempStringStruct = this->GetLine(input);
6000
    vtkErrorMacro(<< io.objectName().c_str() << " is not a volField");
1973
    temp = tempStringStruct->value;
6001
    return;
1974
    delete tempStringStruct;
1975
    }
6002
    }
1976
  input->close();
1977
6003
1978
  //reopen file in correct format
6004
  vtkFoamEntry &iEntry = dict.lookup("internalField");
1979
  if(temp.find("binary") != vtkstd::string::npos)
6005
  if(!iEntry.found())
1980
    {
6006
    {
1981
#ifdef _WIN32
6007
    vtkErrorMacro(<<"internalField not found in " << io.fileName().c_str());
1982
    input->open(varPath.str().c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
6008
    return;
1983
#else
1984
    input->open(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE);
1985
#endif
1986
    binaryWriteFormat = true;
1987
    }
6009
    }
1988
  else
6010
6011
  if(iEntry.firstValue().type() == vtkFoamToken::EMPTYLIST)
1989
    {
6012
    {
1990
    input->open(varPath.str().c_str(),ios::in);
6013
    // if there's no cell there shouldn't be any boundary faces either
1991
    binaryWriteFormat = false;
6014
    if(this->NumCells > 0)
6015
      {
6016
      vtkErrorMacro(<<"internalField of " << io.objectName().c_str()
6017
        << " is empty");
6018
      }
6019
    return;
1992
    }
6020
    }
1993
6021
1994
  vtkstd::string foamClass;
6022
  vtkStdString fieldType = io.className().substr(3, vtkStdString::npos);
1995
  vtksys_ios::stringstream tokenizer;
6023
  vtkFloatArray *iData = this->FillField(&iEntry, this->NumCells, &io,
1996
  double value;
6024
    &fieldType);
1997
6025
  if(iData == NULL)
1998
  //find class
1999
  tempStringStruct = this->GetLine(input);
2000
  temp = tempStringStruct->value;
2001
  delete tempStringStruct;
2002
  while(temp.find("class") == vtkstd::string::npos)
2003
    {
6026
    {
2004
    tempStringStruct = this->GetLine(input);
6027
    return;
2005
    temp = tempStringStruct->value;
2006
    delete tempStringStruct;
2007
    }
6028
    }
2008
  temp.erase(temp.begin()+temp.find(";"));
6029
2009
  tokenizer << temp;
6030
  vtkStdString dimString;
2010
  //while(tokenizer >> foamClass);
6031
  this->ConstructDimensions(&dimString, &dict);
2011
  while(!tokenizer.eof())
6032
6033
  vtkFloatArray *acData = NULL, *ctpData = NULL;
6034
6035
  if(this->CreateCellToPoint)
2012
    {
6036
    {
2013
    tokenizer >> foamClass;
6037
    acData = vtkFloatArray::New();
6038
    acData->SetNumberOfComponents(iData->GetNumberOfComponents());
6039
    acData->SetNumberOfTuples(this->FaceOwner->GetNumberOfTuples());
2014
    }
6040
    }
2015
  temp="";
2016
  //create scalar arrays
2017
  if(foamClass =="volScalarField")
2018
    {
2019
    //find desired mesh
2020
    while(temp.find(this->BoundaryNames->value[boundaryIndex]) == 
2021
            vtkstd::string::npos && !input->eof())
2022
      {
2023
      tempStringStruct = this->GetLine(input);
2024
      temp = tempStringStruct->value;
2025
      delete tempStringStruct;
2026
      }
2027
    if(input->eof())
2028
      {
2029
      input->close();
2030
      delete input;
2031
      return data;
2032
      }
2033
    //find value entry
2034
    while(temp.find("}") == vtkstd::string::npos &&
2035
          temp.find("value ") == vtkstd::string::npos)
2036
      {
2037
      tempStringStruct = this->GetLine(input);
2038
      temp = tempStringStruct->value;
2039
      delete tempStringStruct; //find value
2040
      }
2041
6041
2042
    //nonuniform
6042
  if(iData->GetSize() > 0)
2043
    if(!(temp.find("nonuniform") == vtkstd::string::npos))
6043
    {
6044
    // Add field only if internal Mesh exists (skip if not selected).
6045
    // Note we still need to read internalField even if internal mesh is
6046
    // not selected, since boundaries without value entries may refer to
6047
    // the internalField.
6048
    if(internalMesh != NULL)
2044
      {
6049
      {
2045
6050
      int nAdditionalCells = 0;
2046
      //binary data
6051
      if(this->DecomposePolyhedra)
2047
      if(binaryWriteFormat)
2048
        {
6052
        {
2049
        //create an array
6053
        // add values for decomposed cells
2050
        tempStringStruct = this->GetLine(input);
6054
        nAdditionalCells = this->AdditionalCellIds->GetNumberOfTuples();
2051
        temp = tempStringStruct->value;
6055
        iData->Resize(this->NumCells + nAdditionalCells);
2052
        delete tempStringStruct;
6056
        for(int i = 0; i < nAdditionalCells; i++)
2053
2054
        int scalarCount;
2055
        tokenizer.clear();
2056
        tokenizer << temp;
2057
        tokenizer >> scalarCount;
2058
        data->SetNumberOfValues(scalarCount);
2059
2060
        //assign values to the array
2061
        input->get(); //parenthesis
2062
        for(int i = 0; i < scalarCount; i++)
2063
          {
6057
          {
2064
          input->read((char *) &value, sizeof(double));
6058
          iData->InsertTuple(this->NumCells + i,
2065
          data->SetValue(i, value);
6059
          static_cast<vtkIdType>(this->AdditionalCellIds->GetValue(i)), iData);
2066
          }
6060
          }
2067
        }
6061
        }
2068
6062
2069
      //ascii data
6063
      // set data to internal mesh
2070
      else
6064
      this->AddArrayToFieldData(internalMesh->GetCellData(), iData,
6065
	io.objectName() + dimString);
6066
6067
      if(this->CreateCellToPoint)
2071
        {
6068
        {
2072
        temp.erase(temp.begin(), temp.begin()+temp.find(">")+1);
6069
        // Create cell-to-point interpolated data
2073
        //ascii data with 10 or less values are on the same line
6070
        ctpData = vtkFloatArray::New();
2074
        //>10
6071
        ctpData->SetNumberOfComponents(iData->GetNumberOfComponents());
2075
        if(temp == vtkstd::string(" "))
6072
        ctpData->SetNumberOfTuples(
6073
          internalMesh->GetPoints()->GetNumberOfPoints());
6074
        if(this->InternalPoints != NULL)
2076
          {
6075
          {
2077
          //create an array of data
6076
          this->InterpolateCellToPoint(ctpData, iData, internalMesh,
2078
          tempStringStruct = this->GetLine(input);
6077
            this->InternalPoints, this->InternalPoints->GetNumberOfTuples());
2079
          temp = tempStringStruct->value;
2080
          delete tempStringStruct;
2081
2082
          int scalarCount;
2083
          tokenizer.clear();
2084
          tokenizer << temp;
2085
          tokenizer >> scalarCount;
2086
          data->SetNumberOfValues(scalarCount);
2087
          tempStringStruct = this->GetLine(input);
2088
          temp = tempStringStruct->value;
2089
          delete tempStringStruct; //discard (
2090
2091
          for(int i = 0; i < scalarCount; i++)
2092
            {
2093
            tempStringStruct = this->GetLine(input);
2094
            temp = tempStringStruct->value;
2095
            delete tempStringStruct;
2096
2097
            tokenizer.clear();
2098
            tokenizer << temp;
2099
            tokenizer >> value;
2100
            data->SetValue(i, value);
2101
            }
2102
          }
6078
          }
2103
        //=<10
2104
        else
2105
          {
2106
          //create an array with data
2107
          int scalarCount;
2108
          tokenizer.clear();
2109
          tokenizer << temp;
2110
          tokenizer >> scalarCount;
2111
          data->SetNumberOfValues(scalarCount);
2112
          temp.erase(temp.begin(), temp.begin()+temp.find("(")+1);
2113
          temp.erase(temp.begin()+temp.find(")"), temp.end());
2114
6079
2115
          tokenizer.clear();
6080
        if(this->DecomposePolyhedra)
2116
          tokenizer << temp;
6081
          {
2117
          for(int i = 0; i < scalarCount; i++)
6082
          // assign cell values to additional points
6083
          for(int cellI = 0, oldCellId = -1, pointI = this->NumPoints;
6084
            cellI < nAdditionalCells; cellI++)
2118
            {
6085
            {
2119
            tokenizer >> value;
6086
            const int cellId = this->AdditionalCellIds->GetValue(cellI);
2120
            data->SetValue(i, value);
6087
            if(cellId != oldCellId)
6088
              {
6089
              ctpData->SetTuple(pointI, cellId, iData);
6090
              pointI++;
6091
              oldCellId = cellId;
6092
              }
2121
            }
6093
            }
2122
          }
6094
          }
2123
        }
6095
        }
2124
      }
6096
      }
2125
6097
    }
2126
    //uniform
6098
  else
2127
    else if(!(temp.find("uniform") == vtkstd::string::npos))
6099
    {
2128
      {
6100
    // determine as there's no cells
2129
      //create an array of uniform values
6101
    iData->Delete();
2130
      double value1 = 0;
6102
    if(acData != NULL)
2131
      temp.erase(temp.begin(), temp.begin()+temp.find("uniform")+7);
2132
      temp.erase(temp.begin()+temp.find(";"), temp.end());
2133
      tokenizer.clear();
2134
      tokenizer << temp;
2135
      tokenizer >> value1;
2136
      data->SetNumberOfValues(this->SizeOfBoundary->value[boundaryIndex]);
2137
      for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++)
2138
        {
2139
        data->SetValue(i, value1);
2140
        }
2141
      }
2142
2143
    //no data
2144
    else
2145
      {
6103
      {
2146
      int cellId;
6104
      acData->Delete();
2147
      vtkDataArray * internalData = internalMesh->GetCellData()->
2148
                                    GetArray(varName.c_str());
2149
      data->SetNumberOfValues(this->SizeOfBoundary->value[boundaryIndex]);
2150
      for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++)
2151
        {
2152
        cellId = this->FaceOwner->GetValue(this->StartFace + i);
2153
        data->SetValue(i, internalData->GetComponent(cellId, 0));
2154
        }
2155
      input->close();
2156
      delete input;
2157
      return data;
2158
      }
6105
      }
6106
    return;
2159
    }
6107
    }
2160
  //CREATE VECTOR ARRAYS
6108
2161
  else if(foamClass == "volVectorField")
6109
  vtkFoamBoundaryDict &boundaryDict = *boundaryDictPtr;
6110
6111
  // set boundary values
6112
  vtkFoamEntry& bEntry = dict.lookup("boundaryField");
6113
  if(!bEntry.found())
2162
    {
6114
    {
2163
    while(temp.find(this->BoundaryNames->value[boundaryIndex]) == 
6115
    vtkErrorMacro(<< "boundaryField not found in object " << varNameIn
2164
          vtkstd::string::npos && !input->eof())
6116
      << " at time = " << this->TimeNames->GetValue(timeState).c_str());
6117
    iData->Delete();
6118
    if(acData != NULL)
2165
      {
6119
      {
2166
      tempStringStruct = this->GetLine(input);
6120
      acData->Delete();
2167
      temp = tempStringStruct->value;
2168
      delete tempStringStruct;
2169
      }
6121
      }
2170
    if(input->eof())
6122
    if(ctpData != NULL)
2171
      {
6123
      {
2172
      input->close();
6124
      ctpData->Delete();
2173
      delete input;
2174
      return data;
2175
      }
6125
      }
2176
    while(temp.find("}") == vtkstd::string::npos &&
6126
    return;
2177
          temp.find("value ") == vtkstd::string::npos)
6127
    }
6128
6129
  vtkstd::vector<vtkFloatArray *> vDataVector;
6130
  for(size_t boundaryI = 0, activeBoundaryI = 0;
6131
    boundaryI < boundaryDict.size(); boundaryI++)
6132
    {
6133
    const vtkStdString &boundaryNameI = boundaryDict[boundaryI].boundaryName;
6134
6135
    vtkFoamEntry& bEntryI = bEntry.dictionary().lookup(boundaryNameI);
6136
    if(!bEntryI.found())
2178
      {
6137
      {
2179
      tempStringStruct = this->GetLine(input);
6138
      vtkErrorMacro(<< "boundaryField " << boundaryNameI.c_str()
2180
      temp = tempStringStruct->value;
6139
        << " not found in object " << varNameIn << " at time = "
2181
      delete tempStringStruct; //find value
6140
        << this->TimeNames->GetValue(timeState).c_str());
6141
      iData->Delete();
6142
      if(acData != NULL)
6143
        {
6144
        acData->Delete();
6145
        }
6146
      if(ctpData != NULL)
6147
        {
6148
        ctpData->Delete();
6149
        }
6150
      return;
2182
      }
6151
      }
2183
    //nonuniform
6152
2184
    if(!(temp.find("nonuniform") == vtkstd::string::npos))
6153
    if(bEntryI.firstValue().type() != vtkFoamToken::DICTIONARY)
2185
      {
6154
      {
2186
      //create an array
6155
      vtkErrorMacro(<< "Type of boundaryField " << boundaryNameI.c_str()
2187
      tempStringStruct = this->GetLine(input);
6156
        << " is not a subdictionary in object " << varNameIn << " at time = "
2188
      temp = tempStringStruct->value;
6157
        << this->TimeNames->GetValue(timeState).c_str());
2189
      delete tempStringStruct;
6158
      iData->Delete();
6159
      if(acData != NULL)
6160
        {
6161
        acData->Delete();
6162
        }
6163
      if(ctpData != NULL)
6164
        {
6165
        ctpData->Delete();
6166
        }
6167
      return;
6168
      }
2190
6169
2191
      int vectorCount;
6170
    const int nFaces = boundaryDict[boundaryI].nFaces;
2192
      tokenizer.clear();
2193
      tokenizer << temp;
2194
      tokenizer >> vectorCount;
2195
      data->SetNumberOfComponents(3);
2196
6171
2197
      //binary data
6172
    vtkFloatArray* vData = NULL;
2198
      if(binaryWriteFormat)
6173
    bool valueFound = false;
6174
    vtkFoamEntry& vEntry = bEntryI.dictionary().lookup("value");
6175
    if(vEntry.found()) // the boundary has a value entry
6176
      {
6177
      vData = this->FillField(&vEntry, nFaces, &io, &fieldType);
6178
      if(vData == NULL)
2199
        {
6179
        {
2200
        //insert values into the array
6180
        iData->Delete();
2201
        input->get(); //parenthesis
6181
        if(acData != NULL)
2202
        for(int i = 0; i < vectorCount; i++)
2203
          {
6182
          {
2204
          input->read((char *) &value, sizeof(double));
6183
          acData->Delete();
2205
          data->InsertComponent(i, 0, value);
2206
          input->read((char *) &value, sizeof(double));
2207
          data->InsertComponent(i, 1, value);
2208
          input->read((char *) &value, sizeof(double));
2209
          data->InsertComponent(i, 2, value);
2210
          }
6184
          }
6185
        if(ctpData != NULL)
6186
          {
6187
          ctpData->Delete();
6188
          }
6189
        return;
2211
        }
6190
        }
2212
6191
      valueFound = true;
2213
        //ascii data
6192
      }
2214
        else
6193
    else
6194
      {
6195
      // uniformFixedValue B.C.
6196
      vtkFoamEntry& ufvEntry = bEntryI.dictionary().lookup("type");
6197
      if(ufvEntry.found())
6198
        {
6199
        if(ufvEntry.toString() == "uniformFixedValue")
2215
          {
6200
          {
2216
          //insert values into the array
6201
          // the boundary is of uniformFixedValue type
2217
          tempStringStruct = this->GetLine(input);
6202
          vtkFoamEntry& uvEntry = bEntryI.dictionary().lookup("uniformValue");
2218
          temp = tempStringStruct->value;
6203
          if(uvEntry.found()) // and has a uniformValue entry
2219
          delete tempStringStruct; //discard (
2220
          for(int i = 0; i < vectorCount; i++)
2221
            {
6204
            {
2222
            tempStringStruct = this->GetLine(input);
6205
            vData = this->FillField(&uvEntry, nFaces, &io, &fieldType);
2223
            temp = tempStringStruct->value;
6206
            if(vData == NULL)
2224
            delete tempStringStruct;
6207
              {
2225
6208
              iData->Delete();
2226
            //REMOVE BRACKETS
6209
              if(acData != NULL)
2227
            temp.erase(temp.begin()+temp.find("("));
6210
                {
2228
            temp.erase(temp.begin()+temp.find(")"));
6211
                acData->Delete();
2229
6212
                }
2230
            //GRAB X,Y,&Z VALUES
6213
              if(ctpData != NULL)
2231
            tokenizer.clear();
6214
                {
2232
            tokenizer << temp;
6215
                ctpData->Delete();
2233
            tokenizer >> value;
6216
                }
2234
            data->InsertComponent(i, 0, value);
6217
              return;
2235
            tokenizer >> value;
6218
              }
2236
            data->InsertComponent(i, 1, value);
6219
            valueFound = true;
2237
            tokenizer >> value;
2238
            data->InsertComponent(i, 2, value);
2239
            }
6220
            }
2240
          }
6221
          }
2241
        }
6222
        }
6223
      }
2242
6224
2243
    //uniform
6225
    const int boundaryStartFace
2244
    else if(!(temp.find("uniform") == vtkstd::string::npos))
6226
      = boundaryDict[boundaryI].startFace - boundaryDict[0].startFace;
2245
      {
2246
      //create an array of uniform values
2247
      double value1 = 0, value2 = 0, value3 = 0;
2248
      temp.erase(temp.begin(), temp.begin()+temp.find("(")+1);
2249
      temp.erase(temp.begin()+temp.find(")"), temp.end());
2250
      tokenizer.clear();
2251
      tokenizer << temp;
2252
      tokenizer >> value1;
2253
      tokenizer >> value2;
2254
      tokenizer >> value3;
2255
6227
2256
      data->SetNumberOfComponents(3);
6228
    if(!valueFound) // doesn't have a value nor uniformValue entry
2257
      for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++)
6229
      {
6230
      // use patch-internal values as boundary values
6231
      vData = vtkFloatArray::New();
6232
      vData->SetNumberOfComponents(iData->GetNumberOfComponents());
6233
      vData->SetNumberOfTuples(nFaces);
6234
      for(int j = 0; j < nFaces; j++)
2258
        {
6235
        {
2259
        data->InsertComponent(i, 0, value1);
6236
        const int cellId = this->FaceOwner->GetValue(boundaryStartFace + j);
2260
        data->InsertComponent(i, 1, value2);
6237
        // in this case GetTuple should be thread-safe accoding to
2261
        data->InsertComponent(i, 2, value3);
6238
        // the FAQ on ParaView Wiki
6239
        vData->SetTuple(j, cellId, iData);
2262
        }
6240
        }
2263
      }
6241
      }
2264
6242
2265
    //no data
6243
    if(this->CreateCellToPoint && boundaryDict[boundaryI].isPhysicalBoundary)
2266
    else
2267
      {
6244
      {
2268
      int cellId;
6245
      // set the same value to AllBoundaries
2269
      vtkDataArray * internalData = internalMesh->GetCellData()->
6246
      for(int faceI = 0; faceI < nFaces; faceI++)
2270
                                    GetArray(varName.c_str());
2271
      data->SetNumberOfComponents(3);
2272
      for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++)
2273
        {
6247
        {
2274
        cellId = this->FaceOwner->GetValue(this->StartFace + i);
6248
        const int startFace = boundaryDict[boundaryI].allBoundariesStartFace;
2275
        data->InsertComponent(i, 0, internalData->GetComponent(cellId, 0));
6249
        acData->SetTuple(faceI + startFace, faceI, vData);
2276
        data->InsertComponent(i, 1, internalData->GetComponent(cellId, 1));
2277
        data->InsertComponent(i, 2, internalData->GetComponent(cellId, 2));
2278
        }
6250
        }
2279
      input->close();
2280
      delete input;
2281
      return data;
2282
      }
6251
      }
2283
    }
2284
  input->close();
2285
  delete input;
2286
  vtkDebugMacro(<<"Boundary data read");
2287
  return data;
2288
}
2289
6252
2290
// ****************************************************************************
6253
    if(boundaryDict[boundaryI].isActive)
2291
//  Method: vtkOpenFOAMReader::GatherBlocks
6254
      {
2292
//
6255
      this->AddArrayToFieldData(boundaryMesh->operator[](activeBoundaryI)
2293
//  Purpose:
6256
	->GetCellData(), vData, io.objectName() + dimString);
2294
//  returns a vector of block names for a specified domain
2295
//
2296
// ****************************************************************************
2297
stringVector * vtkOpenFOAMReader::GatherBlocks(const char * typeIn,
2298
                                              int timeState)
2299
{
2300
  vtkstd::string type(typeIn);
2301
  vtkstd::string blockPath = this->PathPrefix->value +
2302
                             this->PolyMeshFacesDir->value[timeState] +
2303
                             "/polyMesh/"+type;
2304
  vtkstd::vector< vtkstd::string > blocks;
2305
  stringVector *returnValue = new stringVector;
2306
  vtkDebugMacro(<<"Get blocks: "<<blockPath.c_str());
2307
2308
  ifstream * input = new ifstream(blockPath.c_str(), ios::in VTK_IOS_NOCREATE);
2309
  //if there is no file return a null vector
2310
  if(input->fail())
2311
    {
2312
    input->close();
2313
    delete input;
2314
    returnValue->value = blocks;
2315
    return returnValue;
2316
    }
2317
2318
  vtkstd::string temp;
2319
  stdString* tempStringStruct;
2320
  vtkstd::string token;
2321
  vtksys_ios::stringstream tokenizer;
2322
  vtkstd::string tempName;
2323
2324
  //find end of header
2325
  //while(temp.compare(0,4,"// *",0,4)!=0)
2326
  while (strcmp(temp.substr(0,4).c_str(), "// *"))
2327
    {
2328
    tempStringStruct = this->GetLine(input);
2329
    temp = tempStringStruct->value;
2330
    delete tempStringStruct;
2331
    }
2332
  tempStringStruct = this->GetLine(input);
2333
  temp = tempStringStruct->value;
2334
  delete tempStringStruct;
2335
2336
  tempStringStruct = this->GetLine(input);
2337
  temp = tempStringStruct->value;
2338
  delete tempStringStruct; //throw out blank line
2339
2340
  //Number of blocks
2341
  tokenizer << temp;
2342
  tokenizer >> this->NumBlocks;
2343
  blocks.resize(this->NumBlocks);
2344
2345
  //loop through each block
2346
  for(int i = 0; i < this->NumBlocks; i++)
2347
    {
2348
    tempStringStruct = this->GetLine(input);
2349
    temp = tempStringStruct->value;
2350
    delete tempStringStruct; //throw out blank line
2351
2352
    //NAME
2353
    tempStringStruct = this->GetLine(input);
2354
    temp = tempStringStruct->value;
2355
    delete tempStringStruct; //name
2356
2357
    tokenizer.clear();
2358
    tokenizer << temp;
2359
    tokenizer >> tempName;
2360
    blocks[i] = tempName;
2361
    //while(temp.compare(0,1,"}",0,1) != 0)
2362
    while (strcmp(temp.substr(0,1).c_str(), "}"))
2363
      {
2364
      tempStringStruct = this->GetLine(input);
2365
      temp = tempStringStruct->value;
2366
      delete tempStringStruct;
2367
      }
2368
    }
2369
  returnValue->value = blocks;
2370
  input->close();
2371
  delete input;
2372
  return returnValue;
2373
}
2374
6257
2375
// ****************************************************************************
6258
      if(this->CreateCellToPoint)
2376
//  Method: vtkOpenFOAMReader::GetBoundaryMesh
6259
	{
2377
//
6260
        // construct cell-to-point interpolated boundary values. This
2378
//  Purpose:
6261
        // is done independently from allBoundary interpolation so
2379
//  returns a requested boundary mesh
6262
        // that the interpolated values are not affected by
2380
//
6263
        // neighboring patches especially at patch edges and for
2381
// ****************************************************************************
6264
        // baffle patches
2382
vtkUnstructuredGrid * vtkOpenFOAMReader::GetBoundaryMesh(int timeState,
6265
        vtkFloatArray *pData = vtkFloatArray::New();
2383
                                                         int boundaryIndex)
6266
        pData->SetNumberOfComponents(vData->GetNumberOfComponents());
2384
{
6267
        const int nPoints = boundaryMesh->operator[](activeBoundaryI)->
2385
  vtkUnstructuredGrid * boundaryMesh = vtkUnstructuredGrid::New();
6268
          GetPoints()->GetNumberOfPoints();
2386
  vtkstd::string boundaryPath = this->PathPrefix->value +
6269
        pData->SetNumberOfTuples(nPoints);
2387
                                this->PolyMeshFacesDir->value[timeState] +
6270
        this->InterpolateCellToPoint(pData, vData,
2388
                                "/polyMesh/boundary";
6271
	  boundaryMesh->operator[](activeBoundaryI), NULL, nPoints);
2389
  vtkDebugMacro(<<"Create boundary mesh: "<<boundaryPath.c_str());
6272
#if 0
6273
	this->AddArrayToFieldData(boundaryMesh->operator[](activeBoundaryI)
6274
          ->GetPointData(), pData,
6275
	  "CellToPoint[" + io.objectName() + "]" + dimString);
6276
#else
6277
	this->AddArrayToFieldData(boundaryMesh->operator[](activeBoundaryI)
6278
          ->GetPointData(), pData, io.objectName() + dimString);
6279
#endif
6280
        pData->Delete();
6281
	}
2390
6282
2391
  int nFaces;
6283
      activeBoundaryI++;
6284
      }
6285
    vData->Delete();
6286
    }
6287
  iData->Delete();
2392
6288
2393
  ifstream * input = new ifstream(boundaryPath.c_str(), ios::in VTK_IOS_NOCREATE);
6289
  if(this->CreateCellToPoint)
2394
  //return a Null object
2395
  if(input->fail())
2396
    {
6290
    {
2397
    input->close();
6291
    // Create cell-to-point interpolated data for all boundaries and
2398
    delete input;
6292
    // override internal values
2399
    return boundaryMesh;
6293
    vtkFloatArray *bpData = vtkFloatArray::New();
2400
    }
6294
    bpData->SetNumberOfComponents(acData->GetNumberOfComponents());
6295
    const int nPoints = this->AllBoundariesPointMap->GetNumberOfTuples();
6296
    bpData->SetNumberOfTuples(nPoints);
6297
    this->InterpolateCellToPoint(bpData, acData, this->AllBoundaries, NULL,
6298
      nPoints);
6299
    acData->Delete();
6300
6301
    if(ctpData != NULL)
6302
      {
6303
      // set cell-to-pint data for internal mesh
6304
      for(int pointI = 0; pointI < nPoints; pointI++)
6305
        {
6306
        ctpData->SetTuple(this->AllBoundariesPointMap->GetValue(pointI), pointI,
6307
          bpData);
6308
        }
6309
#if 0
6310
      this->AddArrayToFieldData(internalMesh->GetPointData(), ctpData,
6311
	"CellToPoint[" + io.objectName() + "]" + dimString);
6312
#else
6313
      this->AddArrayToFieldData(internalMesh->GetPointData(), ctpData,
6314
	io.objectName() + dimString);
6315
#endif
6316
      ctpData->Delete();
6317
      }
2401
6318
2402
  vtkstd::string temp;
6319
    bpData->Delete();
2403
  stdString* tempStringStruct;
6320
    }
2404
  vtkstd::string token;
6321
}
2405
  vtksys_ios::stringstream tokenizer;
2406
6322
2407
  //find desired mesh entry
6323
//-----------------------------------------------------------------------------
2408
  while(temp.find(this->BoundaryNames->value[boundaryIndex]) == 
6324
// read point field at a timestep
2409
        vtkstd::string::npos)
6325
void vtkOpenFOAMReader::GetPointFieldAtTimestep(
6326
  vtkUnstructuredGrid* internalMesh, unstructuredGridVector* boundaryMesh,
6327
  vtkFoamBoundaryDict* boundaryDictPtr, const char* varNameIn, int timeState)
6328
{
6329
  vtkFoamIOobject io(*this->PathPrefix);
6330
  vtkFoamDict dict;
6331
  if(!this->ReadFieldFile(&io, &dict, varNameIn, timeState,
6332
    this->PointDataArraySelection))
2410
    {
6333
    {
2411
    tempStringStruct = this->GetLine(input);
6334
    return;
2412
    temp = tempStringStruct->value;
2413
    delete tempStringStruct;
2414
    }
6335
    }
2415
6336
2416
  //get nFaces
6337
  if(io.className().substr(0, 5) != "point")
2417
  while(temp.find("nFaces") == vtkstd::string::npos)
2418
    {
6338
    {
2419
    tempStringStruct = this->GetLine(input);
6339
    vtkErrorMacro(<< io.objectName().c_str() << " is not a pointField");
2420
    temp = tempStringStruct->value;
6340
    return;
2421
    delete tempStringStruct;
2422
    }
6341
    }
2423
  temp.erase(temp.begin()+temp.find(";")); //remove ;
6342
2424
  tokenizer << temp;
6343
  vtkFoamEntry &iEntry = dict.lookup("internalField");
2425
  //while(tokenizer >> token);
6344
  if(!iEntry.found())
2426
  while(!tokenizer.eof())
2427
    {
6345
    {
2428
    tokenizer >> token;
6346
    vtkErrorMacro(<<"internalField not found in " << io.fileName().c_str());
6347
    return;
2429
    }
6348
    }
2430
  tokenizer.clear();
2431
  tokenizer << token;
2432
  tokenizer >> nFaces;
2433
2434
  //get startface
2435
  tempStringStruct = this->GetLine(input);
2436
  temp = tempStringStruct->value;
2437
  delete tempStringStruct;
2438
6349
2439
  //look for "startFaces"
6350
  if(iEntry.firstValue().type() == vtkFoamToken::EMPTYLIST)
2440
  while(temp.find("startFace") == vtkstd::string::npos)
2441
    {
6351
    {
2442
    tempStringStruct = this->GetLine(input);
6352
    // if there's no cell there shouldn't be any boundary faces either
2443
    temp = tempStringStruct->value;
6353
    if(this->NumPoints > 0)
2444
    delete tempStringStruct;
6354
      {
6355
      vtkErrorMacro(<<"internalField of " << io.objectName().c_str()
6356
        << " is empty");
6357
      }
6358
    return;
2445
    }
6359
    }
2446
  temp.erase(temp.begin()+temp.find(";")); //remove ;
6360
2447
  tokenizer.clear();
6361
  vtkStdString fieldType = io.className().substr(5, vtkStdString::npos);
2448
  tokenizer << temp;
6362
  vtkFloatArray *iData = this->FillField(&iEntry, this->NumPoints, &io,
2449
  //while(tokenizer >> token);
6363
    &fieldType);
2450
  while(!tokenizer.eof())
6364
  if(iData == NULL)
2451
    {
6365
    {
2452
    tokenizer >> token;
6366
    return;
2453
    }
6367
    }
2454
  tokenizer.clear();
2455
  tokenizer << token;
2456
  tokenizer >> this->StartFace;
2457
6368
2458
  //Create the mesh
6369
  vtkStdString dimString;
2459
  int j, k;
6370
  this->ConstructDimensions(&dimString, &dict);
2460
  vtkTriangle * triangle;
2461
  vtkQuad * quad;
2462
  vtkPolygon * polygon;
2463
  int endFace = this->StartFace + nFaces;
2464
  //loop through each face
2465
  for(j = this->StartFace; j < endFace; j++)
2466
    {
2467
6371
2468
    //triangle
6372
  // AdditionalCellPoints is NULL if creation of InternalMesh had been skipped
2469
    if(this->FacePoints->value[j].size() == 3)
6373
  if(this->AdditionalCellPoints != NULL)
2470
      {
6374
    {
2471
      triangle = vtkTriangle::New();
6375
    // point-to-cell interpolation to additional cell centroidal points
2472
      for(k = 0; k < 3; k++)
6376
    // for decomposed cells
6377
    const int nAdditionalPoints = this->AdditionalCellPoints->size();
6378
    const int nComponents = iData->GetNumberOfComponents();
6379
    iData->Resize(this->NumPoints + nAdditionalPoints);
6380
    for(int i = 0; i < nAdditionalPoints; i++)
6381
      {
6382
      vtkIntArray *acp = this->AdditionalCellPoints->operator[](i);
6383
      int nPoints = acp->GetDataSize();
6384
      float interpolatedValue[9];
6385
      for(int k = 0; k < nComponents; k++)
6386
        {
6387
        interpolatedValue[k] = 0.0F;
6388
        }
6389
      for(int j = 0; j < nPoints; j++)
6390
        {
6391
        const float *tuple = iData->GetPointer(nComponents * acp->GetValue(j));
6392
        for(int k = 0; k < nComponents; k++)
6393
          {
6394
          interpolatedValue[k] += tuple[k];
6395
          }
6396
        }
6397
      const float weight = 1.0F / static_cast<float>(nPoints);
6398
      for(int k = 0; k < nComponents; k++)
2473
        {
6399
        {
2474
        triangle->GetPointIds()->SetId(k, this->FacePoints->value[j][k]);
6400
        interpolatedValue[k] *= weight;
2475
        }
6401
        }
2476
      boundaryMesh->InsertNextCell(triangle->GetCellType(),
6402
      iData->InsertTuple(this->NumPoints + i, interpolatedValue);
2477
      triangle->GetPointIds());
2478
      triangle->Delete();
2479
      }
6403
      }
6404
    }
2480
6405
2481
    //quad
6406
  if(iData->GetSize() > 0)
2482
    else if(this->FacePoints->value[j].size() == 4)
6407
    {
6408
    // Add field only if internal Mesh exists (skip if not selected).
6409
    // Note we still need to read internalField even if internal mesh is
6410
    // not selected, since boundaries without value entries may refer to
6411
    // the internalField.
6412
    if(internalMesh != NULL)
2483
      {
6413
      {
2484
      quad = vtkQuad::New();
6414
      // set data to internal mesh
2485
      for(k = 0; k < 4; k++)
6415
      this->AddArrayToFieldData(internalMesh->GetPointData(), iData,
2486
        {
6416
	io.objectName() + dimString);
2487
        quad->GetPointIds()->SetId(k, this->FacePoints->value[j][k]);
2488
        }
2489
      boundaryMesh->InsertNextCell(quad->GetCellType(),
2490
      quad->GetPointIds());
2491
      quad->Delete();
2492
      }
6417
      }
6418
    }
6419
  else
6420
    {
6421
    // determine as there's no points
6422
    iData->Delete();
6423
    return;
6424
    }
2493
6425
2494
    //polygon
6426
  // use patch-internal values as boundary values
2495
    else
6427
  vtkFoamBoundaryDict &boundaryDict = *boundaryDictPtr;
6428
  for(size_t boundaryI = 0, activeBoundaryI = 0;
6429
    boundaryI < boundaryDict.size(); boundaryI++)
6430
    {
6431
    if(boundaryDict[boundaryI].isActive)
2496
      {
6432
      {
2497
      polygon = vtkPolygon::New();
6433
      vtkFloatArray *vData = vtkFloatArray::New();
2498
      for(k = 0; k < (int)this->FacePoints->value[j].size(); k++)
6434
      vtkIntArray& bpMap = *this->BoundaryPointMap->operator[](activeBoundaryI);
6435
      const int nPoints = bpMap.GetNumberOfTuples();
6436
      vData->SetNumberOfComponents(iData->GetNumberOfComponents());
6437
      vData->SetNumberOfTuples(nPoints);
6438
      for(int j = 0; j < nPoints; j++)
2499
        {
6439
        {
2500
        polygon->GetPointIds()->InsertId(k, this->FacePoints->value[j][k]);
6440
        vData->SetTuple(j, bpMap.GetValue(j), iData);
2501
        }
6441
        }
2502
      boundaryMesh->InsertNextCell(polygon->GetCellType(),
6442
      this->AddArrayToFieldData(boundaryMesh->operator[](activeBoundaryI)
2503
      polygon->GetPointIds());
6443
        ->GetPointData(), vData, io.objectName() + dimString);
2504
      polygon->Delete();
6444
      vData->Delete();
6445
      activeBoundaryI++;
2505
      }
6446
      }
2506
    }
6447
    }
2507
6448
  iData->Delete();
2508
  //set points for boundary
2509
  boundaryMesh->SetPoints(this->Points);
2510
  //add size of mesh
2511
  this->SizeOfBoundary->value.push_back(boundaryMesh->GetNumberOfCells());
2512
  input->close();
2513
  delete input;
2514
  vtkDebugMacro(<<"Boundary mesh created");
2515
  return boundaryMesh;
2516
}
6449
}
2517
6450
2518
// ****************************************************************************
6451
//-----------------------------------------------------------------------------
2519
//  Method: vtkOpenFOAMReader::GetPointZoneMesh
6452
vtkPolyData* vtkOpenFOAMReader::MakeLagrangianMesh(int timeState,
2520
//
6453
  const vtkStdString &lagrangianPath)
2521
//  Purpose:
2522
//  returns a requested point zone mesh
2523
//
2524
// ****************************************************************************
2525
vtkUnstructuredGrid * vtkOpenFOAMReader::GetPointZoneMesh(int timeState,
2526
                                                          int pointZoneIndex)
2527
{
6454
{
2528
  vtkUnstructuredGrid * pointZoneMesh = vtkUnstructuredGrid::New();
6455
  vtkStdString positionsPath = *this->PathPrefix
2529
  vtkstd::string pointZonesPath = this->PathPrefix->value[timeState]+
6456
    + this->TimeNames->GetValue(timeState) + "/" + lagrangianPath
2530
                               "/polyMesh/pointZones";
6457
    + "/positions";
2531
  vtkDebugMacro(<<"Create point zone mesh: "<<pointZonesPath.c_str());
2532
6458
2533
  vtkstd::string temp;
6459
  vtkFoamIOobject io(*this->PathPrefix);
2534
  stdString* tempStringStruct;
6460
  if(!(io.open(positionsPath) || io.open(positionsPath + ".gz")))
2535
  bool binaryWriteFormat;
2536
  ifstream * input = new ifstream(pointZonesPath.c_str(), ios::in VTK_IOS_NOCREATE);
2537
  //make sure file exists
2538
  if(input->fail())
2539
    {
6461
    {
2540
    input->close();
6462
    // if positions doesn't exist we simply return without issuing an error
2541
    delete input;
6463
    return NULL;
2542
    return pointZoneMesh;
2543
    }
6464
    }
2544
6465
2545
  //determine if file is binary or ascii
6466
  // tell the IO object if the file is in OF 1.3 binary
2546
  while(temp.find("format") == vtkstd::string::npos)
6467
  // lagrangian/positions format
2547
    {
6468
  io.setIs13Positions(this->PositionsIsIn13Format != 0);
2548
    tempStringStruct = this->GetLine(input);
2549
    temp = tempStringStruct->value;
2550
    delete tempStringStruct;
2551
    }
2552
  input->close();
2553
6469
2554
  //reopen file in correct format
6470
  vtkFoamDict dict;
2555
  if(temp.find("binary") != vtkstd::string::npos)
6471
  if(!dict.read(io))
2556
    {
6472
    {
2557
#ifdef _WIN32
6473
    vtkErrorMacro(<<"Error reading line " << io.lineNumber()
2558
    input->open(pointZonesPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
6474
      << " of " << io.fileName().c_str() << ": " << io.error().c_str());
2559
#else
6475
    return NULL;
2560
    input->open(pointZonesPath.c_str(), ios::in VTK_IOS_NOCREATE);
2561
#endif
2562
    binaryWriteFormat = true;
2563
    }
6476
    }
2564
  else
6477
  if(dict.type() != vtkFoamToken::VECTORLIST)
2565
    {
6478
    {
2566
    input->open(pointZonesPath.c_str(),ios::in);
6479
    vtkErrorMacro(<<"The file type of " << io.fileName().c_str()
2567
    binaryWriteFormat = false;
6480
      << " is not a vectorList");
6481
    return NULL;
2568
    }
6482
    }
2569
6483
2570
  vtkstd::string token;
6484
  vtkFloatArray *pointArray = reinterpret_cast<vtkFloatArray *>(dict.ptr());
2571
  vtksys_ios::stringstream tokenizer;
6485
  const int nParticles = pointArray->GetNumberOfTuples();
2572
  vtkVertex * pointCell;
2573
  int tempElement;
2574
  vtkstd::vector< vtkstd::vector < int > > tempElementZones;
2575
  int numElement;
2576
2577
  //find desired mesh entry
2578
  while(temp.find(this->PointZoneNames->value[pointZoneIndex]) == 
2579
        vtkstd::string::npos)
2580
    {
2581
    tempStringStruct = this->GetLine(input);
2582
    temp = tempStringStruct->value;
2583
    delete tempStringStruct;
2584
    }
2585
  tempStringStruct = this->GetLine(input);
2586
  temp = tempStringStruct->value;
2587
  delete tempStringStruct;//throw out {
2588
2589
  tempStringStruct = this->GetLine(input);
2590
  temp = tempStringStruct->value;
2591
  delete tempStringStruct;//type
2592
2593
  tempStringStruct = this->GetLine(input);
2594
  temp = tempStringStruct->value;
2595
  delete tempStringStruct;//label
2596
2597
  tempStringStruct = this->GetLine(input);
2598
  temp = tempStringStruct->value;
2599
  delete tempStringStruct;//number of elements or {
2600
2601
  //number of elements
2602
  if(temp.find("}") == vtkstd::string::npos)
2603
    {
2604
    tokenizer << temp;
2605
    tokenizer >> numElement;
2606
    if(numElement == 0)
2607
      {
2608
      input->close();
2609
      delete input;
2610
      return NULL;
2611
      }
2612
6486
2613
    //binary data
6487
  // instantiate the points class
2614
    if(binaryWriteFormat)
6488
  vtkPoints *points = vtkPoints::New();
2615
      {
6489
  points->SetData(pointArray);
2616
      input->get(); //parenthesis
6490
  pointArray->Delete();
2617
      for(int j = 0; j < numElement; j++)
6491
2618
        {
6492
  // create lagrangian mesh
2619
        input->read((char *) &tempElement, sizeof(int));
6493
  vtkPolyData* lagrangianMesh = vtkPolyData::New();
2620
        pointCell = vtkVertex::New();
6494
  lagrangianMesh->Allocate(nParticles);
2621
        pointCell->GetPointIds()->SetId(0,tempElement);
6495
  for(vtkIdType i = 0; i < nParticles; i++)
2622
        pointZoneMesh->InsertNextCell(pointCell->GetCellType(),
6496
    {
2623
                                      pointCell->GetPointIds());
6497
    lagrangianMesh->InsertNextCell(VTK_VERTEX, 1, &i);
2624
        pointCell->Delete();
6498
    }
2625
        }
6499
  lagrangianMesh->SetPoints(points);
2626
      }
6500
  points->Delete();
6501
  this->SetDataObjectName(lagrangianMesh, lagrangianPath.c_str());
2627
6502
2628
    //ascii data
6503
  return lagrangianMesh;
2629
    else
6504
}
2630
      {
2631
      tempStringStruct = this->GetLine(input);
2632
      temp = tempStringStruct->value;
2633
      delete tempStringStruct;//THROW OUT (
2634
6505
2635
      //GET EACH ELEMENT & ADD TO VECTOR
6506
//-----------------------------------------------------------------------------
2636
      for(int j = 0; j < numElement; j++)
6507
void vtkOpenFOAMReader::GetLagrangianFieldAtTimestep(
2637
        {
6508
  vtkPolyData* lagrangianMesh, const char* varNameIn, int timeState,
2638
        tempStringStruct = this->GetLine(input);
6509
  const vtkStdString &lagrangianPath)
2639
        temp = tempStringStruct->value;
6510
{
2640
        delete tempStringStruct;
6511
  vtkStdString varPath = *this->PathPrefix
6512
    + this->TimeNames->GetValue(timeState) + "/" + lagrangianPath + "/"
6513
    + vtkStdString(varNameIn);
6514
6515
  // open the file
6516
  vtkFoamIOobject io(*this->PathPrefix);
6517
  if(!io.open(varPath))
6518
    {
6519
    // if the field file doesn't exist we simply return without issuing an error
6520
    // as a simple way of supporting multi-region lagrangians
6521
#if 0
6522
    vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": "
6523
      << io.error().c_str());
6524
#endif
6525
    return;
6526
    }
2641
6527
2642
        tokenizer.clear();
6528
  // if the variable is disabled on selection panel then skip it
2643
        tokenizer << temp;
6529
  vtkStdString selectionName = io.objectName();
2644
        tokenizer >> tempElement;
6530
  if(this->LagrangianDataArraySelection->ArrayExists(selectionName.c_str())
2645
        pointCell = vtkVertex::New();
6531
    && !this->LagrangianDataArraySelection
2646
        pointCell->GetPointIds()->SetId(0,tempElement);
6532
     ->ArrayIsEnabled(selectionName.c_str()))
2647
        pointZoneMesh->InsertNextCell(pointCell->GetCellType(),
6533
    {
2648
                                      pointCell->GetPointIds());
6534
    return;
2649
        pointCell->Delete();
2650
        }
2651
      }
2652
    }
6535
    }
2653
6536
2654
  //there is no entry
6537
  // read the field file into dictionary
2655
  else
6538
  vtkFoamDict dict;
6539
  if(!dict.read(io))
2656
    {
6540
    {
2657
    input->close();
6541
    vtkErrorMacro(<<"Error reading line " << io.lineNumber()
2658
    delete input;
6542
      << " of " << io.fileName().c_str() << ": " << io.error().c_str());
2659
    return NULL;
6543
    return;
2660
    }
6544
    }
2661
  //set point zone points
6545
2662
  pointZoneMesh->SetPoints(Points);
6546
  // set lagrangian values
2663
  input->close();
6547
  if(dict.type() != vtkFoamToken::SCALARLIST
2664
  delete input;
6548
    && dict.type() != vtkFoamToken::VECTORLIST)
2665
  vtkDebugMacro(<<"Point zone mesh created");
6549
    {
2666
  return pointZoneMesh;
6550
      vtkErrorMacro(<< io.fileName().c_str()
6551
        << ": Unsupported lagrangian field type " << io.className().c_str());
6552
    return;
6553
    }
6554
6555
  vtkFloatArray* lData = reinterpret_cast<vtkFloatArray *>(dict.ptr());
6556
6557
  // GetNumberOfTuples() works for both scalar and vector
6558
  const int nParticles = lData->GetNumberOfTuples();
6559
  if(nParticles != lagrangianMesh->GetNumberOfCells())
6560
    {
6561
    vtkErrorMacro(<< io.fileName().c_str()
6562
      <<": Sizes of lagrangian mesh and field don't match: mesh = "
6563
      << lagrangianMesh->GetNumberOfCells() << ", field = " << nParticles);
6564
    lData->Delete();
6565
    return;
6566
    }
6567
6568
  this->AddArrayToFieldData(lagrangianMesh->GetCellData(), lData,
6569
    selectionName);
6570
  if(this->CreateCellToPoint)
6571
    {
6572
#if 0
6573
    // have to use SetArray() since a vtkFloatArray can't be ShallowCopy()-ed
6574
    vtkFloatArray *lpData = vtkFloatArray::New();
6575
    lpData->SetNumberOfComponents(lData->GetNumberOfComponents());
6576
    lpData->SetArray(lData->GetPointer(0), lData->GetMaxId() + 1, 1);
6577
    this->AddArrayToFieldData(lagrangianMesh->GetPointData(), lpData,
6578
      "CellToPoint[" + selectionName + "]");
6579
    lpData->Delete();
6580
#else
6581
    this->AddArrayToFieldData(lagrangianMesh->GetPointData(), lData,
6582
      selectionName);
6583
#endif
6584
    }
6585
  lData->Delete();
6586
6587
  return;
2667
}
6588
}
2668
6589
2669
// ****************************************************************************
6590
//-----------------------------------------------------------------------------
2670
//  Method: vtkOpenFOAMReader::GetFaceZoneMesh
6591
// returns a dictionary of block names for a specified domain
2671
//
6592
vtkOpenFOAMReader::vtkFoamDict* vtkOpenFOAMReader::GatherBlocks(
2672
//  Purpose:
6593
  const char* typeIn, int timeState, bool mustRead)
2673
//  returns a requested face zone mesh
2674
//
2675
// ****************************************************************************
2676
vtkUnstructuredGrid * vtkOpenFOAMReader::GetFaceZoneMesh(int timeState,
2677
                                                         int faceZoneIndex)
2678
{
6594
{
2679
  vtkUnstructuredGrid * faceZoneMesh = vtkUnstructuredGrid::New();
6595
  vtkStdString type(typeIn);
2680
  vtkstd::string faceZonesPath = this->PathPrefix->value +
6596
  vtkStdString blockPath = *this->PathPrefix
2681
                                 this->PolyMeshFacesDir->value[timeState] +
6597
    + this->PolyMeshFacesDir->GetValue(timeState) + "/" + type;
2682
                                 "/polyMesh/faceZones";
2683
  vtkDebugMacro(<<"Create face zone mesh: "<<faceZonesPath.c_str());
2684
6598
2685
  vtkstd::string temp;
6599
  vtkFoamIOobject io(*this->PathPrefix);
2686
  stdString* tempStringStruct;
6600
  if(!(io.open(blockPath) || io.open(blockPath + ".gz")))
2687
  bool binaryWriteFormat;
2688
  ifstream * input = new ifstream(faceZonesPath.c_str(), ios::in VTK_IOS_NOCREATE);
2689
  //make sure file exists
2690
  if(input->fail())
2691
    {
6601
    {
2692
    input->close();
6602
    if(mustRead)
2693
    delete input;
6603
      {
2694
    return faceZoneMesh;
6604
      vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": "
6605
        << io.error().c_str());
6606
      }
6607
    return NULL;
2695
    }
6608
    }
2696
6609
2697
  //determine if file is binary or ascii
6610
  vtkFoamDict* dictPtr = new vtkFoamDict;
2698
  while(temp.find("format") == vtkstd::string::npos)
6611
  vtkFoamDict& dict = *dictPtr;
2699
    {
6612
  if(!dict.read(io))
2700
    tempStringStruct = this->GetLine(input);
6613
    {
2701
    temp = tempStringStruct->value;
6614
    vtkErrorMacro(<<"Error reading line " << io.lineNumber()
2702
    delete tempStringStruct;
6615
      << " of " << io.fileName().c_str() << ": " << io.error().c_str());
6616
    delete dictPtr;
6617
    return NULL;
2703
    }
6618
    }
2704
  input->close();
6619
  if(dict.type() != vtkFoamToken::DICTIONARY)
2705
2706
  //reopen file in correct format
2707
  if(temp.find("binary") != vtkstd::string::npos)
2708
    {
6620
    {
2709
#ifdef _WIN32
6621
    vtkErrorMacro(<<"The file type of " << io.fileName().c_str()
2710
    input->open(faceZonesPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
6622
      << " is not a dictionary");
2711
#else
6623
    delete dictPtr;
2712
    input->open(faceZonesPath.c_str(), ios::in);
6624
    return NULL;
2713
#endif
2714
    binaryWriteFormat = true;
2715
    }
6625
    }
2716
  else
6626
  return dictPtr;
6627
}
6628
6629
//-----------------------------------------------------------------------------
6630
// returns a requested point zone mesh
6631
bool vtkOpenFOAMReader::GetPointZoneMesh(unstructuredGridVector* pointZoneMesh,
6632
  vtkPoints* points, int timeState)
6633
{
6634
  vtkDebugMacro(<<"Create point zone mesh");
6635
6636
  vtkFoamDict* pointZoneDictPtr
6637
    = this->GatherBlocks("polyMesh/pointZones", timeState, false);
6638
6639
  if(pointZoneDictPtr == NULL)
2717
    {
6640
    {
2718
    input->open(faceZonesPath.c_str(),ios::in);
6641
    // not an error
2719
    binaryWriteFormat = false;
6642
    return true;
2720
    }
6643
    }
2721
6644
2722
  vtkstd::string token;
6645
  vtkFoamDict& pointZoneDict = *pointZoneDictPtr;
2723
  vtksys_ios::stringstream tokenizer;
6646
  size_t nPointZones = pointZoneDict.size();
2724
  vtkstd::vector< int > faceZone;
2725
  int tempElement;
2726
  vtkstd::vector< vtkstd::vector < int > > tempElementZones;
2727
  int numElement;
2728
6647
2729
  //find desired mesh entry
6648
  for(size_t i = 0; i < nPointZones; i++)
2730
  while(temp.find(this->FaceZoneNames->value[faceZoneIndex]) == 
2731
        vtkstd::string::npos)
2732
    {
6649
    {
2733
    tempStringStruct = this->GetLine(input);
6650
    // look up point labels
2734
    temp = tempStringStruct->value;
6651
    vtkFoamDict& dict = pointZoneDict.entry(i).dictionary();
2735
    delete tempStringStruct;
6652
    vtkFoamEntry& pointLabelsEntry = dict.lookup("pointLabels");
6653
    if(!pointLabelsEntry.found())
6654
      {
6655
      delete pointZoneDictPtr;
6656
      vtkErrorMacro(<<"pointLabels not found in pointZones");
6657
      return false;
6658
      }
6659
6660
    // allocate an empty mesh if the list is empty
6661
    if(pointLabelsEntry.firstValue().type() == vtkFoamToken::EMPTYLIST)
6662
      {
6663
      vtkUnstructuredGrid *pzm = vtkUnstructuredGrid::New();
6664
      pointZoneMesh->push_back(pzm);
6665
      // set name
6666
      this->SetDataObjectName(pzm, pointZoneDict.entry(i).keyword());
6667
      continue;
6668
      }
6669
6670
    if(pointLabelsEntry.firstValue().type() != vtkFoamToken::LABELLIST)
6671
      {
6672
      delete pointZoneDictPtr;
6673
      vtkErrorMacro(<<"pointLabels not of type labelList: type = "
6674
        << pointLabelsEntry.firstValue().type());
6675
      return false;
6676
      }
6677
6678
    vtkIntArray &labels = pointLabelsEntry.labelList();
6679
6680
    int nPoints = labels.GetNumberOfTuples();
6681
    if(nPoints > this->NumPoints)
6682
      {
6683
      vtkErrorMacro(<<"The length of pointLabels " << nPoints
6684
        << " for pointZone " << pointZoneDict.entry(i).keyword().c_str()
6685
        << " exceeds the number of points " << this->NumPoints);
6686
      delete pointZoneDictPtr;
6687
      return false;
6688
      }
6689
6690
    // allocate new grid: we do not use resize() beforehand since it
6691
    // could lead to undefined pointer if we return by error
6692
    vtkUnstructuredGrid *pzm = vtkUnstructuredGrid::New();
6693
    pointZoneMesh->push_back(pzm);
6694
6695
    // set pointZone size
6696
    pzm->Allocate(nPoints);
6697
6698
    // insert points
6699
    for(int j = 0; j < nPoints; j++)
6700
      {
6701
      vtkIdType pointLabel = labels.GetValue(j); // must be vtkIdType
6702
      if(pointLabel >= this->NumPoints)
6703
        {
6704
        vtkWarningMacro(<<"pointLabels id " << pointLabel
6705
          << " exceeds the number of points " << this->NumPoints);
6706
        pzm->InsertNextCell(VTK_EMPTY_CELL, 0, &pointLabel);
6707
        continue;
6708
        }
6709
      pzm->InsertNextCell(VTK_VERTEX, 1, &pointLabel);
6710
      }
6711
    pzm->SetPoints(points);
6712
6713
    // set name
6714
    this->SetDataObjectName(pzm, pointZoneDict.entry(i).keyword());
2736
    }
6715
    }
2737
6716
2738
  tempStringStruct = this->GetLine(input);
6717
  delete pointZoneDictPtr;
2739
  temp = tempStringStruct->value;
6718
2740
  delete tempStringStruct;//throw out {
6719
  vtkDebugMacro(<<"Point zone mesh created");
6720
  return true;
6721
}
6722
6723
//-----------------------------------------------------------------------------
6724
// returns a requested face zone mesh
6725
bool vtkOpenFOAMReader::GetFaceZoneMesh(
6726
  unstructuredGridVector *faceZoneMesh, const intVectorVector *facesPoints,
6727
  vtkPoints* points, int timeState)
6728
{
6729
  vtkDebugMacro(<<"Create face zone mesh");
2741
6730
2742
  tempStringStruct = this->GetLine(input);
6731
  vtkFoamDict* faceZoneDictPtr
2743
  temp = tempStringStruct->value;
6732
    = this->GatherBlocks("polyMesh/faceZones", timeState, false);
2744
  delete tempStringStruct;//type
2745
6733
2746
  tempStringStruct = this->GetLine(input);
6734
  if(faceZoneDictPtr == NULL)
2747
  temp = tempStringStruct->value;
6735
    {
2748
  delete tempStringStruct;//label
6736
    // not an error
6737
    return true;
6738
    }
2749
6739
2750
  tempStringStruct = this->GetLine(input);
6740
  vtkFoamDict& faceZoneDict = *faceZoneDictPtr;
2751
  temp = tempStringStruct->value;
6741
  size_t nFaceZones = faceZoneDict.size();
2752
  delete tempStringStruct;//number of values or flipmap
2753
6742
2754
  if(temp.find("flipMap") == vtkstd::string::npos)
6743
  for(size_t i = 0; i < nFaceZones; i++)
2755
    {
6744
    {
2756
    //number of elements
6745
    // look up face labels
2757
    tokenizer << temp;
6746
    vtkFoamDict& dict = faceZoneDict.entry(i).dictionary();
2758
    tokenizer >> numElement;
6747
    vtkFoamEntry& faceLabelsEntry = dict.lookup("faceLabels");
2759
    if(numElement == 0)
6748
    if(!faceLabelsEntry.found())
2760
      {
6749
      {
2761
      input->close();
6750
      delete faceZoneDictPtr;
2762
      delete input;
6751
      vtkErrorMacro(<<"faceLabels not found in faceZones");
2763
      return NULL;
6752
      return false;
2764
      }
6753
      }
2765
6754
2766
    //binary
6755
    // allocate an empty mesh if the list is empty
2767
    if(binaryWriteFormat)
6756
    if(faceLabelsEntry.firstValue().type() == vtkFoamToken::EMPTYLIST)
2768
      {
6757
      {
2769
      input->get(); //parenthesis
6758
      vtkUnstructuredGrid *fzm = vtkUnstructuredGrid::New();
2770
      for(int j = 0; j < numElement; j++)
6759
      faceZoneMesh->push_back(fzm);
2771
        {
6760
      // set name
2772
        input->read((char *) &tempElement, sizeof(int));
6761
      this->SetDataObjectName(fzm, faceZoneDict.entry(i).keyword());
2773
        faceZone.push_back(tempElement);
6762
      continue;
2774
        }
2775
      }
6763
      }
2776
6764
2777
    //ascii
6765
    if(faceLabelsEntry.firstValue().type() != vtkFoamToken::LABELLIST)
2778
    else
2779
      {
6766
      {
2780
      //THROW OUT (
6767
      delete faceZoneDictPtr;
2781
      tempStringStruct = this->GetLine(input);
6768
      vtkErrorMacro(<<"faceLabels not of type labelList");
2782
      temp = tempStringStruct->value;
6769
      return false;
2783
      delete tempStringStruct;
6770
      }
2784
6771
2785
      //get each element & add to vector
6772
    vtkIntArray &labels = faceLabelsEntry.labelList();
2786
      for(int j = 0; j < numElement; j++)
2787
        {
2788
        tempStringStruct = this->GetLine(input);
2789
        temp = tempStringStruct->value;
2790
        delete tempStringStruct;
2791
6773
2792
        tokenizer.clear();
6774
    int nFaces = labels.GetNumberOfTuples();
2793
        tokenizer << temp;
6775
    if(nFaces > this->FaceOwner->GetNumberOfTuples())
2794
        tokenizer >> tempElement;
6776
      {
2795
        faceZone.push_back(tempElement);
6777
      vtkErrorMacro(<<"The length of faceLabels " << nFaces
2796
        }
6778
        << " for faceZone " << faceZoneDict.entry(i).keyword().c_str()
6779
        << " exceeds the number of faces "
6780
        << this->FaceOwner->GetNumberOfTuples());
6781
      delete faceZoneDictPtr;
6782
      return false;
2797
      }
6783
      }
2798
    }
2799
6784
2800
  //Create the mesh
6785
    // allocate new grid: we do not use resize() beforehand since it
2801
  int k;
6786
    // could lead to undefined pointer if we return by error
2802
  vtkTriangle * triangle;
6787
    faceZoneMesh->push_back(vtkUnstructuredGrid::New());
2803
  vtkQuad * quad;
6788
    vtkUnstructuredGrid *fzm = faceZoneMesh->back();
2804
  vtkPolygon * polygon;
2805
6789
2806
  //LOOP THROUGH EACH FACE
6790
    // set faceZone size
2807
  for(int j = 0; j < (int)faceZone.size(); j++)
6791
    fzm->Allocate(nFaces);
2808
    {
2809
6792
2810
    //Triangular Face
6793
    // aloocate array for converting int vector to vtkIdType vector:
2811
    if(this->FacePoints->value[faceZone[j]].size() == 3)
6794
    // workaround for 64bit machines
6795
    int maxNFacePoints = 0;
6796
    for(int j = 0; j < nFaces; j++)
2812
      {
6797
      {
2813
      triangle = vtkTriangle::New();
6798
      const int nFacePoints = facesPoints->size(labels.GetValue(j));
2814
      for(k = 0; k < 3; k++)
6799
      if(nFacePoints > maxNFacePoints)
2815
        {
6800
        {
2816
        triangle->GetPointIds()->SetId(k, this->FacePoints->value[
6801
        maxNFacePoints = nFacePoints;
2817
        faceZone[j]][k]);
2818
        }
6802
        }
2819
      faceZoneMesh->InsertNextCell(triangle->GetCellType(),
2820
        triangle->GetPointIds());
2821
      triangle->Delete();
2822
      }
6803
      }
6804
    vtkIdList* facePointsVtkId = vtkIdList::New();
6805
    facePointsVtkId->SetNumberOfIds(maxNFacePoints);
2823
6806
2824
    //Quadraic Face
6807
    // insert faces
2825
    else if(this->FacePoints->value[faceZone[j]].size() == 4)
6808
    this->InsertFacesToGrid(fzm, facesPoints, 0, nFaces, NULL, facePointsVtkId,
2826
      {
6809
      &labels, false);
2827
      quad = vtkQuad::New();
2828
      for(k = 0; k < 4; k++)
2829
        {
2830
        quad->GetPointIds()->SetId(k,
2831
          this->FacePoints->value[faceZone[j]][k]);
2832
        }
2833
      faceZoneMesh->InsertNextCell(quad->GetCellType(),
2834
        quad->GetPointIds());
2835
      quad->Delete();
2836
      }
2837
6810
2838
    //Polygonal Face
6811
    facePointsVtkId->Delete();
2839
    else
6812
    fzm->SetPoints(points);
2840
      {
6813
2841
      polygon = vtkPolygon::New();
6814
    // set name
2842
      for(k = 0; k < (int)this->FacePoints->value[faceZone[j]].size(); k++)
6815
    this->SetDataObjectName(fzm, faceZoneDict.entry(i).keyword());
2843
        {
2844
        polygon->GetPointIds()->InsertId(k, this->FacePoints->value[
2845
          faceZone[j]][k]);
2846
        }
2847
      faceZoneMesh->InsertNextCell(polygon->GetCellType(),
2848
        polygon->GetPointIds());
2849
      polygon->Delete();
2850
      }
2851
    }
6816
    }
2852
6817
2853
  //set the face zone points
6818
  delete faceZoneDictPtr;
2854
  faceZoneMesh->SetPoints(this->Points);
6819
2855
  input->close();
2856
  delete input;
2857
  vtkDebugMacro(<<"Face zone mesh created");
6820
  vtkDebugMacro(<<"Face zone mesh created");
2858
  return faceZoneMesh;
6821
  return true;
2859
}
6822
}
2860
6823
2861
// ****************************************************************************
6824
//-----------------------------------------------------------------------------
2862
//  Method: vtkOpenFOAMReader::GetCellZoneMesh
6825
// returns a requested cell zone mesh
2863
//
6826
bool vtkOpenFOAMReader::GetCellZoneMesh(unstructuredGridVector* cellZoneMesh,
2864
//  Purpose:
6827
  vtkIntArray *cellFacesList, vtkIntArray *cellFacesIndices,
2865
//  returns a requested cell zone mesh
6828
  const intVectorVector *facesPoints, vtkPoints *points, int timeState)
2866
//
2867
// ****************************************************************************
2868
vtkUnstructuredGrid * vtkOpenFOAMReader::GetCellZoneMesh(int timeState,
2869
                                                         int cellZoneIndex)
2870
{
6829
{
2871
  vtkUnstructuredGrid * cellZoneMesh = vtkUnstructuredGrid::New();
6830
  vtkDebugMacro(<<"Create cell zone mesh");
2872
  vtkstd::string cellZonesPath = this->PathPrefix->value +
6831
2873
                                 this->PolyMeshFacesDir->value[timeState] +
6832
  vtkFoamDict* cellZoneDictPtr
2874
                                 "/polyMesh/cellZones";
6833
    = this->GatherBlocks("polyMesh/cellZones", timeState, false);
2875
  vtkDebugMacro(<<"Create cell zone mesh: "<<cellZonesPath.c_str());
6834
2876
  vtkstd::string temp;
6835
  if(cellZoneDictPtr == NULL)
2877
  stdString* tempStringStruct;
2878
  bool binaryWriteFormat;
2879
  ifstream * input = new ifstream(cellZonesPath.c_str(), ios::in VTK_IOS_NOCREATE);
2880
  //make sure file exists
2881
  if(input->fail())
2882
    {
6836
    {
2883
    input->close();
6837
    // not an error
2884
    delete input;
6838
    return true;
2885
    return cellZoneMesh;
2886
    }
6839
    }
2887
6840
2888
  //determine if file is binary or ascii
6841
  vtkFoamDict& cellZoneDict = *cellZoneDictPtr;
2889
  while(temp.find("format") == vtkstd::string::npos)
6842
  size_t nCellZones = cellZoneDict.size();
6843
6844
  for(size_t i = 0; i < nCellZones; i++)
2890
    {
6845
    {
2891
    tempStringStruct = this->GetLine(input);
6846
    // look up cell labels
2892
    temp = tempStringStruct->value;
6847
    vtkFoamDict& dict = cellZoneDict.entry(i).dictionary();
2893
    delete tempStringStruct;
6848
    vtkFoamEntry& cellLabelsEntry = dict.lookup("cellLabels");
6849
    if(!cellLabelsEntry.found())
6850
      {
6851
      delete cellZoneDictPtr;
6852
      vtkErrorMacro(<<"cellLabels not found in cellZones");
6853
      return false;
6854
      }
6855
6856
    // allocate an empty mesh if the list is empty
6857
    if(cellLabelsEntry.firstValue().type() == vtkFoamToken::EMPTYLIST)
6858
      {
6859
      vtkUnstructuredGrid *czm = vtkUnstructuredGrid::New();
6860
      cellZoneMesh->push_back(czm);
6861
      // set name
6862
      this->SetDataObjectName(czm, cellZoneDict.entry(i).keyword());
6863
      continue;
6864
      }
6865
6866
    if(cellLabelsEntry.firstValue().type() != vtkFoamToken::LABELLIST)
6867
      {
6868
      delete cellZoneDictPtr;
6869
      vtkErrorMacro(<<"cellLabels not of type labelList");
6870
      return false;
6871
      }
6872
6873
    vtkIntArray &labels = cellLabelsEntry.labelList();
6874
6875
    int nCells = labels.GetNumberOfTuples();
6876
    if(nCells > this->NumCells)
6877
      {
6878
      vtkErrorMacro(<<"The length of cellLabels " << nCells
6879
        << " for cellZone " << cellZoneDict.entry(i).keyword().c_str()
6880
        << " exceeds the number of cells " << this->NumCells);
6881
      delete cellZoneDictPtr;
6882
      return false;
6883
      }
6884
6885
    // allocate new grid: we do not use resize() beforehand since it
6886
    // could lead to undefined pointers if we return by error
6887
    cellZoneMesh->push_back(vtkUnstructuredGrid::New());
6888
    vtkUnstructuredGrid* czm = cellZoneMesh->back();
6889
6890
    // set cellZone size
6891
    czm->Allocate(nCells);
6892
6893
    // insert cells
6894
    this->InsertCellsToGrid(czm, cellFacesList, cellFacesIndices, facesPoints,
6895
      NULL, NULL, &labels);
6896
6897
    // set cell zone points
6898
    czm->SetPoints(points);
6899
6900
    // set name
6901
    this->SetDataObjectName(czm, cellZoneDict.entry(i).keyword());
2894
    }
6902
    }
2895
  input->close();
2896
6903
2897
  //reopen file in correct format
6904
  delete cellZoneDictPtr;
2898
  if(temp.find("binary") != vtkstd::string::npos)
6905
  vtkDebugMacro(<<"Cell zone mesh created");
6906
  return true;
6907
}
6908
6909
//-----------------------------------------------------------------------------
6910
void vtkOpenFOAMReader::AddArrayToFieldData(vtkDataSetAttributes *fieldData,
6911
  vtkDataArray *array, const vtkStdString &arrayName)
6912
{
6913
  // exclude dimensional unit string if any
6914
  const vtkStdString arrayNameString(arrayName.substr(0, arrayName.find(' ')));
6915
  array->SetName(arrayName.c_str());
6916
6917
  if(array->GetNumberOfComponents() == 1
6918
#if 0
6919
    && (fieldData->IsA("vtkPointData") && arrayNameString == "CellToPoint[p]"
6920
    || fieldData->IsA("vtkCellData") && arrayNameString == "p")
6921
#else
6922
    && arrayNameString == "p"
6923
#endif
6924
    )
2899
    {
6925
    {
2900
#ifdef _WIN32
6926
    fieldData->SetScalars(array);
2901
    input->open(cellZonesPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE);
6927
    }
6928
  else if(array->GetNumberOfComponents() == 3
6929
#if 0
6930
    && (fieldData->IsA("vtkPointData") && arrayNameString == "CellToPoint[U]"
6931
    || fieldData->IsA("vtkCellData") && arrayNameString == "U")
2902
#else
6932
#else
2903
    input->open(cellZonesPath.c_str(), ios::in VTK_IOS_NOCREATE);
6933
    && arrayNameString == "U"
2904
#endif
6934
#endif
2905
    binaryWriteFormat = true;
6935
    )
6936
    {
6937
    fieldData->SetVectors(array);
2906
    }
6938
    }
2907
  else
6939
  else
2908
    {
6940
    {
2909
    input->open(cellZonesPath.c_str(),ios::in);
6941
    fieldData->AddArray(array);
2910
    binaryWriteFormat = false;
2911
    }
6942
    }
6943
}
2912
6944
2913
  vtkstd::string token;
6945
//-----------------------------------------------------------------------------
2914
  vtksys_ios::stringstream tokenizer;
6946
// return 0 if there's any error, 1 if success
2915
  vtkstd::vector< int > cellZone;
6947
int vtkOpenFOAMReader::CreateDataSet(vtkMultiBlockDataSet *output,
2916
  int tempElement;
6948
  int timeState)
2917
  vtkstd::vector< vtkstd::vector < int > > tempElementZones;
6949
{
2918
  int numElement;
6950
  const bool recreateInternalMesh = (!this->CacheMesh)
6951
    || this->TimeStepOld == -1
6952
    || this->PolyMeshFacesDir->GetValue(timeState)
6953
    != this->PolyMeshFacesDir->GetValue(this->TimeStepOld)
6954
    || this->FaceOwner == NULL
6955
    || (this->PatchSelectionStatus & 0x02)
6956
    != (this->PatchSelectionOldStatus & 0x02)
6957
    || this->DecomposePolyhedra != this->DecomposePolyhedraOld
6958
    || this->ReadZones != this->ReadZonesOld
6959
    || this->KeepPatches != this->KeepPatchesOld
6960
    || this->ListTimeStepsByControlDict != this->ListTimeStepsByControlDictOld;
2919
6961
2920
  //find desired mesh entry
6962
  const bool recreateBoundaryMesh = recreateInternalMesh
2921
  while(temp.find(this->CellZoneNames->value[cellZoneIndex]) == 
6963
    || this->PatchSelectionStatus != this->PatchSelectionOldStatus
2922
        vtkstd::string::npos)
6964
    || this->CreateCellToPoint != this->CreateCellToPointOld;
2923
    {
2924
    tempStringStruct = this->GetLine(input);
2925
    temp = tempStringStruct->value;
2926
    delete tempStringStruct;
2927
    }
2928
  tempStringStruct = this->GetLine(input);
2929
  temp = tempStringStruct->value;
2930
  delete tempStringStruct;//throw out {
2931
6965
2932
  tempStringStruct = this->GetLine(input);
6966
  const bool updateVariables = recreateBoundaryMesh
2933
  temp = tempStringStruct->value;
6967
    || timeState != this->TimeStepOld
2934
  delete tempStringStruct;//type
6968
    || this->CellSelectionStatus != this->CellSelectionOldStatus
6969
    || this->PointSelectionStatus != this->PointSelectionOldStatus
6970
    || this->LagrangianSelectionStatus != this->LagrangianSelectionOldStatus
6971
    || this->PositionsIsIn13Format != this->PositionsIsIn13FormatOld
6972
    || this->AddDimensionsToArrayNames != this->AddDimensionsToArrayNamesOld;
2935
6973
2936
  tempStringStruct = this->GetLine(input);
6974
  const bool pointsMoved = this->TimeStepOld == -1
2937
  temp = tempStringStruct->value;
6975
    || this->PolyMeshPointsDir->GetValue(timeState)
2938
  delete tempStringStruct;
6976
    != this->PolyMeshPointsDir->GetValue(this->TimeStepOld);
2939
6977
2940
  tempStringStruct = this->GetLine(input);
6978
  const bool moveInternalPoints = !recreateInternalMesh && pointsMoved;
2941
  temp = tempStringStruct->value;
6979
  const bool moveBoundaryPoints = !recreateBoundaryMesh && pointsMoved;
2942
  delete tempStringStruct;
2943
6980
2944
  //number of elements
6981
  // determine if we need to reconstruct meshes
2945
  tokenizer << temp;
6982
  if(recreateInternalMesh)
2946
  tokenizer >> numElement;
6983
    {
6984
    this->ClearInternalMeshes();
6985
    }
6986
  if(recreateBoundaryMesh)
6987
    {
6988
    this->ClearBoundaryMeshes();
6989
    }
2947
6990
2948
  //binary
6991
  intVectorVector *facePoints = NULL;
2949
  if(binaryWriteFormat)
6992
  vtkStdString meshDir;
6993
  if(recreateInternalMesh || recreateBoundaryMesh)
2950
    {
6994
    {
2951
    input->get(); //parenthesis
6995
    meshDir = *this->PathPrefix
2952
    for(int j = 0; j < numElement; j++)
6996
      + this->PolyMeshFacesDir->GetValue(timeState) + "/polyMesh/";
6997
6998
    // create paths to polyMesh files
6999
    vtkStdString facesPath = meshDir + "faces";
7000
    // create the faces vector
7001
    facePoints = this->ReadFacesFile(facesPath.c_str());
7002
    if(facePoints == NULL)
2953
      {
7003
      {
2954
      input->read((char *) &tempElement, sizeof(int));
7004
      return 0;
2955
      cellZone.push_back(tempElement);
2956
      }
7005
      }
7006
    this->UpdateProgress(0.2);
2957
    }
7007
    }
2958
7008
2959
  //ascii
7009
  vtkIntArray *cellFacesList = NULL;
2960
  else
7010
  vtkIntArray *cellFacesIndices = NULL;
7011
  if(recreateInternalMesh)
2961
    {
7012
    {
2962
    tempStringStruct = this->GetLine(input);
7013
    vtkStdString ownerPath = meshDir + "owner";
2963
    temp = tempStringStruct->value;
7014
    vtkStdString neighborPath = meshDir + "neighbour";
2964
    delete tempStringStruct;//throw out (
2965
7015
2966
    //get each element & add to vector
7016
    // read owner/neighbor and create the faces owner/facesOfCell vector
2967
    for(int j = 0; j < numElement; j++)
7017
    cellFacesList = vtkIntArray::New();
2968
      {
7018
    cellFacesIndices = vtkIntArray::New();
2969
      tempStringStruct = this->GetLine(input);
2970
      temp = tempStringStruct->value;
2971
      delete tempStringStruct;
2972
7019
2973
      tokenizer.clear();
7020
    if(!this->ReadOwnerNeighborFiles(cellFacesList, cellFacesIndices,
2974
      tokenizer << temp;
7021
      ownerPath.c_str(), neighborPath.c_str()))
2975
      tokenizer >> tempElement;
7022
      {
2976
      cellZone.push_back(tempElement);
7023
      delete facePoints;
7024
      cellFacesList->Delete();
7025
      cellFacesIndices->Delete();
7026
      return 0;
2977
      }
7027
      }
7028
    if(static_cast<vtkIdType>(facePoints->nElements())
7029
      != this->FaceOwner->GetNumberOfTuples())
7030
      {
7031
      vtkErrorMacro(<< "The numbers of faces in faces and owners don't match: "
7032
        << "faces = " << facePoints->nElements() << ", owners = "
7033
        << this->FaceOwner->GetNumberOfTuples());
7034
      delete facePoints;
7035
      cellFacesList->Delete();
7036
      cellFacesIndices->Delete();
7037
      return 0;
7038
      }
7039
    this->UpdateProgress(0.3);
2978
    }
7040
    }
2979
7041
2980
  //Create the mesh
7042
  vtkFloatArray *pointArray = NULL;
2981
  bool foundDup = false;
7043
  if(recreateInternalMesh || (recreateBoundaryMesh && !recreateInternalMesh
2982
  vtkstd::vector< int > cellPoints;
7044
    && this->InternalMesh == NULL) || moveInternalPoints || moveBoundaryPoints)
2983
  vtkstd::vector< int > tempFaces[2];
2984
  vtkstd::vector< int > firstFace;
2985
  int pivotPoint = 0;
2986
  int i, j, k, l, pCount;
2987
  int faceCount = 0;
2988
2989
  //Create Mesh
2990
  for(i = 0; i < (int)cellZone.size(); i++)  //each cell
2991
    {
7045
    {
2992
    //calculate total points for all faces of a cell
7046
    // get the points
2993
    //used to determine cell type
7047
    pointArray = this->ReadPointsFile(timeState);
2994
    int totalPointCount = 0;
7048
    if(pointArray == NULL && recreateInternalMesh)
2995
    for(j = 0; j < (int)this->FacesOfCell->value[
2996
      cellZone[i]].size(); j++)  //each face
2997
      {
7049
      {
2998
      totalPointCount += (int)this->FacePoints->value[this->FacesOfCell->value[
7050
      delete facePoints;
2999
        cellZone[i]][j].faceIndex].size();
7051
      cellFacesList->Delete();
7052
      cellFacesIndices->Delete();
7053
      return 0;
3000
      }
7054
      }
7055
    this->UpdateProgress(0.4);
7056
    }
3001
7057
3002
      // using cell type - order points, create cell, add to mesh
7058
  // make internal mesh
3003
7059
  // Create Internal Mesh only if required for display
3004
    //OFhex | vtkHexahedron
7060
  if(recreateInternalMesh)
3005
    if (totalPointCount == 24)
7061
    {
7062
    if(this->GetPatchArrayStatus(GetPatchArrayName(0)))
3006
      {
7063
      {
3007
      faceCount = 0;
7064
      this->InternalMesh = this->MakeInternalMesh(cellFacesList,
3008
7065
        cellFacesIndices, facePoints, pointArray);
3009
      //get first face
7066
      }
3010
      for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[
7067
    // read and construct zones
3011
        cellZone[i]][0].faceIndex].size(); j++)
7068
    if(this->ReadZones)
3012
        {
7069
      {
3013
        firstFace.push_back(this->FacePoints->value[this->FacesOfCell->value[
7070
      vtkPoints *points;
3014
          cellZone[i]][0].faceIndex][j]);
7071
      if(this->InternalMesh != NULL)
3015
        }
3016
3017
      //-if it is a neighbor face flip it
3018
      if(FacesOfCell->value[i][0].neighborFace)
3019
        {
7072
        {
3020
        int tempPop;
7073
        points = this->InternalMesh->GetPoints();
3021
        for(k = 0; k < (int)firstFace.size() - 1; k++)
3022
          {
3023
          tempPop = firstFace[firstFace.size()-1];
3024
          firstFace.pop_back();
3025
          firstFace.insert(firstFace.begin()+1+k, tempPop);
3026
          }
3027
        }
7074
        }
3028
7075
      else
3029
      //add first face to cell points
3030
      for(j =0; j < (int)firstFace.size(); j++)
3031
        {
7076
        {
3032
        cellPoints.push_back(firstFace[j]);
7077
        points = vtkPoints::New();
7078
        points->SetData(pointArray);
3033
        }
7079
        }
3034
7080
3035
      for(int pointCount = 0;pointCount < (int)firstFace.size();pointCount++)
7081
      this->PointZoneMesh = new unstructuredGridVector;
7082
      if(!this->GetPointZoneMesh(this->PointZoneMesh, points, timeState))
3036
        {
7083
        {
3037
        //find the 2 other faces containing each point - start with face 1
7084
        delete this->PointZoneMesh;
3038
        for(j = 1; j < (int)this->FacesOfCell->value[
7085
        this->PointZoneMesh = NULL;
3039
          cellZone[i]].size(); j++)  //each face
7086
        delete facePoints;
7087
        cellFacesList->Delete();
7088
        cellFacesIndices->Delete();
7089
        if(this->InternalMesh == NULL)
3040
          {
7090
          {
3041
          for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->
7091
          points->Delete();
3042
              value[cellZone[i]][j].faceIndex].size(); k++)
3043
            {
3044
            if(firstFace[pointCount] == this->FacePoints->
3045
               value[this->FacesOfCell->value[cellZone[i]][j].faceIndex][k])
3046
              {
3047
              //another face with the point
3048
              for(l = 0; l < (int)this->FacePoints->value[this->FacesOfCell->
3049
                                  value[cellZone[i]][j].faceIndex].size(); l++)
3050
                {
3051
                tempFaces[faceCount].push_back(this->FacePoints->value[
3052
                  this->FacesOfCell->value[cellZone[i]][j].faceIndex]
3053
                  [l]);
3054
                }
3055
              faceCount++;
3056
              }
3057
            }
3058
          }
3059
3060
        //locate the pivot point contained in faces 0 & 1
3061
        for(j = 0; j < (int)tempFaces[0].size(); j++)
3062
          {
3063
          for(k = 0; k < (int)tempFaces[1].size(); k++)
3064
            {
3065
            if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] !=
3066
              firstFace[pointCount])
3067
              {
3068
              pivotPoint = tempFaces[0][j];
3069
              break;
3070
              }
3071
            }
3072
          }
7092
          }
3073
        cellPoints.push_back(pivotPoint);
7093
        pointArray->Delete();
3074
        tempFaces[0].clear();
7094
        return 0;
3075
        tempFaces[1].clear();
3076
        faceCount=0;
3077
        }
7095
        }
3078
7096
      if(this->PointZoneMesh->size() == 0)
3079
        //create the hex cell and insert it into the mesh
7097
        {
3080
        vtkHexahedron * hexahedron = vtkHexahedron::New();
7098
        delete this->PointZoneMesh;
3081
        for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
7099
        this->PointZoneMesh = NULL;
3082
          {
3083
          hexahedron->GetPointIds()->SetId(pCount, cellPoints[pCount]);
3084
          }
3085
        cellZoneMesh->InsertNextCell(hexahedron->GetCellType(),
3086
                                     hexahedron->GetPointIds());
3087
        hexahedron->Delete();
3088
        cellPoints.clear();
3089
        firstFace.clear();
3090
        }
7100
        }
3091
7101
3092
    //OFprism | vtkWedge
7102
      this->FaceZoneMesh = new unstructuredGridVector;
3093
    else if (totalPointCount == 18)
7103
      if(!this->GetFaceZoneMesh(this->FaceZoneMesh, facePoints, points,
3094
      {
7104
        timeState))
3095
      faceCount = 0;
3096
      int index = 0;
3097
3098
      //find first triangular face
3099
      for(j = 0; j < (int)this->FacesOfCell->value[
3100
        cellZone[i]].size(); j++)  //each face
3101
        {
7105
        {
3102
        if((int)this->FacePoints->value[this->FacesOfCell->value[
7106
        delete this->FaceZoneMesh;
3103
          cellZone[i]][j].faceIndex].size() == 3)
7107
        this->FaceZoneMesh = NULL;
7108
        delete this->PointZoneMesh;
7109
        this->PointZoneMesh = NULL;
7110
        delete facePoints;
7111
        cellFacesList->Delete();
7112
        cellFacesIndices->Delete();
7113
        if(this->InternalMesh == NULL)
3104
          {
7114
          {
3105
          for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[
7115
          points->Delete();
3106
            cellZone[i]][j].faceIndex].size(); k++)
3107
            {
3108
            firstFace.push_back(this->FacePoints->value[this->FacesOfCell->
3109
                                  value[cellZone[i]][j].faceIndex][k]);
3110
            index = j;
3111
            }
3112
          break;
3113
          }
7116
          }
7117
        pointArray->Delete();
7118
        return 0;
3114
        }
7119
        }
3115
7120
      if(this->FaceZoneMesh->size() == 0)
3116
      //-if it is a neighbor face flip it
3117
      if(this->FacesOfCell->value[i][0].neighborFace)
3118
        {
7121
        {
3119
        int tempPop;
7122
        delete this->FaceZoneMesh;
3120
        for(k = 0; k < (int)firstFace.size() - 1; k++)
7123
        this->FaceZoneMesh = NULL;
7124
        }
7125
7126
      this->CellZoneMesh = new unstructuredGridVector;
7127
      if(!this->GetCellZoneMesh(this->CellZoneMesh, cellFacesList,
7128
        cellFacesIndices, facePoints, points, timeState))
7129
        {
7130
        delete this->CellZoneMesh;
7131
        this->CellZoneMesh = NULL;
7132
        delete this->FaceZoneMesh;
7133
        this->FaceZoneMesh = NULL;
7134
        delete this->PointZoneMesh;
7135
        this->PointZoneMesh = NULL;
7136
        delete facePoints;
7137
        cellFacesList->Delete();
7138
        cellFacesIndices->Delete();
7139
        if(this->InternalMesh == NULL)
3121
          {
7140
          {
3122
          tempPop = firstFace[firstFace.size()-1];
7141
          points->Delete();
3123
          firstFace.pop_back();
3124
          firstFace.insert(firstFace.begin()+1+k, tempPop);
3125
          }
7142
          }
7143
        pointArray->Delete();
7144
        return 0;
3126
        }
7145
        }
3127
7146
      if(this->CellZoneMesh->size() == 0)
3128
      //add first face to cell points
3129
      for(j =0; j < (int)firstFace.size(); j++)
3130
        {
7147
        {
3131
        cellPoints.push_back(firstFace[j]);
7148
        delete this->CellZoneMesh;
7149
        this->CellZoneMesh = NULL;
3132
        }
7150
        }
3133
7151
      if(this->InternalMesh == NULL)
3134
      for(int pointCount = 0;pointCount < (int)firstFace.size();pointCount++)
3135
        {
7152
        {
3136
        //find the 2 other faces containing each point
7153
        points->Delete();
3137
        for(j = 0; j < (int)this->FacesOfCell->value[
3138
          cellZone[i]].size(); j++)  //each face
3139
          {
3140
          for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[
3141
            cellZone[i]][j].faceIndex].size(); k++) //each point
3142
            {
3143
            if(firstFace[pointCount] == this->FacePoints->
3144
               value[this->FacesOfCell->value[cellZone[i]][j].faceIndex][k] &&
3145
               j != index)
3146
              {
3147
              //another face with point
3148
              for(l = 0; l < (int)this->FacePoints->value[this->
3149
                  FacesOfCell->value[cellZone[i]][j].faceIndex].size(); l++)
3150
                {
3151
                tempFaces[faceCount].push_back(this->FacePoints->value[
3152
                  this->FacesOfCell->value[cellZone[i]][j].faceIndex]
3153
                  [l]);
3154
                }
3155
              faceCount++;
3156
              }
3157
            }
3158
          }
3159
3160
        //locate the pivot point contained in faces 0 & 1
3161
        for(j = 0; j < (int)tempFaces[0].size(); j++)
3162
          {
3163
          for(k = 0; k < (int)tempFaces[1].size(); k++)
3164
            {
3165
            if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] !=
3166
              firstFace[pointCount])
3167
              {
3168
              pivotPoint = tempFaces[0][j];
3169
              break;
3170
              }
3171
            }
3172
          }
3173
        cellPoints.push_back(pivotPoint);
3174
        tempFaces[0].clear();
3175
        tempFaces[1].clear();
3176
        faceCount=0;
3177
        }
7154
        }
7155
      }
7156
    cellFacesList->Delete();
7157
    cellFacesIndices->Delete();
7158
    this->TruncateFaceOwner();
7159
    }
3178
7160
3179
      //create the wedge cell and insert it into the mesh
7161
  if(recreateBoundaryMesh)
3180
      vtkWedge * wedge = vtkWedge::New();
7162
    {
3181
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
7163
    vtkFloatArray *boundaryPointArray;
7164
    if(pointArray != NULL)
7165
      {
7166
      boundaryPointArray = pointArray;
7167
      }
7168
    else
7169
      {
7170
      boundaryPointArray = static_cast<vtkFloatArray *>(
7171
        this->InternalMesh->GetPoints()->GetData());
7172
      }
7173
    // create boundary mesh
7174
    this->BoundaryMesh = this->MakeBoundaryMesh(this->BoundaryDict, facePoints,
7175
      boundaryPointArray);
7176
    if(this->BoundaryMesh == NULL)
7177
      {
7178
      delete facePoints;
7179
      if(pointArray != NULL)
3182
        {
7180
        {
3183
        wedge->GetPointIds()->SetId(pCount, cellPoints[pCount]);
7181
        pointArray->Delete();
3184
        }
7182
        }
3185
      cellZoneMesh->InsertNextCell(wedge->GetCellType(),
7183
      return 0;
3186
                                   wedge->GetPointIds());
3187
      cellPoints.clear();
3188
      wedge->Delete();
3189
      firstFace.clear();
3190
      }
7184
      }
7185
    }
3191
7186
3192
    //OFpyramid | vtkPyramid
7187
  delete facePoints;
3193
    else if (totalPointCount == 16)
7188
7189
  // if only point coordinates change refresh point vector
7190
  if(moveInternalPoints)
7191
    {
7192
    // refresh the points in each mesh
7193
    vtkPoints *points;
7194
    // Check if Internal Mesh exists first....
7195
    if(this->InternalMesh != NULL)
7196
      {
7197
      points = this->MoveInternalMesh(this->InternalMesh, pointArray);
7198
      }
7199
    else
3194
      {
7200
      {
3195
      foundDup = false;
7201
      points = vtkPoints::New();
7202
      points->SetData(pointArray);
7203
      }
3196
7204
3197
      //find quad
7205
    if(this->PointZoneMesh != NULL)
3198
      for(j = 0; j < (int)this->FacesOfCell->value[
7206
      {
3199
        cellZone[i]].size(); j++)  //each face
7207
      for(size_t i = 0; i < this->PointZoneMesh->size(); i++)
3200
        {
7208
        {
3201
        if((int)this->FacePoints->value[this->FacesOfCell->value[
7209
        this->PointZoneMesh->operator[](i)->SetPoints(points);
3202
          cellZone[i]][j].faceIndex].size() == 4)
3203
          {
3204
          for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[
3205
            cellZone[i]][j].faceIndex].size(); k++)
3206
            {
3207
            cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->
3208
              value[cellZone[i]][j].faceIndex][k]);
3209
            }
3210
          break;
3211
          }
3212
        }
7210
        }
3213
7211
      }
3214
      //compare first face points to second faces
7212
    if(this->FaceZoneMesh != NULL)
3215
      for(j = 0; j < (int)cellPoints.size(); j++) //each point
7213
      {
7214
      for(size_t i = 0; i < this->FaceZoneMesh->size(); i++)
3216
        {
7215
        {
3217
        for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[
7216
        this->FaceZoneMesh->operator[](i)->SetPoints(points);
3218
          cellZone[i]][1].faceIndex].size(); k++)
3219
          {
3220
          if(cellPoints[j] == this->FacePoints->value[this->FacesOfCell->value[
3221
            cellZone[i]][1].faceIndex][k])
3222
            {
3223
            foundDup = true;
3224
            }
3225
          }
3226
        if(!foundDup)
3227
          {
3228
          cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->value[
3229
            cellZone[i]][j].faceIndex][k]);
3230
          break;
3231
          }
3232
        }
7217
        }
3233
7218
      }
3234
      //create the pyramid cell and insert it into the mesh
7219
    if(this->CellZoneMesh != NULL)
3235
      vtkPyramid * pyramid = vtkPyramid::New();
7220
      {
3236
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
7221
      for(size_t i = 0; i < this->CellZoneMesh->size(); i++)
3237
        {
7222
        {
3238
        pyramid->GetPointIds()->SetId(pCount, cellPoints[pCount]);
7223
        this->CellZoneMesh->operator[](i)->SetPoints(points);
3239
        }
7224
        }
3240
      cellZoneMesh->InsertNextCell(pyramid->GetCellType(),
3241
                                   pyramid->GetPointIds());
3242
      cellPoints.clear();
3243
      pyramid->Delete();
3244
      }
7225
      }
7226
    points->Delete();
7227
    }
3245
7228
3246
    //OFtet | vtkTetrahedron
7229
  if(moveBoundaryPoints)
3247
    else if (totalPointCount == 12)
7230
    {
7231
    // Check if Boundary Mesh exists first....
7232
    if(this->BoundaryMesh != NULL)
3248
      {
7233
      {
3249
      foundDup = false;
7234
      this->MoveBoundaryMesh(this->BoundaryMesh, pointArray);
7235
      }
7236
    }
7237
7238
  if(pointArray != NULL)
7239
    {
7240
    pointArray->Delete();
7241
    }
7242
  this->UpdateProgress(0.5);
3250
7243
3251
      //grab first face
7244
  polyDataVector *lagrangianMesh = new polyDataVector;
3252
      for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[
7245
  if(updateVariables)
3253
        cellZone[i]][0].faceIndex].size(); j++)
7246
    {
7247
    if(!recreateInternalMesh && this->InternalMesh != NULL)
7248
      {
7249
      // clean up arrays of the previous timestep
7250
      // Check if Internal Mesh Exists first...
7251
      this->InternalMesh->GetCellData()->Initialize();
7252
      this->InternalMesh->GetPointData()->Initialize();
7253
      }
7254
    // Check if Boundary Mesh Exists first...
7255
    if(!recreateBoundaryMesh && this->BoundaryMesh != NULL)
7256
      {
7257
      for(size_t i = 0; i < this->BoundaryMesh->size(); i++)
3254
        {
7258
        {
3255
        cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->value[
7259
        this->BoundaryMesh->operator[](i)->GetCellData()->Initialize();
3256
          cellZone[i]][0].faceIndex][j]);
7260
        this->BoundaryMesh->operator[](i)->GetPointData()->Initialize();
3257
        }
7261
        }
7262
      }
7263
    // read field data variables into Internal/Boundary meshes
7264
    for(int i = 0; i < (int)this->VolFieldFiles->GetNumberOfValues(); i++)
7265
      {
7266
      this->GetVolFieldAtTimestep(this->InternalMesh, this->BoundaryMesh,
7267
        this->BoundaryDict, this->VolFieldFiles->GetValue(i).c_str(),
7268
        timeState);
7269
      this->UpdateProgress(0.5 + 0.25 * ((float)(i + 1)
7270
        / ((float)this->VolFieldFiles->GetNumberOfValues() + 0.0001)));
7271
      }
7272
    for(int i = 0; i < (int)this->PointFieldFiles->GetNumberOfValues(); i++)
7273
      {
7274
      this->GetPointFieldAtTimestep(this->InternalMesh, this->BoundaryMesh,
7275
        this->BoundaryDict, this->PointFieldFiles->GetValue(i).c_str(),
7276
        timeState);
7277
      this->UpdateProgress(0.75 + 0.125 * ((float)(i + 1)
7278
        / ((float)this->PointFieldFiles->GetNumberOfValues() + 0.0001)));
7279
      }
3258
7280
3259
      //compare first face points to second faces
7281
    // read lagrangian mesh and fields
3260
      for(j = 0; j < (int)cellPoints.size(); j++) //each point
7282
    for(int cloudI = 0; cloudI < this->LagrangianPaths->GetNumberOfTuples();
7283
      cloudI++)
7284
      {
7285
      const vtkStdString& pathI = this->LagrangianPaths->GetValue(cloudI);
7286
      if(this->GetPatchArrayStatus(pathI.c_str()))
3261
        {
7287
        {
3262
        for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[
7288
        // construct lagrangian mesh
3263
          cellZone[i]][1].faceIndex].size(); k++)
7289
        vtkPolyData *meshI = this->MakeLagrangianMesh(timeState, pathI);
7290
        if(meshI == NULL)
7291
	  {
7292
          // if mesh doesn't exist we create an empty mesh to keep
7293
          // node/leaf structure of the multi-block consistent
7294
          meshI = vtkPolyData::New();
7295
          this->SetDataObjectName(meshI, pathI.c_str());
7296
	  }
7297
	else
3264
          {
7298
          {
3265
          if(cellPoints[j] == this->FacePoints->value[this->FacesOfCell->value[
7299
          // read lagrangian variables
3266
            cellZone[i]][1].faceIndex][k])
7300
          for(int i = 0; i < this->LagrangianFieldFiles->GetNumberOfValues();
7301
            i++)
3267
            {
7302
            {
3268
            foundDup = true;
7303
            this->GetLagrangianFieldAtTimestep(meshI,
7304
              this->LagrangianFieldFiles->GetValue(i).c_str(), timeState,
7305
              pathI);
3269
            }
7306
            }
3270
          }
7307
          }
3271
        if(!foundDup)
7308
        lagrangianMesh->push_back(meshI);
3272
          {
3273
          cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->value[
3274
            cellZone[i]][j].faceIndex][k]);
3275
          break;
3276
          }
3277
        }
3278
3279
      //create the wedge cell and insert it into the mesh
3280
      vtkTetra * tetra = vtkTetra::New();
3281
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
3282
        {
3283
        tetra->GetPointIds()->SetId(pCount, cellPoints[pCount]);
3284
        }
7309
        }
3285
      cellZoneMesh->InsertNextCell(tetra->GetCellType(),
3286
                                   tetra->GetPointIds());
3287
      cellPoints.clear();
3288
      tetra->Delete();
3289
      }
7310
      }
7311
    }
7312
7313
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7314
  // do nothing
7315
#else
7316
  // assign group to each of data and point/face/cell-Zones
7317
  int nGroups = 1
7318
    + ((lagrangianMesh->size() != 0
7319
      ||  this->GetPatchArrayStatus("Lagrangian Particles")) ? 1 : 0)
7320
    + (this->PointZoneMesh != NULL ? 1 : 0)
7321
    + (this->FaceZoneMesh != NULL ? 1 : 0)
7322
    + (this->CellZoneMesh != NULL ? 1 : 0);
7323
  output->SetNumberOfGroups(nGroups);
7324
#endif
7325
7326
  // set internal mesh/data as output
7327
7328
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7329
  vtkMultiBlockDataSet *eulerians = vtkMultiBlockDataSet::New();
7330
#endif
7331
7332
  // Add Internal Mesh to final output only if selected for display
7333
  if(this->InternalMesh != NULL)
7334
    {
7335
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7336
    eulerians->SetBlock(0, this->InternalMesh);
7337
    this->SetBlockName(eulerians, 0, this->InternalMesh);
7338
#else
7339
    output->SetDataSet(0, output->GetNumberOfDataSets(0), this->InternalMesh);
7340
#endif
7341
    }
3290
7342
3291
    //erronous cells
7343
  // set boundary meshes/data as output
3292
    else if(totalPointCount == 0)
7344
  for(size_t j = 0; j < this->BoundaryMesh->size(); j++)
7345
    {
7346
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7347
    const unsigned int dataSetI = eulerians->GetNumberOfBlocks();
7348
    eulerians->SetBlock(dataSetI, this->BoundaryMesh->operator[](j));
7349
    this->SetBlockName(eulerians, dataSetI, this->BoundaryMesh->operator[](j));
7350
#else
7351
    output->SetDataSet(0, output->GetNumberOfDataSets(0),
7352
      this->BoundaryMesh->operator[](j));
7353
#endif
7354
    }
7355
7356
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7357
  output->SetBlock(0, eulerians);
7358
  output->GetMetaData(static_cast<unsigned int>(0))
7359
    ->Set(vtkCompositeDataSet::NAME(), "Vol/Point Data");
7360
  eulerians->Delete();
7361
#else
7362
  int groupI = 1;
7363
#endif
7364
7365
  // set lagrangian mesh as output
7366
  if(lagrangianMesh->size() > 0)
7367
    {
7368
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7369
    vtkMultiBlockDataSet *lagrangians = vtkMultiBlockDataSet::New();
7370
#endif
7371
    for(size_t meshI = 0; meshI < lagrangianMesh->size(); meshI++)
3293
      {
7372
      {
3294
      vtkWarningMacro("Warning: No points in cell.");
7373
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7374
      lagrangians->SetBlock(meshI, lagrangianMesh->operator[](meshI));
7375
      this->SetBlockName(lagrangians, meshI, lagrangianMesh->operator[](meshI));
7376
#else
7377
      output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI),
7378
        lagrangianMesh->operator[](meshI));
7379
#endif
3295
      }
7380
      }
7381
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7382
    const unsigned int groupTypeI = output->GetNumberOfBlocks();
7383
    output->SetBlock(groupTypeI, lagrangians);
7384
    output->GetMetaData(groupTypeI)
7385
      ->Set(vtkCompositeDataSet::NAME(), "Lagrangian Particles");
7386
    lagrangians->Delete();
7387
#else
7388
    groupI++;
7389
#endif
7390
    }
7391
  delete lagrangianMesh;
3296
7392
3297
    //OFpolyhedron || vtkConvexPointSet
7393
  if(this->ReadZones)
3298
    else
7394
    {
7395
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7396
    vtkMultiBlockDataSet *zones = NULL;
7397
#endif
7398
    // set Zone Meshes as output
7399
    if(this->PointZoneMesh != NULL)
3299
      {
7400
      {
3300
      vtkWarningMacro("Warning: Polyhedral Data is very Slow!");
7401
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
3301
      foundDup = false;
7402
      if(zones == NULL)
3302
7403
	{
3303
      //grab face 0
7404
	zones = vtkMultiBlockDataSet::New();
3304
      for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[
7405
	}
3305
        cellZone[i]][0].faceIndex].size(); j++)
7406
      vtkMultiBlockDataSet *pointZone = vtkMultiBlockDataSet::New();
7407
#endif
7408
      for(size_t i = 0; i < this->PointZoneMesh->size(); i++)
3306
        {
7409
        {
3307
        firstFace.push_back(this->FacePoints->value[
7410
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
3308
          this->FacesOfCell->value[i][0].faceIndex][j]);
7411
        const unsigned int zoneI = pointZone->GetNumberOfBlocks();
7412
	vtkDataObject *zoneMeshI = this->PointZoneMesh->operator[](i);
7413
        pointZone->SetBlock(zoneI, zoneMeshI);
7414
        this->SetBlockName(pointZone, zoneI, zoneMeshI);
7415
#else
7416
        output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI),
7417
          this->PointZoneMesh->operator[](i));
7418
#endif
3309
        }
7419
        }
7420
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7421
      const unsigned int zoneTypeI = zones->GetNumberOfBlocks();
7422
      zones->SetBlock(zoneTypeI, pointZone);
7423
      this->SetBlockName(zones, zoneTypeI, "pointZones");
7424
      pointZone->Delete();
7425
#else
7426
      groupI++;
7427
#endif
7428
      }
3310
7429
3311
      //ADD FIRST FACE TO CELL POINTS
7430
    if(this->FaceZoneMesh != NULL)
3312
      for(j =0; j < (int)firstFace.size(); j++)
7431
      {
3313
        {
7432
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
3314
        cellPoints.push_back(firstFace[j]);
7433
      if(zones == NULL)
3315
        }
7434
	{
3316
      //j = 1 skip firstFace
7435
	zones = vtkMultiBlockDataSet::New();
3317
      for(j = 1; j < (int) this->FacesOfCell->value[
7436
	}
3318
           cellZone[i]].size(); j++)
7437
      vtkMultiBlockDataSet *faceZone = vtkMultiBlockDataSet::New();
3319
        {
7438
#endif
3320
        //remove duplicate points from faces
7439
      for(size_t i = 0; i < this->FaceZoneMesh->size(); i++)
3321
        for(k = 0; k < (int)this->FacePoints->value[
7440
	{
3322
            this->FacesOfCell->value[i][j].faceIndex].size(); k++)
7441
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
3323
          {
7442
        const unsigned int zoneI = faceZone->GetNumberOfBlocks();
3324
          for(l = 0; l < (int)cellPoints.size(); l++);
7443
	vtkDataObject *zoneMeshI = this->FaceZoneMesh->operator[](i);
3325
            {
7444
	faceZone->SetBlock(zoneI, zoneMeshI);
3326
            if(cellPoints[l] == this->FacePoints->value[this->FacesOfCell->
7445
	this->SetBlockName(faceZone, zoneI, zoneMeshI);
3327
                                value[cellZone[i]][j].faceIndex][k])
7446
#else
3328
              {
7447
        output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI),
3329
              foundDup = true;
7448
          this->FaceZoneMesh->operator[](i));
3330
              }
7449
#endif
3331
            }
3332
          if(!foundDup)
3333
            {
3334
            cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->
3335
                                 value[cellZone[i]][j].faceIndex][k]);
3336
            foundDup = false;
3337
            }
3338
          }
3339
        }
7450
        }
7451
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7452
      const unsigned int zoneTypeI = zones->GetNumberOfBlocks();
7453
      zones->SetBlock(zoneTypeI, faceZone);
7454
      this->SetBlockName(zones, zoneTypeI, "faceZones");
7455
      faceZone->Delete();
7456
#else
7457
      groupI++;
7458
#endif
7459
      }
3340
7460
3341
      //create the poly cell and insert it into the mesh
7461
    if(this->CellZoneMesh != NULL)
3342
      vtkConvexPointSet * poly = vtkConvexPointSet::New();
7462
      {
3343
      poly->GetPointIds()->SetNumberOfIds(cellPoints.size());
7463
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
3344
      for(pCount = 0; pCount < (int)cellPoints.size(); pCount++)
7464
      if(zones == NULL)
3345
        {
7465
	{
3346
        poly->GetPointIds()->SetId(pCount, cellPoints[pCount]);
7466
	zones = vtkMultiBlockDataSet::New();
3347
        }
7467
	}
3348
      cellZoneMesh->InsertNextCell(poly->GetCellType(),
7468
      vtkMultiBlockDataSet *cellZone = vtkMultiBlockDataSet::New();
3349
                                   poly->GetPointIds());
7469
#endif
3350
      cellPoints.clear();
7470
      for(size_t i = 0; i < this->CellZoneMesh->size(); i++)
3351
      firstFace.clear();
7471
	{
3352
      poly->Delete();
7472
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7473
        const unsigned int zoneI = cellZone->GetNumberOfBlocks();
7474
	vtkDataObject *zoneMeshI = this->CellZoneMesh->operator[](i);
7475
	cellZone->SetBlock(zoneI, zoneMeshI);
7476
	this->SetBlockName(cellZone, zoneI, zoneMeshI);
7477
#else
7478
	output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI),
7479
	  this->CellZoneMesh->operator[](i));
7480
#endif
7481
	}
7482
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7483
      const unsigned int zoneTypeI = zones->GetNumberOfBlocks();
7484
      zones->SetBlock(zoneTypeI, cellZone);
7485
      this->SetBlockName(zones, zoneTypeI, "cellZones");
7486
      cellZone->Delete();
7487
#endif
7488
      }
7489
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
7490
    if(zones != NULL)
7491
      {
7492
      const unsigned int groupTypeI = output->GetNumberOfBlocks();
7493
      output->SetBlock(groupTypeI, zones);
7494
      this->SetBlockName(output, groupTypeI, "Zones");
3353
      }
7495
      }
7496
#endif
3354
    }
7497
    }
3355
  //set cell zone points
3356
  cellZoneMesh->SetPoints(Points);
3357
  input->close();
3358
  delete input;
3359
  vtkDebugMacro(<<"Cell zone mesh created");
3360
  return cellZoneMesh;
3361
}
3362
7498
3363
void vtkOpenFOAMReader::CreateDataSet(vtkMultiBlockDataSet *output)
7499
  if(this->CacheMesh)
3364
{
7500
    {
3365
  int timeState = this->TimeStep;
7501
    this->TimeStepOld = timeState;
3366
  //create paths to polyMesh files
3367
  vtkstd::string boundaryPath = this->PathPrefix->value +
3368
                                this->PolyMeshFacesDir->value[timeState] +
3369
                                "/polyMesh/boundary";
3370
  vtkstd::string facePath = this->PathPrefix->value +
3371
                            this->PolyMeshFacesDir->value[timeState] +
3372
                            "/polyMesh/faces";
3373
  vtkstd::string ownerPath = this->PathPrefix->value +
3374
                             this->PolyMeshFacesDir->value[timeState] +
3375
                             "/polyMesh/owner";
3376
  vtkstd::string neighborPath = this->PathPrefix->value +
3377
                                this->PolyMeshFacesDir->value[timeState] +
3378
                                "/polyMesh/neighbour";
3379
  //create the faces vector
3380
  this->ReadFacesFile(facePath.c_str());
3381
3382
  //create the faces owner vector
3383
  this->ReadOwnerFile(ownerPath.c_str());
3384
3385
  //create the faces neighbor vector
3386
  this->ReadNeighborFile(neighborPath.c_str());
3387
3388
  //create a vector containing a faces of each cell
3389
  this->CombineOwnerNeigbor();
3390
3391
  this->GetPoints(timeState); //get the points
3392
3393
  //get the names of the regions
3394
  //this->BoundaryNames->value =
3395
  //  this->GatherBlocks("boundary", timeState)->value;
3396
  //this->PointZoneNames->value =
3397
  //  this->GatherBlocks("pointZones", timeState)->value;
3398
  //this->FaceZoneNames->value =
3399
  //  this->GatherBlocks("faceZones", timeState)->value;
3400
  //this->CellZoneNames->value =
3401
  //  this->GatherBlocks("cellZones", timeState)->value;
3402
3403
  //get the names of the regions
3404
  this->BoundaryNames =
3405
    this->GatherBlocks("boundary", timeState);
3406
  this->PointZoneNames =
3407
    this->GatherBlocks("pointZones", timeState);
3408
  this->FaceZoneNames =
3409
    this->GatherBlocks("faceZones", timeState);
3410
  this->CellZoneNames =
3411
    this->GatherBlocks("cellZones", timeState);
3412
3413
  int numBoundaries = static_cast<int>(this->BoundaryNames->value.size());
3414
  int numPointZones = static_cast<int>(this->PointZoneNames->value.size());
3415
  int numFaceZones = static_cast<int>(this->FaceZoneNames->value.size());
3416
  int numCellZones = static_cast<int>(this->CellZoneNames->value.size());
3417
3418
  //Internal Mesh
3419
  vtkUnstructuredGrid * internalMesh = this->MakeInternalMesh();
3420
  for(int i = 0; i < (int)this->TimeStepData->value.size(); i++)
3421
    {
3422
    vtkDoubleArray * data =
3423
      this->GetInternalVariableAtTimestep(this->TimeStepData->value[i].c_str(),
3424
                                          timeState);
3425
    if(data->GetSize() > 0)
3426
      {
3427
      data->SetName(this->TimeStepData->value[i].c_str());
3428
      internalMesh->GetCellData()->AddArray(data);
3429
      }
3430
    data->Delete();
3431
    }
3432
  output->SetBlock(output->GetNumberOfBlocks(), internalMesh);
3433
3434
  //Boundary Meshes
3435
  for(int i = 0; i < (int)numBoundaries; i++)
3436
    {
3437
    vtkUnstructuredGrid * boundaryMesh = this->GetBoundaryMesh(timeState, i);
3438
    for(int j = 0; j < (int)this->TimeStepData->value.size(); j++)
3439
      {
3440
      vtkDoubleArray * data =
3441
        this->GetBoundaryVariableAtTimestep(i, TimeStepData->value[j].c_str(),
3442
                                            timeState, internalMesh);
3443
      if(data->GetSize() > 0)
3444
        {
3445
        data->SetName(this->TimeStepData->value[j].c_str());
3446
        boundaryMesh->GetCellData()->AddArray(data);
3447
        }
3448
      data->Delete();
3449
      }
3450
    output->SetBlock(output->GetNumberOfBlocks(), boundaryMesh);
3451
    boundaryMesh->Delete();
3452
    }
3453
3454
  internalMesh->Delete();
3455
  this->FaceOwner->Delete();
3456
  //Zone Meshes
3457
  for(int i = 0; i < (int)numPointZones; i++)
3458
    {
3459
    vtkUnstructuredGrid * pointMesh = this->GetPointZoneMesh(timeState, i);
3460
    output->SetBlock(output->GetNumberOfBlocks(), pointMesh);
3461
    pointMesh->Delete();
3462
    }
3463
  for(int i = 0; i < (int)numFaceZones; i++)
3464
    {
3465
    vtkUnstructuredGrid * faceMesh = this->GetFaceZoneMesh(timeState, i);
3466
    output->SetBlock(output->GetNumberOfBlocks(), faceMesh);
3467
    faceMesh->Delete();
3468
    }
3469
  for(int i = 0; i < (int)numCellZones; i++)
3470
    {
3471
    vtkUnstructuredGrid * cellMesh = this->GetCellZoneMesh(timeState, i);
3472
    output->SetBlock(output->GetNumberOfBlocks(), cellMesh);
3473
    cellMesh->Delete();
3474
    }
7502
    }
3475
  return;
7503
  else
3476
}
3477
stdString * vtkOpenFOAMReader::GetLine(ifstream * file)
3478
{
3479
  char tempChar;
3480
  stdString * buffer = new stdString;
3481
  while(file->peek() != '\n')
3482
    {
7504
    {
3483
    file->get(tempChar);
7505
    this->ClearMeshes();
3484
    buffer->value += tempChar;
7506
    this->TimeStepOld = -1;
3485
    }
7507
    }
3486
  file->get(tempChar); //throw out \n
7508
3487
  return buffer;
7509
  this->UpdateProgress(1.0);
7510
  return 1;
3488
}
7511
}
(-)ParaView3-src/VTK/IO/vtkOpenFOAMReader.h (-69 / +343 lines)
Lines 23-52 Link Here
23
// .SECTION Thanks
23
// .SECTION Thanks
24
// Thanks to Terry Jordan of SAIC at the National Energy
24
// Thanks to Terry Jordan of SAIC at the National Energy
25
// Technology Laboratory who developed this class.
25
// Technology Laboratory who developed this class.
26
// Please address all comments to Terry Jordan (terry.jordan@sa.netl.doe.gov)
26
// Please address all comments to Terry Jordan (terry.jordan@sa.netl.doe.gov).
27
// Gzipped file, lagrangian field, new UI support and
28
// performance/compatibility enhancements by Takuya Oshima
29
// (oshima@eng.niigata-u.ac.jp) and Philippose Rajan (sarith@rocketmail.com).
30
31
// version 2008-07-24
27
32
28
#ifndef __vtkOpenFOAMReader_h
33
#ifndef __vtkOpenFOAMReader_h
29
#define __vtkOpenFOAMReader_h
34
#define __vtkOpenFOAMReader_h
30
35
31
#include "vtkMultiBlockDataSetAlgorithm.h"
36
#include "vtkMultiBlockDataSetAlgorithm.h"
37
#include "vtkPVConfig.h" // for PARAVIEW_VERSION_MAJOR, PARAVIEW_VERSION_MINOR
32
38
33
typedef struct
39
class vtkCallbackCommand;
34
{
35
  int faceIndex;
36
  bool neighborFace;
37
} face;
38
39
class vtkUnstructuredGrid;
40
class vtkPoints;
41
class vtkIntArray;
42
class vtkFloatArray;
43
class vtkDoubleArray;
44
class vtkDataArraySelection;
40
class vtkDataArraySelection;
45
struct stdString;
41
class vtkDataObject;
46
struct stringVector;
42
class vtkDataSetAttributes;
47
struct intVector;
43
class vtkFloatArray;
48
struct intVectorVector;
44
class vtkIdList;
49
struct faceVectorVector;
45
class vtkIdTypeArray;
46
class vtkIntArray;
47
class vtkPoints;
48
class vtkPolyData;
49
class vtkStdString;
50
class vtkStringArray;
51
class vtkUnstructuredGrid;
52
//BTX
53
class intArrayVector;
54
class unstructuredGridVector;
55
//ETX
50
56
51
class VTK_IO_EXPORT vtkOpenFOAMReader : public vtkMultiBlockDataSetAlgorithm
57
class VTK_IO_EXPORT vtkOpenFOAMReader : public vtkMultiBlockDataSetAlgorithm
52
{
58
{
Lines 56-61 Link Here
56
  void PrintSelf(ostream& os, vtkIndent indent);
62
  void PrintSelf(ostream& os, vtkIndent indent);
57
63
58
  // Description:
64
  // Description:
65
  // Determine if the file can be readed with this reader.
66
  int CanReadFile(const char* fname);
67
68
  // Description:
59
  // Set/Get the filename.
69
  // Set/Get the filename.
60
  vtkSetStringMacro(FileName);
70
  vtkSetStringMacro(FileName);
61
  vtkGetStringMacro(FileName);
71
  vtkGetStringMacro(FileName);
Lines 80-164 Link Here
80
  // Description:
90
  // Description:
81
  // Get/Set whether the cell array with the given name is to
91
  // Get/Set whether the cell array with the given name is to
82
  // be read.
92
  // be read.
83
  int GetCellArrayStatus(const char* name);
93
  int GetCellArrayStatus(const char *name);
84
  void SetCellArrayStatus(const char* name, int status);
94
  void SetCellArrayStatus(const char *name, int status);
85
95
86
  // Description:
96
  // Description:
87
  // Get the name of the  cell array with the given index in
97
  // Get the name of the  cell array with the given index in
88
  // the input.
98
  // the input.
89
  const char* GetCellArrayName(int index);
99
  const char *GetCellArrayName(int index);
90
100
91
  // Description:
101
  // Description:
92
  // Turn on/off all cell arrays.
102
  // Turn on/off all cell arrays.
93
  void DisableAllCellArrays();
103
  void DisableAllCellArrays();
94
  void EnableAllCellArrays();
104
  void EnableAllCellArrays();
95
105
106
  // Description:
107
  // Get the number of point arrays available in the input.
108
  int GetNumberOfPointArrays(void);
109
110
  // Description:
111
  // Get/Set whether the point array with the given name is to
112
  // be read.
113
  int GetPointArrayStatus(const char *name);
114
  void SetPointArrayStatus(const char *name, int status);
115
116
  // Description:
117
  // Get the name of the  point array with the given index in
118
  // the input.
119
  const char* GetPointArrayName(int index);
120
121
  // Description:
122
  // Turn on/off all point arrays.
123
  void DisableAllPointArrays();
124
  void EnableAllPointArrays();
125
126
  // Description:
127
  // Get the number of point arrays available in the input.
128
  int GetNumberOfLagrangianArrays(void);
129
130
  // Description:
131
  // Get/Set whether the point array with the given name is to
132
  // be read.
133
  int GetLagrangianArrayStatus(const char *name);
134
  void SetLagrangianArrayStatus(const char *name, int status);
135
136
  // Description:
137
  // Get the name of the  point array with the given index in
138
  // the input.
139
  const char* GetLagrangianArrayName(int index);
140
141
  // Description:
142
  // Turn on/off all point arrays.
143
  void DisableAllLagrangianArrays();
144
  void EnableAllLagrangianArrays();
145
146
  // Description:
147
  // Get the number of Patches (inlcuding Internal Mesh) available in the input.
148
  int GetNumberOfPatchArrays(void);
149
150
  // Description:
151
  // Get/Set whether the Patch with the given name is to
152
  // be read.
153
  int GetPatchArrayStatus(const char *name);
154
  void SetPatchArrayStatus(const char *name, int status);
155
156
  // Description:
157
  // Get the name of the Patch with the given index in
158
  // the input.
159
  const char *GetPatchArrayName(int index);
160
161
  // Description:
162
  // Turn on/off all Patches including the Internal Mesh.
163
  void DisableAllPatchArrays();
164
  void EnableAllPatchArrays();
165
166
  // Selection observer callback functions
167
  static void SelectionModifiedCallback
168
  (
169
    vtkObject *caller,
170
    unsigned long eid,
171
    void *clientdata,
172
    void *calldata
173
  );
174
175
  void SelectionModified(const bool);
176
177
  // Description:
178
  // Set/Get whether to create cell-to-point translated data for cell-type data
179
  vtkSetMacro(CreateCellToPoint,int);
180
  vtkGetMacro(CreateCellToPoint,int);
181
  vtkBooleanMacro(CreateCellToPoint, int);
182
183
  // Description:
184
  // Set/Get whether mesh is to be cached.
185
  vtkSetMacro(CacheMesh, int);
186
  vtkGetMacro(CacheMesh, int);
187
  vtkBooleanMacro(CacheMesh, int);
188
189
  // Description:
190
  // Set/Get whether polyhedra are to be decomposed.
191
  vtkSetMacro(DecomposePolyhedra, int);
192
  vtkGetMacro(DecomposePolyhedra, int);
193
  vtkBooleanMacro(DecomposePolyhedra, int);
194
195
  // Option to accumulate patches and fields across time steps
196
  // Description:
197
  // Set/Get whether the patches are listed even if size = 0
198
  vtkSetMacro(KeepPatches, int);
199
  vtkGetMacro(KeepPatches, int);
200
  vtkBooleanMacro(KeepPatches, int);
201
202
  // Option for reading old binary lagrangian/positions format
203
  // Description:
204
  // Set/Get whether the lagrangian/positions is in OF 1.3 format
205
  vtkSetMacro(PositionsIsIn13Format, int);
206
  vtkGetMacro(PositionsIsIn13Format, int);
207
  vtkBooleanMacro(PositionsIsIn13Format, int);
208
209
  // Description:
210
  // Determine if time directories are to be listed according to controlDict
211
  vtkSetMacro(ListTimeStepsByControlDict, int);
212
  vtkGetMacro(ListTimeStepsByControlDict, int);
213
  vtkBooleanMacro(ListTimeStepsByControlDict, int);
214
215
  // Description:
216
  // Add dimensions to array names
217
  vtkSetMacro(AddDimensionsToArrayNames, int);
218
  vtkGetMacro(AddDimensionsToArrayNames, int);
219
  vtkBooleanMacro(AddDimensionsToArrayNames, int);
220
221
  // Description:
222
  // Set/Get whether zones will be read.
223
  vtkSetMacro(ReadZones, int);
224
  vtkGetMacro(ReadZones, int);
225
  vtkBooleanMacro(ReadZones, int);
96
226
97
protected:
227
protected:
228
  // for creating cell-to-point translated data
229
  int CreateCellToPoint;
230
231
  // for caching mesh
232
  int CacheMesh;
233
234
  // for decomposing polyhedra on-the-fly
235
  int DecomposePolyhedra;
236
237
  // for accumulating patches across time steps
238
  int KeepPatches;
239
240
  // for reading old binary lagrangian/positions format
241
  int PositionsIsIn13Format;
242
243
  // for reading point/face/cell-Zones
244
  int ReadZones;
245
246
  // determine if time directories are listed according to controlDict
247
  int ListTimeStepsByControlDict;
248
249
  // add dimensions to array names
250
  int AddDimensionsToArrayNames;
251
98
  vtkOpenFOAMReader();
252
  vtkOpenFOAMReader();
99
  ~vtkOpenFOAMReader();
253
  ~vtkOpenFOAMReader();
100
  int RequestData(vtkInformation *,
254
  int RequestData(vtkInformation *, vtkInformationVector **,
101
    vtkInformationVector **, vtkInformationVector *);
255
    vtkInformationVector *);
102
  int RequestInformation(vtkInformation *,
256
  int RequestInformation(vtkInformation *, vtkInformationVector **,
103
    vtkInformationVector **, vtkInformationVector *);
257
    vtkInformationVector *);
104
258
105
private:
259
private:
260
  struct vtkFoamError;
261
  struct vtkFoamToken;
262
  struct vtkFoamFileStack;
263
  struct vtkFoamFile;
264
  struct vtkFoamIOobject;
265
  struct vtkFoamEntryValue;
266
  struct vtkFoamEntry;
267
  struct vtkFoamDict;
268
  struct vtkFoamBoundaryDict;
269
270
  // declared inside the vtkOpenFOAMReader class for workarounding a
271
  // bug in MSVC++
272
  struct intVectorVector;
273
106
  vtkOpenFOAMReader(const vtkOpenFOAMReader&);  // Not implemented.
274
  vtkOpenFOAMReader(const vtkOpenFOAMReader&);  // Not implemented.
107
  void operator=(const vtkOpenFOAMReader&);  // Not implemented.
275
  void operator=(const vtkOpenFOAMReader&);  // Not implemented.
108
276
109
  vtkSetVector2Macro(TimeStepRange, int);
277
  vtkSetVector2Macro(TimeStepRange, int);
110
278
111
  char * FileName;
279
  char *FileName;
112
  int NumberOfTimeSteps;
280
  int NumberOfTimeSteps;
113
  int TimeStep;
281
  int TimeStep;
114
  int TimeStepRange[2];
282
  int TimeStepRange[2];
115
  double * Steps;
283
  double *Steps;
116
  bool RequestInformationFlag;
284
  int ListTimeStepsByControlDictOld;
117
  int StartFace;
285
118
286
  // Selection Observer for translating GUI Changes to Mesh Updates
119
  stdString * Path;
287
  vtkCallbackCommand *SelectionObserver;
120
  stdString * PathPrefix;
288
121
  stringVector * TimeStepData;
289
  // DataArraySelection for Patch / Region Data
122
  vtkDataArraySelection * CellDataArraySelection;
290
  vtkDataArraySelection *PatchDataArraySelection;
123
  intVectorVector * FacePoints;
291
  vtkDataArraySelection *CellDataArraySelection;
124
  intVectorVector * FacesOwnerCell;
292
  vtkDataArraySelection *PointDataArraySelection;
125
  intVectorVector * FacesNeighborCell;
293
  vtkDataArraySelection *LagrangianDataArraySelection;
126
  faceVectorVector * FacesOfCell;
294
127
  vtkPoints * Points;
295
  // Previous and Current Status of each of the selection arrays (in
296
  // Bitwise form). Maximum 31 patches or fields support as of now
297
  // (since we use LSB for overflow handling)
298
  unsigned long CellSelectionOldStatus;
299
  unsigned long PointSelectionOldStatus;
300
  unsigned long LagrangianSelectionOldStatus;
301
  unsigned long PatchSelectionOldStatus;
302
  unsigned long CellSelectionStatus;
303
  unsigned long PointSelectionStatus;
304
  unsigned long LagrangianSelectionStatus;
305
  unsigned long PatchSelectionStatus;
306
  int ReadZonesOld;
307
308
  // filenames / directories
309
  vtkStdString *OldFileName;
310
  vtkStdString *PathPrefix;
311
  vtkStringArray *TimeNames;
312
  vtkStringArray *VolFieldFiles;
313
  vtkStringArray *PointFieldFiles;
314
  vtkStringArray *LagrangianPaths;
315
  vtkStringArray *LagrangianFieldFiles;
316
  vtkStringArray *PolyMeshPointsDir;
317
  vtkStringArray *PolyMeshFacesDir;
318
319
  // for mesh construction
128
  vtkIdType NumCells;
320
  vtkIdType NumCells;
129
  vtkIdType NumFaces;
130
  vtkIntArray * FaceOwner;
131
  //vtkIntArray * FaceNeighbor;
132
  stringVector * PolyMeshPointsDir;
133
  stringVector * PolyMeshFacesDir;
134
  vtkIdType NumPoints;
321
  vtkIdType NumPoints;
135
  intVector * SizeOfBoundary;
322
  vtkIntArray *FaceOwner;
136
  stringVector * BoundaryNames;
323
137
  stringVector * PointZoneNames;
324
  // for cell-to-point interpolation
138
  stringVector * FaceZoneNames;
325
  vtkUnstructuredGrid *AllBoundaries;
139
  stringVector * CellZoneNames;
326
  vtkIntArray *AllBoundariesPointMap;
140
  int NumBlocks;
327
  vtkIntArray *InternalPoints;
141
328
  int CreateCellToPointOld;
142
  void CombineOwnerNeigbor();
329
143
  vtkUnstructuredGrid * MakeInternalMesh();
330
  // for caching mesh
144
  double ControlDictDataParser(const char *);
331
  vtkUnstructuredGrid *InternalMesh;
145
  void ReadControlDict ();
332
  unstructuredGridVector *BoundaryMesh;
146
  void GetPoints (int);
333
  intArrayVector *BoundaryPointMap;
147
  void ReadFacesFile (const char *);
334
  vtkFoamBoundaryDict *BoundaryDict;
148
  void ReadOwnerFile(const char *);
335
  unstructuredGridVector *PointZoneMesh;
149
  void ReadNeighborFile(const char *);
336
  unstructuredGridVector *FaceZoneMesh;
337
  unstructuredGridVector *CellZoneMesh;
338
  int TimeStepOld;
339
340
  // for polyhedra handling
341
  vtkIntArray *AdditionalCellIds;
342
  intArrayVector *AdditionalCellPoints;
343
  int DecomposePolyhedraOld;
344
345
  // for accumulating patches across time steps
346
  int KeepPatchesOld;
347
348
  // for reading old binary lagrangian/positions format
349
  int PositionsIsIn13FormatOld;
350
351
  // for addiing dimensions to array names
352
  int AddDimensionsToArrayNamesOld;
353
354
  // member functions
355
  void ClearInternalMeshes();
356
  void ClearBoundaryMeshes();
357
  void ClearMeshes();
358
359
  // Calculate selection status variables
360
  unsigned long CreateSelectionStatus(vtkDataArraySelection *, unsigned long);
361
362
  // search time directories for mesh
363
  void AppendMeshDirToArray(vtkStringArray *, const char *, const int);
150
  void PopulatePolyMeshDirArrays();
364
  void PopulatePolyMeshDirArrays();
151
  const char * GetDataType(const char *, const char *);
365
152
  vtkDoubleArray * GetInternalVariableAtTimestep(const char *, int);
366
  // search a time directory for field objects
153
  vtkDoubleArray * GetBoundaryVariableAtTimestep(int, const char *, int,
367
  void GetFieldNames(const char *, const bool, vtkStringArray *,
154
                                                 vtkUnstructuredGrid *);
368
    vtkStringArray *);
155
  stringVector *GatherBlocks(const char *, int);
369
  void LocateLagrangianClouds(vtkStringArray *, const vtkStdString &);
156
  vtkUnstructuredGrid * GetBoundaryMesh(int, int);
370
  int MakeTimeStepData(const bool);
157
  vtkUnstructuredGrid * GetPointZoneMesh(int, int);
371
158
  vtkUnstructuredGrid * GetFaceZoneMesh(int, int);
372
  // read controlDict
159
  vtkUnstructuredGrid * GetCellZoneMesh(int, int);
373
  bool ListTimeDirectoriesByControlDict(vtkFoamDict *dict);
160
  void CreateDataSet(vtkMultiBlockDataSet *);
374
  bool ListTimeDirectoriesByInstances();
161
  stdString * GetLine(ifstream *);
375
  bool ReadControlDict(const char *);
376
377
  // read mesh files
378
  vtkFloatArray* ReadPointsFile(int);
379
  intVectorVector* ReadFacesFile (const char *);
380
  bool ReadOwnerNeighborFiles(vtkIntArray *, vtkIntArray *, const char *,
381
    const char *);
382
383
  // create mesh
384
  void InsertCellsToGrid(vtkUnstructuredGrid *, vtkIntArray *, vtkIntArray *,
385
    const intVectorVector *, vtkFloatArray *, vtkIdTypeArray *,
386
    vtkIntArray *);
387
  vtkUnstructuredGrid *MakeInternalMesh(vtkIntArray *, vtkIntArray *,
388
    const intVectorVector *, vtkFloatArray *);
389
  void InsertFacesToGrid(vtkUnstructuredGrid *, const intVectorVector *,
390
    int, int, vtkIntArray *, vtkIdList *, vtkIntArray *, const bool);
391
  unstructuredGridVector* MakeBoundaryMesh(vtkFoamBoundaryDict *,
392
    const intVectorVector *, vtkFloatArray *);
393
  void SetDataObjectName(vtkDataObject *, const char *);
394
#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3
395
  void SetBlockName(vtkMultiBlockDataSet *, unsigned int, const char *);
396
  void SetBlockName(vtkMultiBlockDataSet *, unsigned int, vtkDataObject *);
397
#endif
398
  void TruncateFaceOwner();
399
400
  // move additional points for decomposed cells
401
  vtkPoints *MoveInternalMesh(vtkUnstructuredGrid *, vtkFloatArray *);
402
  void MoveBoundaryMesh(unstructuredGridVector *, vtkFloatArray *);
403
404
  // cell-to-point interpolator
405
  void InterpolateCellToPoint(vtkFloatArray *, vtkFloatArray *,
406
    vtkUnstructuredGrid *, vtkIntArray *, const int);
407
408
  // read and create cell/point fields
409
  void ConstructDimensions(vtkStdString *, vtkFoamDict *);
410
  bool ReadFieldFile(vtkFoamIOobject *, vtkFoamDict *, const char *, int,
411
    vtkDataArraySelection *);
412
  vtkFloatArray *FillField(vtkFoamEntry *, int, vtkFoamIOobject *,
413
    const vtkStdString *);
414
  void GetVolFieldAtTimestep(vtkUnstructuredGrid *, unstructuredGridVector *,
415
    vtkFoamBoundaryDict *, const char *, int);
416
  void GetPointFieldAtTimestep(vtkUnstructuredGrid *, unstructuredGridVector *,
417
    vtkFoamBoundaryDict *, const char *, int);
418
  void AddArrayToFieldData(vtkDataSetAttributes *, vtkDataArray *,
419
    const vtkStdString &);
420
421
  // create lagrangian mesh/fields
422
  vtkPolyData *MakeLagrangianMesh(int, const vtkStdString &);
423
  void GetLagrangianFieldAtTimestep(vtkPolyData *, const char *, int,
424
    const vtkStdString &);
425
426
  // create point/face/cell zones
427
  vtkFoamDict *GatherBlocks(const char *, int, bool);
428
  bool GetPointZoneMesh(unstructuredGridVector *, vtkPoints *, int);
429
  bool GetFaceZoneMesh(unstructuredGridVector *, const intVectorVector *,
430
    vtkPoints *, int);
431
  bool GetCellZoneMesh(unstructuredGridVector *, vtkIntArray *, vtkIntArray *,
432
    const intVectorVector *, vtkPoints *, int);
433
434
  // read mesh/fields and create dataset
435
  int CreateDataSet(vtkMultiBlockDataSet *, int);
162
};
436
};
163
437
164
#endif
438
#endif
(-)ParaView3/Servers/ServerManager/Resources/readers.xml.orig (-57 / +195 lines)
Lines 3806-3870 Link Here
3806
   </SourceProxy>
3806
   </SourceProxy>
3807
3807
3808
    <!-- Beginning of FOAM Reader -->
3808
    <!-- Beginning of FOAM Reader -->
3809
    <SourceProxy name="OpenFOAMReader" 
3809
    <SourceProxy
3810
                    class="vtkOpenFOAMReader">
3810
3811
      <StringVectorProperty name="FileName"
3811
        name="OpenFOAMReader" 
3812
                            command="SetFileName"
3812
        class="vtkOpenFOAMReader"
3813
                            animateable="0"
3813
	output="vtkDataSet">
3814
                            number_of_elements="1">
3814
3815
        <FileListDomain name="files"/>
3815
       <StringVectorProperty
3816
        <Documentation>
3816
           name="FileName"
3817
          Set the file name for the OpenFOAM reader.
3817
           command="SetFileName"
3818
        </Documentation>
3818
           number_of_elements="1">
3819
      </StringVectorProperty>
3819
           <FileListDomain name="files"/>
3820
      <StringVectorProperty name="CellArrayInfo"
3820
        </StringVectorProperty>
3821
                            information_only="1">
3821
3822
        <ArraySelectionInformationHelper attribute_name="Cell"/>
3822
	<IntVectorProperty 
3823
      </StringVectorProperty>
3823
           name="CreateCellToPoint" 
3824
      <StringVectorProperty name="CellArrayStatus"
3824
           command="SetCreateCellToPoint" 
3825
                            command="SetCellArrayStatus"
3825
           number_of_elements="1"
3826
                            number_of_elements="0" 
3826
           default_values="1"
3827
                            repeat_command="1"
3827
	   label="Create cell-to-point filtered data">
3828
                            number_of_elements_per_command="2"
3828
           <BooleanDomain name="bool"/>
3829
                            element_types="2 0" 
3829
                <Documentation>
3830
                            information_property="CellArrayInfo"
3830
                   Create cell-to-point filtered data.
3831
                            label="Cell Arrays">
3831
                </Documentation>
3832
        <ArraySelectionDomain name="array_list">
3832
        </IntVectorProperty>
3833
          <RequiredProperties>
3833
3834
            <Property name="CellArrayInfo" function="ArrayList"/>
3834
        <IntVectorProperty name="AddDimensionsToArrayNames" 
3835
          </RequiredProperties>
3835
                           command="SetAddDimensionsToArrayNames"
3836
        </ArraySelectionDomain>
3837
        <Documentation>
3838
          Select which cell-centered arrays to read.
3839
        </Documentation>
3840
      </StringVectorProperty>
3841
      <IntVectorProperty name="TimeStepRangeInfo"
3842
                         command="GetTimeStepRange"
3843
                         information_only="1">
3844
        <SimpleIntInformationHelper/>
3845
      </IntVectorProperty>
3846
      <IntVectorProperty name="TimeStep"
3847
                           command="SetTimeStep"
3848
                           number_of_elements="1"
3836
                           number_of_elements="1"
3849
                           animateable="1"
3837
                           default_values="0"
3850
                           default_values="0">
3838
                           label="Add dimensional units to array names">
3851
        <IntRangeDomain name="range">
3839
          <BooleanDomain name="bool"/>
3852
          <RequiredProperties>
3840
          <Documentation>
3853
            <Property name="TimeStepRangeInfo" function="Range"/>
3841
            Read dimensional units from field data and add them to array names as human-understandable string.
3854
          </RequiredProperties>
3842
          </Documentation>
3855
        </IntRangeDomain>
3843
        </IntVectorProperty>
3856
        <Documentation>
3844
3857
          Set the current timestep.
3845
	<DoubleVectorProperty
3858
        </Documentation>
3846
           name="TimestepValues"
3859
      </IntVectorProperty>
3847
	   repeatable="1"
3860
      <DoubleVectorProperty 
3848
	   information_only="1">
3861
          name="TimestepValues"
3849
           <TimeStepsInformationHelper/>
3862
          repeatable="1"
3850
        </DoubleVectorProperty>
3863
          information_only="1">
3851
3864
        <TimeStepsInformationHelper/>
3852
	<StringVectorProperty 
3865
      </DoubleVectorProperty>
3853
            name="PatchArrayInfo"
3854
            information_only="1">
3855
            <ArraySelectionInformationHelper attribute_name="Patch"/>
3856
	</StringVectorProperty>
3857
	<StringVectorProperty
3858
            name="MeshRegions"
3859
            command="SetPatchArrayStatus"
3860
            number_of_elements="0" 
3861
            repeat_command="1"
3862
            number_of_elements_per_command="2"
3863
            element_types="2 0"
3864
            information_property="PatchArrayInfo">
3865
            <ArraySelectionDomain name="array_list">
3866
                <RequiredProperties>
3867
                    <Property name="PatchArrayInfo"
3868
                        function="ArrayList"/>
3869
                    </RequiredProperties>
3870
            </ArraySelectionDomain>
3871
        </StringVectorProperty>
3872
	
3873
        <StringVectorProperty 
3874
            name="CellArrayInfo"
3875
            information_only="1">
3876
            <ArraySelectionInformationHelper attribute_name="Cell"/>
3877
        </StringVectorProperty>
3878
        <StringVectorProperty
3879
            name="CellArrays"
3880
            command="SetCellArrayStatus"
3881
            number_of_elements="0" 
3882
            repeat_command="1"
3883
            number_of_elements_per_command="2"
3884
            element_types="2 0"
3885
    	    information_property="CellArrayInfo">
3886
            <ArraySelectionDomain name="array_list">
3887
                <RequiredProperties>
3888
                    <Property name="CellArrayInfo"
3889
                        function="ArrayList"/>
3890
                </RequiredProperties>
3891
            </ArraySelectionDomain>
3892
        </StringVectorProperty>
3893
3894
        <StringVectorProperty 
3895
            name="PointArrayInfo"
3896
            information_only="1">
3897
            <ArraySelectionInformationHelper attribute_name="Point"/>
3898
        </StringVectorProperty>
3899
        <StringVectorProperty
3900
            name="PointArrays"
3901
            command="SetPointArrayStatus"
3902
            number_of_elements="0" 
3903
            repeat_command="1"
3904
            number_of_elements_per_command="2"
3905
            element_types="2 0"
3906
	        information_property="PointArrayInfo">
3907
            <ArraySelectionDomain name="array_list">
3908
                <RequiredProperties>
3909
                    <Property name="PointArrayInfo"
3910
                        function="ArrayList"/>
3911
                </RequiredProperties>
3912
            </ArraySelectionDomain>
3913
        </StringVectorProperty>
3914
3915
        <StringVectorProperty 
3916
            name="LagrangianArrayInfo"
3917
            information_only="1">
3918
            <ArraySelectionInformationHelper attribute_name="Lagrangian"/>
3919
        </StringVectorProperty>
3920
        <StringVectorProperty
3921
            name="LagrangianArrays"
3922
            command="SetLagrangianArrayStatus"
3923
            number_of_elements="0" 
3924
            repeat_command="1"
3925
            number_of_elements_per_command="2"
3926
            element_types="2 0"
3927
	        information_property="LagrangianArrayInfo">
3928
            <ArraySelectionDomain name="array_list">
3929
                <RequiredProperties>
3930
                    <Property name="LagrangianArrayInfo"
3931
                        function="ArrayList"/>
3932
                </RequiredProperties>
3933
            </ArraySelectionDomain>
3934
        </StringVectorProperty>
3935
3936
	<IntVectorProperty 
3937
           name="CacheMesh" 
3938
           command="SetCacheMesh" 
3939
           number_of_elements="1"
3940
           default_values="1"
3941
	   label="Cache mesh">
3942
           <BooleanDomain name="bool"/>
3943
                <Documentation>
3944
                   Cache the OpenFOAM mesh between GUI selection changes.
3945
                </Documentation>
3946
        </IntVectorProperty>
3947
3948
	<IntVectorProperty 
3949
           name="DecomposePolyhedra" 
3950
           command="SetDecomposePolyhedra" 
3951
           number_of_elements="1"
3952
           default_values="1"
3953
	   label="Decompose polyhedra">
3954
           <BooleanDomain name="bool"/>
3955
                <Documentation>
3956
                   Decompose polyhedra into tetrahedra and pyramids.
3957
                </Documentation>
3958
        </IntVectorProperty>
3959
3960
        <IntVectorProperty name="ListTimeStepsByControlDict" 
3961
                           command="SetListTimeStepsByControlDict"
3962
                           number_of_elements="1" 
3963
                           default_values="0"
3964
                           label="List timesteps according to controlDict">
3965
          <BooleanDomain name="bool"/>
3966
          <Documentation>
3967
            Determine if time directories are to be listed according to the description in controlDict.
3968
          </Documentation>
3969
        </IntVectorProperty>
3970
3971
	<IntVectorProperty name="AccumulatePatches" 
3972
			   command="SetKeepPatches"
3973
			   number_of_elements="1" 
3974
			   default_values="1"
3975
			   label="Accumulate patches to selection list">
3976
	  <BooleanDomain name="bool"/>
3977
	  <Documentation>
3978
	    Accumulate patches into selection list across time-steps even if they stop existing.
3979
	  </Documentation>
3980
	</IntVectorProperty>
3981
3982
	<IntVectorProperty name="PositionsIsIn13Format" 
3983
			   command="SetPositionsIsIn13Format"
3984
			   number_of_elements="1" 
3985
			   default_values="0"
3986
			   label="Lagrangian positions are in OF 1.3 binary format">
3987
	  <BooleanDomain name="bool"/>
3988
	  <Documentation>
3989
	    Set if Lagrangian positions files are in OpenFOAM 1.3 binary format.
3990
	  </Documentation>
3991
	</IntVectorProperty>
3992
3993
        <IntVectorProperty name="ReadZones" 
3994
                           command="SetReadZones"
3995
                           number_of_elements="1" 
3996
                           default_values="0"
3997
                           label="Read zones">
3998
          <BooleanDomain name="bool"/>
3999
          <Documentation>
4000
            Read point/face/cell-Zones?
4001
          </Documentation>
4002
        </IntVectorProperty>
4003
3866
    </SourceProxy>
4004
    </SourceProxy>
3867
    <!-- End of foam Reader -->
4005
    <!-- End of FOAM Reader -->
3868
4006
3869
    <!-- Beginning of MFIX Reader -->
4007
    <!-- Beginning of MFIX Reader -->
3870
    <SourceProxy name="MFIXReader" class="vtkMFIXReader">
4008
    <SourceProxy name="MFIXReader" class="vtkMFIXReader">

Return to bug 233191