vtkOpenFOAMReader.cxx 290 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOpenFOAMReader.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
15
// Thanks to Terry Jordan of SAIC at the National Energy
16 17 18
// Technology Laboratory who developed this class.
// Please address all comments to Terry Jordan (terry.jordan@sa.netl.doe.gov)
//
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
// Token-based FoamFile format lexer/parser,
// performance/stability/compatibility enhancements, gzipped file
// support, lagrangian field support, variable timestep support,
// builtin cell-to-point filter, pointField support, polyhedron
// decomposition support, OF 1.5 extended format support, multiregion
// support, old mesh format support, parallelization support for
// decomposed cases in conjunction with vtkPOpenFOAMReader, et. al. by
// Takuya Oshima of Niigata University, Japan (oshima@eng.niigata-u.ac.jp)
//
// * GUI Based selection of mesh regions and fields available in the case
// * Minor bug fixes / Strict memory allocation checks
// * Minor performance enhancements
// by Philippose Rajan (sarith@rocketmail.com)

// Hijack the CRC routine of zlib to omit CRC check for gzipped files
// (on OSes other than Windows where the mechanism doesn't work due
// to pre-bound DLL symbols) if set to 1, or not (set to 0). Affects
// performance by about 3% - 4%.
#define VTK_FOAMFILE_OMIT_CRCCHECK 0

// The input/output buffer sizes for zlib in bytes.
#define VTK_FOAMFILE_INBUFSIZE (16384)
#define VTK_FOAMFILE_OUTBUFSIZE (131072)
#define VTK_FOAMFILE_INCLUDE_STACK_SIZE (10)

44
#if defined(_MSC_VER)
45
#define _CRT_SECURE_NO_WARNINGS 1
46 47
// No strtoll on msvc:
#define strtoll _strtoi64
48 49 50 51 52 53 54 55 56
#endif

#if VTK_FOAMFILE_OMIT_CRCCHECK
#define ZLIB_INTERNAL
#endif

// for possible future extension of linehead-aware directives
#define VTK_FOAMFILE_RECOGNIZE_LINEHEAD 0

57 58
#include "vtkOpenFOAMReader.h"

59
#include "vtk_zlib.h"
60
#include "vtksys/RegularExpression.hxx"
61
#include "vtksys/SystemTools.hxx"
62
#include <sstream>
63
#include <vector>
64

65
#include "vtkAssume.h"
66
#include "vtkCellArray.h"
67 68 69 70
#include "vtkCellData.h"
#include "vtkCharArray.h"
#include "vtkCollection.h"
#include "vtkConvexPointSet.h"
71
#include "vtkDataArraySelection.h"
72
#include "vtkDirectory.h"
73
#include "vtkDoubleArray.h"
74
#include "vtkFloatArray.h"
75
#include "vtkHexahedron.h"
76 77 78 79 80 81 82 83 84
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkIntArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkPolygon.h"
85
#include "vtkPyramid.h"
86 87 88 89 90
#include "vtkQuad.h"
#include "vtkSortDataArray.h"
#include "vtkStdString.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkStringArray.h"
91 92
#include "vtkTetra.h"
#include "vtkTriangle.h"
93 94
#include "vtkTypeInt32Array.h"
#include "vtkTypeInt64Array.h"
95
#include "vtkTypeTraits.h"
96
#include "vtkUnstructuredGrid.h"
97 98
#include "vtkVertex.h"
#include "vtkWedge.h"
99

100 101 102
#if !(defined(_WIN32) && !defined(__CYGWIN__) || defined(__LIBCATAMOUNT__))
// for getpwnam() / getpwuid()
#include <pwd.h>
103
#include <sys/types.h>
104 105 106 107
// for getuid()
#include <unistd.h>
#endif
// for fabs()
108
#include <cmath>
109
// for isalnum() / isspace() / isdigit()
110
#include <cctype>
111

112
#include <typeinfo>
113 114
#include <vector>

115
#if VTK_FOAMFILE_OMIT_CRCCHECK
116 117 118 119
uLong ZEXPORT crc32(uLong, const Bytef*, uInt)
{
  return 0;
}
120
#endif
121 122 123

vtkStandardNewMacro(vtkOpenFOAMReader);

124 125
namespace
{
126 127 128 129

// Given a data array and a flag indicating whether 64 bit labels are used,
// lookup and return a single element in the array. The data array must
// be either a vtkTypeInt32Array or vtkTypeInt64Array.
130
vtkTypeInt64 GetLabelValue(vtkDataArray* array, vtkIdType idx, bool use64BitLabels)
131 132
{
  if (!use64BitLabels)
133
  {
134 135
    vtkTypeInt64 result =
      static_cast<vtkTypeInt64>(static_cast<vtkTypeInt32Array*>(array)->GetValue(idx));
136 137
    assert(result >= -1); // some arrays store -1 == 'uninitialized'.
    return result;
138
  }
139
  else
140
  {
141 142 143
    vtkTypeInt64 result = static_cast<vtkTypeInt64Array*>(array)->GetValue(idx);
    assert(result >= -1); // some arrays store -1 == 'uninitialized'.
    return result;
144
  }
145 146 147
}

// Setter analogous to the above getter.
148
void SetLabelValue(vtkDataArray* array, vtkIdType idx, vtkTypeInt64 value, bool use64BitLabels)
149 150
{
  if (!use64BitLabels)
151
  {
152
    assert(static_cast<vtkTypeInt32>(value) >= 0);
153
    static_cast<vtkTypeInt32Array*>(array)->SetValue(idx, static_cast<vtkTypeInt32>(value));
154
  }
155
  else
156
  {
157 158
    assert(value >= 0);
    static_cast<vtkTypeInt64Array*>(array)->SetValue(idx, value);
159
  }
160 161 162
}

// Similar to above, but increments the specified value by one.
163
void IncrementLabelValue(vtkDataArray* array, vtkIdType idx, bool use64BitLabels)
164 165
{
  if (!use64BitLabels)
166
  {
167 168 169
    vtkTypeInt32 val = static_cast<vtkTypeInt32Array*>(array)->GetValue(idx);
    assert(val + 1 >= 0);
    static_cast<vtkTypeInt32Array*>(array)->SetValue(idx, val + 1);
170
  }
171
  else
172
  {
173 174 175
    vtkTypeInt64 val = static_cast<vtkTypeInt64Array*>(array)->GetValue(idx);
    assert(val + 1 >= 0);
    static_cast<vtkTypeInt64Array*>(array)->SetValue(idx, val + 1);
176
  }
177 178 179
}

// Another helper for appending an id to a list
180
void AppendLabelValue(vtkDataArray* array, vtkTypeInt64 val, bool use64BitLabels)
181 182
{
  if (!use64BitLabels)
183
  {
184
    assert(static_cast<vtkTypeInt32>(val) >= 0);
185
    static_cast<vtkTypeInt32Array*>(array)->InsertNextValue(static_cast<vtkTypeInt32>(val));
186
  }
187
  else
188
  {
189 190
    assert(val >= 0);
    static_cast<vtkTypeInt64Array*>(array)->InsertNextValue(val);
191
  }
192 193 194 195
}

// Another 64/32 bit label helper. Given a void* c-array, set/get element idx.
// The array must be of vtkTypeInt32 or vtkTypeInt64.
196
void SetLabelValue(void* array, size_t idx, vtkTypeInt64 value, bool use64BitLabels)
197 198
{
  if (!use64BitLabels)
199
  {
200 201
    assert(static_cast<vtkTypeInt32>(value) >= 0);
    static_cast<vtkTypeInt32*>(array)[idx] = static_cast<vtkTypeInt32>(value);
202
  }
203
  else
204
  {
205 206
    assert(value >= 0);
    static_cast<vtkTypeInt64*>(array)[idx] = value;
207
  }
208
}
209
vtkTypeInt64 GetLabelValue(const void* array, size_t idx, bool use64BitLabels)
210 211
{
  if (!use64BitLabels)
212
  {
213
    vtkTypeInt64 result = static_cast<vtkTypeInt64>(static_cast<const vtkTypeInt32*>(array)[idx]);
214 215
    assert(result >= 0);
    return result;
216
  }
217
  else
218
  {
219 220 221
    vtkTypeInt64 result = static_cast<const vtkTypeInt64*>(array)[idx];
    assert(result >= 0);
    return result;
222
  }
223 224 225 226
}

} // end anon namespace

227
// forward declarations
228 229
template <typename T>
struct vtkFoamArrayVector : public std::vector<T*>
230
{
231
private:
232
  typedef std::vector<T*> Superclass;
233

234 235 236
public:
  ~vtkFoamArrayVector()
  {
237
    for (size_t arrayI = 0; arrayI < Superclass::size(); arrayI++)
238
    {
239
      if (Superclass::operator[](arrayI))
240
      {
241 242
        Superclass::operator[](arrayI)->Delete();
      }
243
    }
244
  }
245 246
};

247
typedef vtkFoamArrayVector<vtkDataArray> vtkFoamLabelArrayVector;
248 249
typedef vtkFoamArrayVector<vtkIntArray> vtkFoamIntArrayVector;
typedef vtkFoamArrayVector<vtkFloatArray> vtkFoamFloatArrayVector;
250 251

struct vtkFoamLabelVectorVector;
252 253
template <typename ArrayT>
struct vtkFoamLabelVectorVectorImpl;
254 255
typedef vtkFoamLabelVectorVectorImpl<vtkTypeInt32Array> vtkFoamLabel32VectorVector;
typedef vtkFoamLabelVectorVectorImpl<vtkTypeInt64Array> vtkFoamLabel64VectorVector;
256 257 258 259 260 261

struct vtkFoamError;
struct vtkFoamToken;
struct vtkFoamFileStack;
struct vtkFoamFile;
struct vtkFoamIOobject;
262 263
template <typename T>
struct vtkFoamReadValue;
264 265 266 267 268 269 270
struct vtkFoamEntryValue;
struct vtkFoamEntry;
struct vtkFoamDict;

//-----------------------------------------------------------------------------
// class vtkOpenFOAMReaderPrivate
// the reader core of vtkOpenFOAMReader
271
class vtkOpenFOAMReaderPrivate : public vtkObject
272
{
273
public:
274
  static vtkOpenFOAMReaderPrivate* New();
275
  vtkTypeMacro(vtkOpenFOAMReaderPrivate, vtkObject);
276

277
  vtkDoubleArray* GetTimeValues() { return this->TimeValues; }
278 279
  vtkGetMacro(TimeStep, int);
  vtkSetMacro(TimeStep, int);
280
  const vtkStdString& GetRegionName() const { return this->RegionName; }
281 282

  // gather timestep information
283 284
  bool MakeInformationVector(
    const vtkStdString&, const vtkStdString&, const vtkStdString&, vtkOpenFOAMReader*);
285
  // read mesh/fields and create dataset
286
  int RequestData(vtkMultiBlockDataSet*, bool, bool, bool);
287
  void SetTimeValue(const double);
288 289 290
  int MakeMetaDataAtTimeStep(vtkStringArray*, vtkStringArray*, vtkStringArray*, const bool);
  void SetupInformation(
    const vtkStdString&, const vtkStdString&, const vtkStdString&, vtkOpenFOAMReaderPrivate*);
291 292 293

private:
  struct vtkFoamBoundaryEntry
294
  {
295
    enum bt
296
    {
297 298
      PHYSICAL = 1,   // patch, wall
      PROCESSOR = 2,  // processor
299
      GEOMETRICAL = 0 // symmetryPlane, wedge, cyclic, empty, etc.
300
    };
301
    vtkStdString BoundaryName;
302
    vtkIdType NFaces, StartFace, AllBoundariesStartFace;
303 304
    bool IsActive;
    bt BoundaryType;
305
  };
306

307
  struct vtkFoamBoundaryDict : public std::vector<vtkFoamBoundaryEntry>
308
  {
309 310 311 312
    // we need to keep the path to time directory where the current mesh
    // is read from, since boundaryDict may be accessed multiple times
    // at a timestep for patch selections
    vtkStdString TimeDir;
313
  };
314

315
  vtkOpenFOAMReader* Parent;
316 317 318 319 320 321 322

  // case and region
  vtkStdString CasePath;
  vtkStdString RegionName;
  vtkStdString ProcessorName;

  // time information
323
  vtkDoubleArray* TimeValues;
324 325
  int TimeStep;
  int TimeStepOld;
326
  vtkStringArray* TimeNames;
327 328 329 330 331

  int InternalMeshSelectionStatus;
  int InternalMeshSelectionStatusOld;

  // filenames / directories
332 333 334 335 336
  vtkStringArray* VolFieldFiles;
  vtkStringArray* PointFieldFiles;
  vtkStringArray* LagrangianFieldFiles;
  vtkStringArray* PolyMeshPointsDir;
  vtkStringArray* PolyMeshFacesDir;
337 338 339 340

  // for mesh construction
  vtkIdType NumCells;
  vtkIdType NumPoints;
341
  vtkDataArray* FaceOwner;
342 343

  // for cell-to-point interpolation
344 345 346
  vtkPolyData* AllBoundaries;
  vtkDataArray* AllBoundariesPointMap;
  vtkDataArray* InternalPoints;
347 348

  // for caching mesh
349 350 351
  vtkUnstructuredGrid* InternalMesh;
  vtkMultiBlockDataSet* BoundaryMesh;
  vtkFoamLabelArrayVector* BoundaryPointMap;
352
  vtkFoamBoundaryDict BoundaryDict;
353 354 355
  vtkMultiBlockDataSet* PointZoneMesh;
  vtkMultiBlockDataSet* FaceZoneMesh;
  vtkMultiBlockDataSet* CellZoneMesh;
356 357 358

  // for polyhedra handling
  int NumTotalAdditionalCells;
359 360 361
  vtkIdTypeArray* AdditionalCellIds;
  vtkIntArray* NumAdditionalCells;
  vtkFoamLabelArrayVector* AdditionalCellPoints;
362 363 364

  // constructor and destructor are kept private
  vtkOpenFOAMReaderPrivate();
365
  ~vtkOpenFOAMReaderPrivate() override;
366

367 368
  vtkOpenFOAMReaderPrivate(const vtkOpenFOAMReaderPrivate&) = delete;
  void operator=(const vtkOpenFOAMReaderPrivate&) = delete;
369 370 371 372 373 374 375

  // clear mesh construction
  void ClearInternalMeshes();
  void ClearBoundaryMeshes();
  void ClearMeshes();

  vtkStdString RegionPath() const
376 377 378
  {
    return (this->RegionName.empty() ? "" : "/") + this->RegionName;
  }
379
  vtkStdString TimePath(const int timeI) const
380 381 382
  {
    return this->CasePath + this->TimeNames->GetValue(timeI);
  }
383
  vtkStdString TimeRegionPath(const int timeI) const
384 385 386 387 388 389 390 391 392
  {
    return this->TimePath(timeI) + this->RegionPath();
  }
  vtkStdString CurrentTimePath() const { return this->TimePath(this->TimeStep); }
  vtkStdString CurrentTimeRegionPath() const { return this->TimeRegionPath(this->TimeStep); }
  vtkStdString CurrentTimeRegionMeshPath(vtkStringArray* dir) const
  {
    return this->CasePath + dir->GetValue(this->TimeStep) + this->RegionPath() + "/polyMesh/";
  }
393
  vtkStdString RegionPrefix() const
394 395 396
  {
    return this->RegionName + (this->RegionName.empty() ? "" : "/");
  }
397 398

  // search time directories for mesh
399
  void AppendMeshDirToArray(vtkStringArray*, const vtkStdString&, const int);
400 401 402
  void PopulatePolyMeshDirArrays();

  // search a time directory for field objects
403 404 405
  void GetFieldNames(const vtkStdString&, const bool, vtkStringArray*, vtkStringArray*);
  void SortFieldFiles(vtkStringArray*, vtkStringArray*, vtkStringArray*);
  void LocateLagrangianClouds(vtkStringArray*, const vtkStdString&);
406 407

  // read controlDict
408
  bool ListTimeDirectoriesByControlDict(vtkFoamDict* dict);
409 410 411 412
  bool ListTimeDirectoriesByInstances();

  // read mesh files
  vtkFloatArray* ReadPointsFile();
413 414 415
  vtkFoamLabelVectorVector* ReadFacesFile(const vtkStdString&);
  vtkFoamLabelVectorVector* ReadOwnerNeighborFiles(const vtkStdString&, vtkFoamLabelVectorVector*);
  bool CheckFacePoints(vtkFoamLabelVectorVector*);
416 417

  // create mesh
418 419 420 421 422 423 424 425 426 427
  void InsertCellsToGrid(vtkUnstructuredGrid*, const vtkFoamLabelVectorVector*,
    const vtkFoamLabelVectorVector*, vtkFloatArray*, vtkIdTypeArray*, vtkDataArray*);
  vtkUnstructuredGrid* MakeInternalMesh(
    const vtkFoamLabelVectorVector*, const vtkFoamLabelVectorVector*, vtkFloatArray*);
  void InsertFacesToGrid(vtkPolyData*, const vtkFoamLabelVectorVector*, vtkIdType, vtkIdType,
    vtkDataArray*, vtkIdList*, vtkDataArray*, const bool);
  template <typename T1, typename T2>
  bool ExtendArray(T1*, vtkIdType);
  vtkMultiBlockDataSet* MakeBoundaryMesh(const vtkFoamLabelVectorVector*, vtkFloatArray*);
  void SetBlockName(vtkMultiBlockDataSet*, unsigned int, const char*);
428 429 430
  void TruncateFaceOwner();

  // move additional points for decomposed cells
431 432
  vtkPoints* MoveInternalMesh(vtkUnstructuredGrid*, vtkFloatArray*);
  void MoveBoundaryMesh(vtkMultiBlockDataSet*, vtkFloatArray*);
433 434

  // cell-to-point interpolator
435 436
  void InterpolateCellToPoint(
    vtkFloatArray*, vtkFloatArray*, vtkPointSet*, vtkDataArray*, vtkTypeInt64);
437 438

  // read and create cell/point fields
439 440 441 442 443 444
  void ConstructDimensions(vtkStdString*, vtkFoamDict*);
  bool ReadFieldFile(vtkFoamIOobject*, vtkFoamDict*, const vtkStdString&, vtkDataArraySelection*);
  vtkFloatArray* FillField(vtkFoamEntry*, vtkIdType, vtkFoamIOobject*, const vtkStdString&);
  void GetVolFieldAtTimeStep(vtkUnstructuredGrid*, vtkMultiBlockDataSet*, const vtkStdString&);
  void GetPointFieldAtTimeStep(vtkUnstructuredGrid*, vtkMultiBlockDataSet*, const vtkStdString&);
  void AddArrayToFieldData(vtkDataSetAttributes*, vtkDataArray*, const vtkStdString&);
445 446

  // create lagrangian mesh/fields
447
  vtkMultiBlockDataSet* MakeLagrangianMesh();
448 449

  // create point/face/cell zones
450 451 452 453 454
  vtkFoamDict* GatherBlocks(const char*, bool);
  bool GetPointZoneMesh(vtkMultiBlockDataSet*, vtkPoints*);
  bool GetFaceZoneMesh(vtkMultiBlockDataSet*, const vtkFoamLabelVectorVector*, vtkPoints*);
  bool GetCellZoneMesh(vtkMultiBlockDataSet*, const vtkFoamLabelVectorVector*,
    const vtkFoamLabelVectorVector*, vtkPoints*);
455
};
456

457
vtkStandardNewMacro(vtkOpenFOAMReaderPrivate);
458

459
//-----------------------------------------------------------------------------
460 461 462 463 464
// struct vtkFoamLabelVectorVector
struct vtkFoamLabelVectorVector
{
  typedef std::vector<vtkTypeInt64> CellType;

465
  virtual ~vtkFoamLabelVectorVector() = default;
466 467 468 469 470 471 472 473
  virtual size_t GetLabelSize() const = 0; // in bytes
  virtual void ResizeBody(vtkIdType bodyLength) = 0;
  virtual void* WritePointer(vtkIdType i, vtkIdType bodyI, vtkIdType number) = 0;
  virtual void SetIndex(vtkIdType i, vtkIdType bodyI) = 0;
  virtual void SetValue(vtkIdType bodyI, vtkTypeInt64 value) = 0;
  virtual void InsertValue(vtkIdType bodyI, vtkTypeInt64 value) = 0;
  virtual const void* operator[](vtkIdType i) const = 0;
  virtual vtkIdType GetSize(vtkIdType i) const = 0;
474 475
  virtual void GetCell(vtkIdType i, CellType& cell) const = 0;
  virtual void SetCell(vtkIdType i, const CellType& cell) = 0;
476 477 478 479
  virtual vtkIdType GetNumberOfElements() const = 0;
  virtual vtkDataArray* GetIndices() = 0;
  virtual vtkDataArray* GetBody() = 0;

480
  bool Is64Bit() const { return this->GetLabelSize() == 8; }
481 482 483 484
};

template <typename ArrayT>
struct vtkFoamLabelVectorVectorImpl : public vtkFoamLabelVectorVector
485
{
486
private:
487 488
  ArrayT* Indices;
  ArrayT* Body;
489 490

public:
491 492 493
  typedef ArrayT LabelArrayType;
  typedef typename ArrayT::ValueType LabelType;

494
  ~vtkFoamLabelVectorVectorImpl() override
495 496 497 498 499
  {
    this->Indices->Delete();
    this->Body->Delete();
  }

500
  // Construct from base class:
501 502 503
  vtkFoamLabelVectorVectorImpl(const vtkFoamLabelVectorVector& ivv)
    : Indices(nullptr)
    , Body(nullptr)
504
  {
505 506
    assert(
      "LabelVectorVectors use the same label width." && this->GetLabelSize() == ivv.GetLabelSize());
507 508

    typedef vtkFoamLabelVectorVectorImpl<LabelArrayType> ThisType;
509
    const ThisType& ivvCast = static_cast<const ThisType&>(ivv);
510 511 512

    this->Indices = ivvCast.Indices;
    this->Body = ivvCast.Body;
513 514
    this->Indices->Register(nullptr); // ref count the copy
    this->Body->Register(nullptr);
515 516
  }

517 518 519
  vtkFoamLabelVectorVectorImpl(const vtkFoamLabelVectorVectorImpl<ArrayT>& ivv)
    : Indices(ivv.Indices)
    , Body(ivv.Body)
520
  {
521
    this->Indices->Register(0); // ref count the copy
522 523
    this->Body->Register(0);
  }
524

525 526 527
  vtkFoamLabelVectorVectorImpl()
    : Indices(LabelArrayType::New())
    , Body(LabelArrayType::New())
528 529
  {
  }
530

531 532 533
  vtkFoamLabelVectorVectorImpl(vtkIdType nElements, vtkIdType bodyLength)
    : Indices(LabelArrayType::New())
    , Body(LabelArrayType::New())
534 535 536 537 538
  {
    this->Indices->SetNumberOfValues(nElements + 1);
    this->Body->SetNumberOfValues(bodyLength);
  }

539
  size_t GetLabelSize() const override { return sizeof(LabelType); }
540

541
  // note that vtkIntArray::Resize() allocates (current size + new
542 543
  // size) bytes if current size < new size until 2010-06-27
  // cf. commit c869c3d5875f503e757b64f2fd1ec349aee859bf
544
  void ResizeBody(vtkIdType bodyLength) override { this->Body->Resize(bodyLength); }
545

546
  void* WritePointer(vtkIdType i, vtkIdType bodyI, vtkIdType number) override
547
  {
548
    return this->Body->WritePointer(*this->Indices->GetPointer(i) = bodyI, number);
549
  }
550

551
  void SetIndex(vtkIdType i, vtkIdType bodyI) override
552
  {
553
    this->Indices->SetValue(i, static_cast<LabelType>(bodyI));
554
  }
555

556
  void SetValue(vtkIdType bodyI, vtkTypeInt64 value) override
557
  {
558
    this->Body->SetValue(bodyI, static_cast<LabelType>(value));
559
  }
560

561
  void InsertValue(vtkIdType bodyI, vtkTypeInt64 value) override
562 563 564
  {
    this->Body->InsertValue(bodyI, value);
  }
565

566
  const void* operator[](vtkIdType i) const override
567 568 569
  {
    return this->Body->GetPointer(this->Indices->GetValue(i));
  }
570

571
  vtkIdType GetSize(vtkIdType i) const override
572 573 574
  {
    return this->Indices->GetValue(i + 1) - this->Indices->GetValue(i);
  }
575

576
  void GetCell(vtkIdType cellId, CellType& cell) const override
577
  {
578 579
    LabelType cellStart = this->Indices->GetValue(cellId);
    LabelType cellSize = this->Indices->GetValue(cellId + 1) - cellStart;
580 581
    cell.resize(cellSize);
    for (vtkIdType i = 0; i < cellSize; ++i)
582
    {
583
      cell[i] = this->Body->GetValue(cellStart + i);
584
    }
585 586
  }

587
  void SetCell(vtkIdType cellId, const CellType& cell) override
588
  {
589 590
    LabelType cellStart = this->Indices->GetValue(cellId);
    LabelType cellSize = this->Indices->GetValue(cellId + 1) - cellStart;
591
    for (vtkIdType i = 0; i < cellSize; ++i)
592
    {
593
      this->Body->SetValue(cellStart + i, cell[i]);
594
    }
595 596
  }

597
  vtkIdType GetNumberOfElements() const override { return this->Indices->GetNumberOfTuples() - 1; }
598

599
  vtkDataArray* GetIndices() override { return this->Indices; }
600

601
  vtkDataArray* GetBody() override { return this->Body; }
602 603
};

604 605 606 607
//-----------------------------------------------------------------------------
// class vtkFoamError
// class for exception-carrying object
struct vtkFoamError : public vtkStdString
608
{
609 610 611 612 613
private:
  typedef vtkStdString Superclass;

public:
  // a super-easy way to make use of operator<<()'s defined in
614
  // std::ostringstream class
615 616
  template <class T>
  vtkFoamError& operator<<(const T& t)
617
  {
618
    std::ostringstream os;
619 620 621 622 623
    os << t;
    this->Superclass::operator+=(os.str());
    return *this;
  }
};
624

625 626 627 628 629 630 631
//-----------------------------------------------------------------------------
// class vtkFoamToken
// token class which also works as container for list types
// - a word token is treated as a string token for simplicity
// - handles only atomic types. Handling of list types are left to the
//   derived classes.
struct vtkFoamToken
632
{
633 634
public:
  enum tokenType
635
  {
636 637 638
    // undefined type
    UNDEFINED,
    // atomic types
639 640 641 642 643
    PUNCTUATION,
    LABEL,
    SCALAR,
    STRING,
    IDENTIFIER,
644
    // vtkObject-derived list types
645 646 647 648
    STRINGLIST,
    LABELLIST,
    SCALARLIST,
    VECTORLIST,
649
    // original list types
650 651 652 653 654
    LABELLISTLIST,
    ENTRYVALUELIST,
    BOOLLIST,
    EMPTYLIST,
    DICTIONARY,
655 656
    // error state
    TOKEN_ERROR
657
  };
658

659 660
  // Bitwidth of labels.
  enum labelType
661
  {
662 663 664
    NO_LABEL_TYPE = 0, // Used for assertions.
    INT32,
    INT64
665
  };
666

667 668
protected:
  tokenType Type;
669
  labelType LabelType;
670
  union {
671
    char Char;
672
    vtkTypeInt64 Int;
673 674
    double Double;
    vtkStdString* String;
675
    vtkObjectBase* VtkObjectPtr;
676
    // vtkObject-derived list types
677
    vtkDataArray* LabelListPtr;
678
    vtkFloatArray *ScalarListPtr, *VectorListPtr;
679
    vtkStringArray* StringListPtr;
680
    // original list types
681 682 683
    vtkFoamLabelVectorVector* LabelListListPtr;
    std::vector<vtkFoamEntryValue*>* EntryValuePtrs;
    vtkFoamDict* DictPtr;
684 685 686 687 688
  };

  void Clear()
  {
    if (this->Type == STRING || this->Type == IDENTIFIER)
689
    {
690
      delete this->String;
691
    }
692
  }
693

694 695 696
  void AssignData(const vtkFoamToken& value)
  {
    switch (value.Type)
697
    {
698 699 700 701 702 703 704 705 706 707 708 709 710
      case PUNCTUATION:
        this->Char = value.Char;
        break;
      case LABEL:
        this->Int = value.Int;
        break;
      case SCALAR:
        this->Double = value.Double;
        break;
      case STRING:
      case IDENTIFIER:
        this->String = new vtkStdString(*value.String);
        break;
711 712 713 714 715 716 717
      case UNDEFINED:
      case STRINGLIST:
      case LABELLIST:
      case SCALARLIST:
      case VECTORLIST:
      case LABELLISTLIST:
      case ENTRYVALUELIST:
718
      case BOOLLIST:
719 720 721
      case EMPTYLIST:
      case DICTIONARY:
      case TOKEN_ERROR:
722
        break;
723
    }
724 725 726
  }

public:
727 728 729
  vtkFoamToken()
    : Type(UNDEFINED)
    , LabelType(NO_LABEL_TYPE)
730 731
  {
  }
732 733 734
  vtkFoamToken(const vtkFoamToken& value)
    : Type(value.Type)
    , LabelType(value.LabelType)
735 736 737
  {
    this->AssignData(value);
  }
738
  ~vtkFoamToken() { this->Clear(); }
739

740
  tokenType GetType() const { return this->Type; }
741

742 743
  void SetLabelType(labelType type) { this->LabelType = type; }
  labelType GetLabelType() const { return this->LabelType; }
744

745 746 747 748
  template <typename T>
  bool Is() const;
  template <typename T>
  T To() const;
749 750
#if defined(_MSC_VER)
  // workaround for Win32-64ids-nmake70
751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
  template <>
  bool Is<vtkTypeInt32>() const;
  template <>
  bool Is<vtkTypeInt64>() const;
  template <>
  bool Is<float>() const;
  template <>
  bool Is<double>() const;
  template <>
  vtkTypeInt32 To<vtkTypeInt32>() const;
  template <>
  vtkTypeInt64 To<vtkTypeInt64>() const;
  template <>
  float To<float>() const;
  template <>
  double To<double>() const;
767
#endif
768

769
  // workaround for SunOS-CC5.6-dbg
770
  vtkTypeInt64 ToInt() const
771
  {
772
    assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
773 774 775 776
    return this->Int;
  }

  // workaround for SunOS-CC5.6-dbg
777
  float ToFloat() const
778
  {
779
    return this->Type == LABEL ? static_cast<float>(this->Int) : static_cast<float>(this->Double);
780 781
  }

782 783
  vtkStdString ToString() const { return *this->String; }
  vtkStdString ToIdentifier() const { return *this->String; }
784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801

  void SetBad()
  {
    this->Clear();
    this->Type = TOKEN_ERROR;
  }
  void SetIdentifier(const vtkStdString& idString)
  {
    this->operator=(idString);
    this->Type = IDENTIFIER;
  }

  void operator=(const char value)
  {
    this->Clear();
    this->Type = PUNCTUATION;
    this->Char = value;
  }
802 803 804 805 806 807
  void operator=(const vtkTypeInt32 value)
  {
    this->Clear();

    assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
    if (this->LabelType == INT64)
808
    {
809
      vtkGenericWarningMacro("Setting a 64 bit label from a 32 bit integer.");
810
    }
811 812 813 814 815

    this->Type = LABEL;
    this->Int = static_cast<vtkTypeInt32>(value);
  }
  void operator=(const vtkTypeInt64 value)
816 817
  {
    this->Clear();
818 819 820

    assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
    if (this->LabelType == INT32)
821
    {
822 823
      vtkGenericWarningMacro("Setting a 32 bit label from a 64 bit integer. "
                             "Precision loss may occur.");
824
    }
825

826 827 828 829 830 831 832 833 834
    this->Type = LABEL;
    this->Int = value;
  }
  void operator=(const double value)
  {
    this->Clear();
    this->Type = SCALAR;
    this->Double = value;
  }
835
  void operator=(const char* value)
836 837 838 839 840 841 842 843 844 845 846
  {
    this->Clear();
    this->Type = STRING;
    this->String = new vtkStdString(value);
  }
  void operator=(const vtkStdString& value)
  {
    this->Clear();
    this->Type = STRING;
    this->String = new vtkStdString(value);
  }
847
  vtkFoamToken& operator=(const vtkFoamToken& value)
848 849 850
  {
    this->Clear();
    this->Type = value.Type;
851
    this->LabelType = value.LabelType;
852
    this->AssignData(value);
853
    return *this;
854 855 856 857 858
  }
  bool operator==(const char value) const
  {
    return this->Type == PUNCTUATION && this->Char == value;
  }
859
  bool operator==(const vtkTypeInt32 value) const
860
  {
861 862 863 864 865 866
    assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
    return this->Type == LABEL && this->Int == static_cast<vtkTypeInt64>(value);
  }
  bool operator==(const vtkTypeInt64 value) const
  {
    assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
867 868 869 870 871 872 873 874 875 876
    return this->Type == LABEL && this->Int == value;
  }
  bool operator==(const vtkStdString& value) const
  {
    return this->Type == STRING && *this->String == value;
  }
  bool operator!=(const vtkStdString& value) const
  {
    return this->Type != STRING || *this->String != value;
  }
877
  bool operator!=(const char value) const { return !this->operator==(value); }
878

879
  friend std::ostringstream& operator<<(std::ostringstream& str, const vtkFoamToken& value)
880 881
  {
    switch (value.GetType())
882
    {
883 884 885 886 887 888 889
      case TOKEN_ERROR:
        str << "badToken (an unexpected EOF?)";
        break;
      case PUNCTUATION:
        str << value.Char;
        break;
      case LABEL:
890 891
        assert("Label type not set!" && value.LabelType != NO_LABEL_TYPE);
        if (value.LabelType == INT32)
892
        {
893
          str << static_cast<vtkTypeInt32>(value.Int);
894
        }
895
        else
896
        {
897
          str << value.Int;
898
        }
899 900 901 902 903 904 905 906
        break;
      case SCALAR:
        str << value.Double;
        break;
      case STRING:
      case IDENTIFIER:
        str << *value.String;
        break;
907 908 909 910 911 912 913
      case UNDEFINED:
      case STRINGLIST:
      case LABELLIST:
      case SCALARLIST:
      case VECTORLIST:
      case LABELLISTLIST:
      case ENTRYVALUELIST:
914
      case BOOLLIST:
915 916
      case EMPTYLIST:
      case DICTIONARY:
917
        break;
918
    }
919 920 921
    return str;
  }
};
922

923 924
template <>
inline bool vtkFoamToken::Is<char>() const
925 926 927 928 929
{
  // masquerade for bool
  return this->Type == LABEL;
}

930 931
template <>
inline bool vtkFoamToken::Is<vtkTypeInt32>() const
932 933 934 935 936
{
  assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
  return this->Type == LABEL && this->LabelType == INT32;
}

937 938
template <>
inline bool vtkFoamToken::Is<vtkTypeInt64>() const
939
{
940
  assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
941
  return this->Type == LABEL;
942
}
943

944 945
template <>
inline bool vtkFoamToken::Is<float>() const
946
{
947
  return this->Type == LABEL || this->Type == SCALAR;
948
}
949

950 951
template <>
inline bool vtkFoamToken::Is<double>() const
952
{
953
  return this->Type == SCALAR;
954 955
}

956 957
template <>
inline char vtkFoamToken::To<char>() const
958 959 960 961
{
  return static_cast<char>(this->Int);
}

962 963
template <>
inline vtkTypeInt32 vtkFoamToken::To<vtkTypeInt32>() const
964
{
965 966
  assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
  if (this->LabelType == INT64)
967
  {
968 969
    vtkGenericWarningMacro("Casting 64 bit label to int32. Precision loss "
                           "may occur.");
970
  }
971 972 973
  return static_cast<vtkTypeInt32>(this->Int);
}

974 975
template <>
inline vtkTypeInt64 vtkFoamToken::To<vtkTypeInt64>() const
976 977
{
  assert("Label type not set!" && this->LabelType != NO_LABEL_TYPE);
978
  return this->Int;
979 980
}

981 982
template <>
inline float vtkFoamToken::To<float>() const
983
{
984
  return this->Type == LABEL ? static_cast<float>(this->Int) : static_cast<float>(this->Double);
985 986
}

987 988
template <>
inline double vtkFoamToken::To<double>() const
989
{
990
  return this->Type == LABEL ? static_cast<double>(this->Int) : this->Double;
991
}
992

993 994 995 996
//-----------------------------------------------------------------------------
// class vtkFoamFileStack
// list of variables that have to be saved when a file is included.
struct vtkFoamFileStack
997
{
998
protected:
999
  vtkOpenFOAMReader* Reader;
1000
  vtkStdString FileName;
1001
  FILE* File;
1002 1003 1004 1005 1006 1007 1008
  bool IsCompressed;
  z_stream Z;
  int ZStatus;
  int LineNumber;
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
  bool WasNewline;
#endif
1009

1010
  // buffer pointers. using raw pointers for performance reason.
1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
  unsigned char* Inbuf;
  unsigned char* Outbuf;
  unsigned char* BufPtr;
  unsigned char* BufEndPtr;

  vtkFoamFileStack(vtkOpenFOAMReader* reader)
    : Reader(reader)
    , FileName()
    , File(nullptr)
    , IsCompressed(false)
    , ZStatus(Z_OK)
    , LineNumber(0)
    ,
1024
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
1025 1026
    WasNewline(true)
    ,
1027
#endif
1028 1029 1030 1031
    Inbuf(nullptr)
    , Outbuf(nullptr)
    , BufPtr(nullptr)
    , BufEndPtr(nullptr)
1032 1033 1034 1035 1036 1037 1038 1039 1040
  {
    this->Z.zalloc = Z_NULL;
    this->Z.zfree = Z_NULL;
    this->Z.opaque = Z_NULL;
  }

  void Reset()
  {
    // this->FileName = "";
1041
    this->File = nullptr;
1042 1043 1044 1045 1046 1047 1048 1049 1050
    this->IsCompressed = false;
    // this->ZStatus = Z_OK;
    this->Z.zalloc = Z_NULL;
    this->Z.zfree = Z_NULL;
    this->Z.opaque = Z_NULL;
    // this->LineNumber = 0;
#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD
    this->WasNewline = true;
#endif
1051

1052 1053 1054 1055
    this->Inbuf = nullptr;
    this->Outbuf = nullptr;
    // this->BufPtr = nullptr;
    // this->BufEndPtr = nullptr;
1056 1057 1058
  }

public:
1059 1060 1061
  const vtkStdString& GetFileName() const { return this->FileName; }
  int GetLineNumber() const { return this->LineNumber; }
  vtkOpenFOAMReader* GetReader() const { return this->Reader; }
1062
};
1063

1064 1065 1066 1067
//-----------------------------------------------------------------------------
// class vtkFoamFile
// read and tokenize the input.
struct vtkFoamFile : public vtkFoamFileStack
1068
{
1069 1070 1071 1072 1073 1074
private:
  typedef vtkFoamFileStack Superclass;

public:
  // #inputMode values
  enum inputModes
1075
  {
1076 1077 1078 1079 1080
    INPUT_MODE_MERGE,
    INPUT_MODE_OVERWRITE,
    INPUT_MODE_PROTECT,
    INPUT_MODE_WARN,
    INPUT_MODE_ERROR
1081
  };
1082 1083 1084 1085 1086

private:
  inputModes InputMode;

  // inclusion handling
1087
  vtkFoamFileStack* Stack[VTK_FOAMFILE_INCLUDE_STACK_SIZE];
1088 1089 1090 1091
  int StackI;
  vtkStdString CasePath;

  // declare and define as private
1092
  vtkFoamFile() = delete;
1093
  bool InflateNext(unsigned char* buf, int requestSize, int* readSize = nullptr);
1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105
  int NextTokenHead();
  // hacks to keep exception throwing / recursive codes out-of-line to make
  // putBack(), getc() and readExpecting() inline expandable
  void ThrowDuplicatedPutBackException();
  void ThrowUnexpectedEOFException();
  void ThrowUnexpectedNondigitCharExecption(const int c);
  void ThrowUnexpectedTokenException(const char, const int c);
  int ReadNext();

  void PutBack(const int c)
  {
    if (--this->Superclass::BufPtr < this->Superclass::Outbuf)
1106
    {
1107
      this->ThrowDuplicatedPutBackException();
1108
    }
1109
    *this->Superclass::BufPtr = static_cast<unsigned char>(c);
1110 1111 1112 1113 1114 1115
  }

  // get a character
  int Getc()
  {
    return this->Superclass::BufPtr == this->Superclass::BufEndPtr ? this->ReadNext()
1116
                                                                   : *this->Superclass::BufPtr++;
1117 1118 1119 1120
  }

  vtkFoamError StackString()
  {
1121
    std::ostringstream os;
1122
    if (this->StackI > 0)
1123
    {
1124
      os << "\n included";
1125

1126
      for (int stackI = this->StackI - 1; stackI >= 0; stackI--)
1127
      {
1128
        os << " from line " << this->Stack[stackI]->GetLineNumber() << " of "
1129
           << this->Stack[stackI]->GetFileName() << "\n";
1130
      }
1131 1132
      os << ": ";
    }
1133 1134
    return vtkFoamError() << os.str();
  }
1135

1136 1137 1138
  bool CloseIncludedFile()
  {
    if (this->StackI == 0)
1139
    {
1140
      return false;
1141
    }
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
    this->Clear();
    this->StackI--;
    // use the default bitwise assignment operator
    this->Superclass::operator=(*this->Stack[this->StackI]);
    delete this->Stack[this->StackI];
    return true;
  }

  void Clear()
  {
    if (this->Superclass::IsCompressed)
1153
    {
1154
      inflateEnd(&this->Superclass::Z);
1155
    }
1156

1157 1158
    delete[] this->Superclass::Inbuf;
    delete[] this->Superclass::Outbuf;
1159
    this->Superclass::Inbuf = this->Superclass::Outbuf = nullptr;
1160

1161
    if (this->Superclass::File)
1162
    {
1163
      fclose(this->Superclass::File);
1164
      this->Superclass::File = nullptr;
1165
    }
1166 1167 1168 1169 1170
    // don't reset the line number so that the last line number is
    // retained after close
    // lineNumber_ = 0;
  }

1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
  //! Return file name (part beyond last /)
  vtkStdString ExtractName(const vtkStdString& path) const
  {
#if defined(_WIN32)
    const vtkStdString pathFindSeparator = "/\\", pathSeparator = "\\";
#else
    const vtkStdString pathFindSeparator = "/", pathSeparator = "/";
#endif
    vtkStdString::size_type pos = path.find_last_of(pathFindSeparator);
    if (pos == vtkStdString::npos)
1181
    {
1182 1183
      // no slash
      return path;
1184
    }
1185
    else if (pos + 1 == path.size())
1186
    {