Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 161581 Details for
Bug 233191
sci-vizualization/paraview-3.3_pre20080514: add >=OpenFOAM-1.5 support
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for the OpenFOAM-1.5 file support
paraview-3.3_pre20080514-OpenFOAM.patch (text/plain), 353.36 KB, created by
Oliver Borm
on 2008-07-28 20:31:44 UTC
(
hide
)
Description:
Patch for the OpenFOAM-1.5 file support
Filename:
MIME Type:
Creator:
Oliver Borm
Created:
2008-07-28 20:31:44 UTC
Size:
353.36 KB
patch
obsolete
>--- ParaView3-src/VTK/IO/vtkOpenFOAMReader.cxx 2008-04-24 20:05:18.000000000 +0200 >+++ ParaView3-20080728/VTK/IO/vtkOpenFOAMReader.cxx 2008-07-26 09:06:44.000000000 +0200 >@@ -12,3477 +12,7500 @@ > PURPOSE. See the above copyright notice for more information. > > =========================================================================*/ >-// Thanks to Terry Jordan of SAIC at the National Energy >+// Thanks to Terry Jordan of SAIC at the National Energy > // Technology Laboratory who developed this class. > // Please address all comments to Terry Jordan (terry.jordan@sa.netl.doe.gov) > // >+// Token-based FoamFile format lexer/parser, performance enhancements, >+// gzipped file and lagrangian field support by Takuya Oshima >+// (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) >+ >+// version 2008-07-26 >+ >+// 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 1 >+ >+// 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) >+ >+#if defined(_MSC_VER) && (_MSC_VER >= 1400) >+#define _CRT_SECURE_NO_WARNINGS 1 >+#endif >+ >+#if VTK_FOAMFILE_OMIT_CRCCHECK >+#define ZLIB_INTERNAL >+#endif >+ >+// for possible future extension of linehead-aware directives >+#define VTK_FOAMFILE_RECOGNIZE_LINEHEAD 0 >+ > #include "vtkOpenFOAMReader.h" > >-#include <vtkstd/string> > #include <vtkstd/vector> > #include <vtksys/ios/sstream> >+#include <vtk_zlib.h> > >-#include "vtkInformation.h" >-#include "vtkInformationVector.h" >-#include "vtkErrorCode.h" >-#include "vtkDataArraySelection.h" >-#include "vtkStreamingDemandDrivenPipeline.h" >+#include "vtkCallbackCommand.h" > #include "vtkCellArray.h" >+#include "vtkCellData.h" >+#include "vtkCharArray.h" >+#include "vtkConvexPointSet.h" > #include "vtkDataArraySelection.h" >-#include "vtkIntArray.h" >-#include "vtkFloatArray.h" >+#include "vtkDirectory.h" > #include "vtkDoubleArray.h" >-#include "vtkPoints.h" >-#include "vtkCellData.h" >+#include "vtkFloatArray.h" > #include "vtkHexahedron.h" >-#include "vtkWedge.h" >+#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" > #include "vtkPyramid.h" >-#include "vtkVertex.h" >+#include "vtkQuad.h" >+#include "vtkSmartPointer.h" >+#include "vtkSortDataArray.h" >+#include "vtkStdString.h" >+#include "vtkStreamingDemandDrivenPipeline.h" >+#include "vtkStringArray.h" > #include "vtkTetra.h" >-#include "vtkConvexPointSet.h" > #include "vtkTriangle.h" >-#include "vtkQuad.h" >-#include "vtkPolygon.h" > #include "vtkUnstructuredGrid.h" >-#include "vtkMultiBlockDataSet.h" >-#include "vtkUnstructuredGridAlgorithm.h" >-#include "vtkObjectFactory.h" >-#include "vtkDirectory.h" >- >-#include <ctype.h> >-#include <sys/stat.h> >+#include "vtkVertex.h" >+#include "vtkWedge.h" >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+#include "vtksys/DateStamp.h" >+#endif > >-#ifdef VTK_USE_ANSI_STDLIB >-#define VTK_IOS_NOCREATE >-#else >-#define VTK_IOS_NOCREATE | ios::nocreate >+#if !(defined(_WIN32) && !defined(__CYGWIN__) || defined(__LIBCATAMOUNT__)) >+// for getpwnam() / getpwuid() >+#include <sys/types.h> >+#include <pwd.h> >+// for getuid() >+#include <unistd.h> > #endif >+// for fabs() >+#include <math.h> > >-vtkCxxRevisionMacro(vtkOpenFOAMReader, "$Revision: 1.12 $"); >+vtkCxxRevisionMacro(vtkOpenFOAMReader, "$Revision: 1.7.2.2 $"); > vtkStandardNewMacro(vtkOpenFOAMReader); > >-struct stdString >+#if VTK_FOAMFILE_OMIT_CRCCHECK >+uLong ZEXPORT crc32(uLong, const Bytef *, uInt) >+{ return 0; } >+#endif >+ >+template<typename T> class objectVector: public vtkstd::vector<T> > { >- vtkstd::string value; >+ typedef vtkstd::vector<T> Superclass; >+ >+public: >+ ~objectVector() >+ { >+ for(size_t arrayI = 0; arrayI < Superclass::size(); arrayI++) >+ { >+ if(Superclass::operator[](arrayI) != NULL) >+ { >+ Superclass::operator[](arrayI)->Delete(); >+ } >+ } >+ } > }; > >-struct stringVector >+class intArrayVector: public objectVector<vtkIntArray*> {}; >+class unstructuredGridVector: public objectVector<vtkUnstructuredGrid*> {}; >+typedef objectVector<vtkPolyData*> polyDataVector; >+typedef objectVector<vtkStringArray*> stringArrayVector; >+ >+struct vtkOpenFOAMReader::intVectorVector > { >- vtkstd::vector< vtkstd::string > value; >+private: >+ vtkIntArray *body_, *indices_; >+ int nElements_; >+ void clear() { indices_->Delete(); body_->Delete(); } >+ intVectorVector(); >+ >+public: >+ intVectorVector(const intVectorVector &ivv) >+ : body_(vtkIntArray::New()), indices_(vtkIntArray::New()), >+ nElements_(ivv.nElements_) >+ { >+ indices_->DeepCopy(ivv.indices_); // vtkDataArrays do not have ShallowCopy >+ body_->DeepCopy(ivv.body_); >+ } >+ intVectorVector(const int nElements, const int bodyLength) >+ : body_(vtkIntArray::New()), indices_(vtkIntArray::New()), >+ nElements_(nElements) >+ { >+ indices_->SetNumberOfValues(nElements + 1); >+ body_->SetNumberOfValues(bodyLength); >+ } >+ >+ ~intVectorVector() { clear(); } >+ >+ // GetSize() returns all allocated size (Size) while GetDataSize() >+ // returns actually used size (MaxId * nComponents) >+ int bodySize() const { return body_->GetSize(); } >+ // note that vtkIntArray::Resize() allocates (current size + new >+ // size) bytes if current size < new size >+ void resizeBody(const int bodyLength) { body_->Resize(bodyLength); } >+ int *setIndex(const int i, const int bodyI) >+ { return body_->GetPointer(*indices_->GetPointer(i) = bodyI); } >+ void setValue(const int bodyI, int value) { body_->SetValue(bodyI, value); } >+ const int *operator[](const int i) const >+ { return body_->GetPointer(indices_->GetValue(i)); } >+ int size(const int i) const >+ { return indices_->GetValue(i + 1) - indices_->GetValue(i); } >+ int nElements() const { return nElements_; } > }; > >-struct intVector >+struct vtkFoamBoundaryEntry > { >- vtkstd::vector< int > value; >+ vtkStdString boundaryName; >+ int nFaces, startFace, allBoundariesStartFace; >+ bool isActive, isPhysicalBoundary; > }; > >-struct intVectorVector >+struct vtkOpenFOAMReader::vtkFoamBoundaryDict >+ : public vtkstd::vector<vtkFoamBoundaryEntry> > { >- vtkstd::vector< vtkstd::vector< int > > value; >+ // 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; > }; > >-struct faceVectorVector >+//----------------------------------------------------------------------------- >+// class vtkFoamError >+// class for exception-carrying object >+struct vtkOpenFOAMReader::vtkFoamError: public vtkStdString > { >- vtkstd::vector< vtkstd::vector< face > > value; >+public: >+ vtkFoamError(): vtkStdString() {} >+ vtkFoamError(const vtkFoamError& e): vtkStdString(e) {} >+ ~vtkFoamError() {} >+ // a super-easy way to make use of operator<<()'s defined in >+ // vtksys_ios::ostringstream class >+ template <class T> vtkFoamError& operator<<(const T& t) >+ { vtksys_ios::ostringstream os; os << t; operator+=(os.str()); return *this; } > }; > >-vtkOpenFOAMReader::vtkOpenFOAMReader() >+//----------------------------------------------------------------------------- >+// 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 vtkOpenFOAMReader::vtkFoamToken > { >- vtkDebugMacro(<<"Constructor"); >- this->SetNumberOfInputPorts(0); >- >- //INTIALIZE FILE NAME >- this->FileName = NULL; >- >- //VTK CLASSES >- this->Points = vtkPoints::New(); >- this->CellDataArraySelection = vtkDataArraySelection::New(); >- >- //DATA COUNTS >- this->NumFaces = 0; >- this->NumPoints = 0; >- this->NumCells = 0; >- >- this->TimeStepData = new stringVector; >- this->Path = new stdString; >- this->PathPrefix = new stdString; >- this->PolyMeshPointsDir = new stringVector; >- this->PolyMeshFacesDir = new stringVector; >- this->BoundaryNames = new stringVector; >- this->PointZoneNames = new stringVector; >- this->FaceZoneNames = new stringVector; >- this->CellZoneNames = new stringVector; >- >- this->FacePoints = new intVectorVector; >- this->FacesOwnerCell = new intVectorVector; >- this->FacesNeighborCell = new intVectorVector; >- this->FacesOfCell = new faceVectorVector; >- this->SizeOfBoundary = new intVector; >- >- //DATA TIMES >- this->NumberOfTimeSteps = 0; >- this->Steps = NULL; >- this->TimeStep = 0; >- this->TimeStepRange[0] = 0; >- this->TimeStepRange[1] = 0; >- this->RequestInformationFlag = true; >-} >+public: >+ enum tokenType >+ { >+ // undefined type >+ UNDEFINED, >+ // atomic types >+ PUNCTUATION, LABEL, SCALAR, STRING, IDENTIFIER, >+ // vtkObject-derived list types >+ STRINGLIST, LABELLIST, SCALARLIST, VECTORLIST, >+ // original list types >+ LABELLISTLIST, ENTRYVALUELIST, EMPTYLIST, DICTIONARY, >+ // exceptional state >+ UNIFORMLABELLIST, UNIFORMSCALARLIST, >+ // error state >+ ERROR >+ }; >+ >+protected: >+ tokenType type_; >+ union >+ { >+ char char_; >+ int int_; >+ double double_; >+ vtkStdString* string_; >+ vtkObjectBase *vtkObjectPtr_; >+ // vtkObject-derived list types >+ vtkIntArray *labelListPtr_; >+ vtkFloatArray *scalarListPtr_, *vectorListPtr_; >+ vtkStringArray *stringListPtr_; >+ // original list types >+ intVectorVector *labelListListPtr_; >+ vtkstd::vector<vtkFoamEntryValue*> *entryValuePtrs_; >+ vtkFoamDict *dictPtr_; >+ }; >+ >+ void clear() >+ { >+ if(type_ == STRING || type_ == IDENTIFIER) >+ { >+ delete string_; >+ } >+ } >+ >+ void assignData(const vtkFoamToken& value) >+ { >+ switch(value.type_) >+ { >+ case PUNCTUATION: >+ char_ = value.char_; >+ break; >+ case LABEL: >+ int_ = value.int_; >+ break; >+ case SCALAR: >+ double_ = value.double_; >+ break; >+ case STRING: case IDENTIFIER: >+ string_ = new vtkStdString(*value.string_); >+ } >+ } >+ >+public: >+ vtkFoamToken(): type_(UNDEFINED) {} >+ vtkFoamToken(const vtkFoamToken& value): type_(value.type_) >+ { assignData(value); } >+ ~vtkFoamToken() { clear(); } >+ >+ const tokenType type() const { return type_; } >+ >+ template<typename T> bool is() const; >+ template<typename T> T to() const; >+ >+ const vtkStdString toString() const { return *string_; } >+ const vtkStdString toIdentifier() const { return *string_; } >+ >+ void setBad() { clear(); type_ = ERROR; } >+ void setIdentifier(const vtkStdString& idString) >+ { operator=(idString); type_ = IDENTIFIER; } >+ >+ void operator=(const char value) >+ { clear(); type_ = PUNCTUATION; char_ = value; } >+ void operator=(const int value) >+ { clear(); type_ = LABEL; int_ = value; } >+ void operator=(const double value) >+ { clear(); type_ = SCALAR; double_ = value; } >+ void operator=(const char *value) >+ { clear(); type_ = STRING; string_ = new vtkStdString(value); } >+ void operator=(const vtkStdString& value) >+ { clear(); type_ = STRING; string_ = new vtkStdString(value); } >+ void operator=(const vtkFoamToken& value) >+ { clear(); type_ = value.type_; assignData(value); } >+ bool operator==(const char value) const >+ { return type_ == PUNCTUATION && char_ == value; } >+ bool operator==(const int value) const >+ { return type_ == LABEL && int_ == value; } >+ bool operator==(const vtkStdString& value) const >+ { return type_ == STRING && *string_ == value; } >+ bool operator!=(const vtkStdString& value) const >+ { return type_ != STRING || *string_ != value; } >+ bool operator!=(const char value) const { return !operator==(value); } >+ >+ friend vtksys_ios::ostringstream& operator<<(vtksys_ios::ostringstream& str, >+ const vtkFoamToken& value) >+ { >+ switch(value.type()) >+ { >+ case ERROR: >+ str << "badToken (an unexpected EOF?)"; >+ break; >+ case PUNCTUATION: >+ str << value.char_; >+ break; >+ case LABEL: >+ str << value.int_; >+ break; >+ case SCALAR: >+ str << value.double_; >+ break; >+ case STRING: case IDENTIFIER: >+ str << *value.string_; >+ break; >+ } >+ return str; >+ } >+}; > >-vtkOpenFOAMReader::~vtkOpenFOAMReader() >+template<> inline bool vtkOpenFOAMReader::vtkFoamToken::is<int>() const >+{ return type_ == LABEL; } >+template<> inline bool vtkOpenFOAMReader::vtkFoamToken::is<float>() const >+{ return type_ == LABEL || type_ == SCALAR; } >+template<> inline bool vtkOpenFOAMReader::vtkFoamToken::is<double>() const >+{ return type_ == SCALAR; } >+template<> inline int vtkOpenFOAMReader::vtkFoamToken::to() const >+{ return int_; } >+template<> inline float vtkOpenFOAMReader::vtkFoamToken::to() const >+{ return type_ == LABEL ? int_ : double_; } >+template<> inline double vtkOpenFOAMReader::vtkFoamToken::to() const >+{ return type_ == LABEL ? int_ : double_; } >+ >+//----------------------------------------------------------------------------- >+// class vtkFoamFileStack >+// list of variables that have to be saved when a file is included. >+struct vtkOpenFOAMReader::vtkFoamFileStack > { >- vtkDebugMacro(<<"DeConstructor"); >- this->Points->Delete(); >- this->CellDataArraySelection->Delete(); >- this->SetFileName(0); >- delete [] this->Steps; >+protected: >+ vtkStdString fileName_; >+ FILE *file_; >+ bool isCompressed_; >+ z_stream z_; >+ int zStatus_; >+ int lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ bool wasNewline_; >+#endif > >- delete this->TimeStepData; >- delete this->Path; >- delete this->PathPrefix; >- delete this->PolyMeshPointsDir; >- delete this->PolyMeshFacesDir; >- delete this->BoundaryNames; >- delete this->PointZoneNames; >- delete this->FaceZoneNames; >- delete this->CellZoneNames; >- delete this->FacePoints; >- delete this->FacesOwnerCell; >- delete this->FacesNeighborCell; >- delete this->FacesOfCell; >- delete this->SizeOfBoundary; >-} >+ // buffer pointers. using raw pointers for performance reason. >+ unsigned char *inbuf_; >+ unsigned char *outbuf_; >+ unsigned char *bufPtr_; >+ unsigned char *bufEndPtr_; >+ >+ vtkFoamFileStack() >+ : fileName_(), file_(NULL), isCompressed_(false), zStatus_(Z_OK), >+ lineNumber_(0), >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_(true), >+#endif >+ inbuf_(NULL), outbuf_(NULL), bufPtr_(NULL), bufEndPtr_(NULL) >+ { z_.zalloc = Z_NULL; z_.zfree = Z_NULL; z_.opaque = Z_NULL; } > >-int vtkOpenFOAMReader::RequestData( >- vtkInformation *vtkNotUsed(request), >- vtkInformationVector **vtkNotUsed(inputVector), >- vtkInformationVector *outputVector) >-{ >- vtkDebugMacro(<<"Request Data"); >- vtkInformation* outInfo = outputVector->GetInformationObject(0); >- vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::SafeDownCast( >- outInfo->Get(vtkMultiBlockDataSet::DATA_OBJECT())); >- if(!this->FileName) >- { >- vtkErrorMacro("FileName has to be specified!"); >- return 0; >- } >- this->CreateDataSet(output); >- return 1; >-} >+ void reset() >+ { >+ // path_ = ""; >+ file_ = NULL; >+ isCompressed_ = false; >+ // zStatus_ = Z_OK; >+ z_.zalloc = Z_NULL; >+ z_.zfree = Z_NULL; >+ z_.opaque = Z_NULL; >+ // lineNumber_ = 0; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif > >-void vtkOpenFOAMReader::PrintSelf(ostream& os, vtkIndent indent) >-{ >- vtkDebugMacro(<<"Print Self"); >- this->Superclass::PrintSelf(os,indent); >- os << indent << "File Name: " >- << (this->FileName ? this->FileName : "(none)") << "\n"; >- os << indent << "Number Of Nodes: " << this->NumPoints << "\n"; >- os << indent << "Number Of Cells: " << this->NumCells << "\n"; >- os << indent << "Number of Time Steps: " << this->NumberOfTimeSteps << endl; >- os << indent << "TimeStepRange: " >- << this->TimeStepRange[0] << " - " << this->TimeStepRange[1] >- << endl; >- os << indent << "TimeStep: " << this->TimeStep << endl; >- return; >-} >+ inbuf_ = NULL; >+ outbuf_ = NULL; >+ // bufPtr_ = NULL; >+ // bufEndPtr_ = NULL; >+ } >+ >+public: >+ const vtkStdString& fileName() const { return fileName_; } >+ int lineNumber() const { return lineNumber_; } >+}; > >-int vtkOpenFOAMReader::RequestInformation( >- vtkInformation *vtkNotUsed(request), >- vtkInformationVector **vtkNotUsed(inputVector), >- vtkInformationVector *outputVector) >+//----------------------------------------------------------------------------- >+// class vtkFoamFile >+// read and tokenize the input. >+struct vtkOpenFOAMReader::vtkFoamFile: public vtkFoamFileStack > { >- if(!this->FileName) >- { >- vtkErrorMacro("FileName has to be specified!"); >- return 0; >- } >- vtkDebugMacro(<<"Request Info"); >- if(RequestInformationFlag) >- { >- vtkDebugMacro(<<this->FileName); >- this->Path->value.append(this->FileName); >- this->ReadControlDict(); >- this->TimeStepRange[0] = 0; >- this->TimeStepRange[1] = this->NumberOfTimeSteps-1; >- this->PopulatePolyMeshDirArrays(); >- outputVector->GetInformationObject(0)->Set( >- vtkStreamingDemandDrivenPipeline::TIME_STEPS(), this->Steps, >- this->NumberOfTimeSteps); >- this->RequestInformationFlag = false; >- } >+public: >+ // #inputMode values >+ enum inputModes { INPUT_MODE_MERGE, INPUT_MODE_OVERWRITE, INPUT_MODE_ERROR }; > >- //Add scalars and vectors to metadata >- //create path to current time step >- vtksys_ios::stringstream tempPath; >- tempPath << this->PathPrefix->value.c_str(); >- tempPath << this->Steps[this->TimeStep]; >+private: >+ bool is13Positions_; >+ inputModes inputMode_; > >- //open the directory and get num of files >- int numSolvers; >- vtkDirectory * directory = vtkDirectory::New(); >- int opened = directory->Open(tempPath.str().c_str()); >- if(opened) >- { >- numSolvers = directory->GetNumberOfFiles(); >- } >- else >- { >- numSolvers = -1; //no dir >- } >+ // inclusion handling >+ vtkFoamFileStack *stack_[VTK_FOAMFILE_INCLUDE_STACK_SIZE]; >+ int stackI_; >+ vtkStdString casePath_; > >- //clear prior timestep data >- this->TimeStepData->value.clear(); >+ // declare and define as private >+ vtkFoamFile(); >+ bool inflateNext(unsigned char *buf, int requestSize); >+ 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(); > >- //loop over all files and locate >- //volScalars and volVectors >- for(int j = 0; j < numSolvers; j++) >- { >- const char * tempSolver = directory->GetFile(j); >- if(tempSolver != (char *)"polyMesh") >+ void putBack(const int c) >+ { >+ if(--bufPtr_ < outbuf_) > { >- if(tempSolver != (char *)"." && tempSolver != (char *)"..") >- { >- vtkstd::string type(this->GetDataType(tempPath.str().c_str(), >- tempSolver)); >- if(strcmp(type.c_str(), "Scalar") == 0) >- { >- this->TimeStepData->value.push_back(vtkstd::string(tempSolver)); >- this->CellDataArraySelection->AddArray(tempSolver); >- } >- else if(strcmp(type.c_str(), "Vector") == 0) >- { >- this->TimeStepData->value.push_back(vtkstd::string(tempSolver)); >- this->CellDataArraySelection->AddArray(tempSolver); >- } >- } >+ throwDuplicatedPutBackException(); > } >- } >- >- directory->Delete(); >- return 1; >-} >- >-// >-// CELL METHODS >-// >-int vtkOpenFOAMReader::GetNumberOfCellArrays() >-{ >- return this->CellDataArraySelection->GetNumberOfArrays(); >-} >- >-const char* vtkOpenFOAMReader::GetCellArrayName(int index) >-{ >- return this->CellDataArraySelection->GetArrayName(index); >-} >- >-int vtkOpenFOAMReader::GetCellArrayStatus(const char* name) >-{ >- return this->CellDataArraySelection->ArrayIsEnabled(name); >-} >- >-void vtkOpenFOAMReader::SetCellArrayStatus(const char* name, int status) >-{ >- if(status) >- { >- this->CellDataArraySelection->EnableArray(name); >- } >- else >- { >- this->CellDataArraySelection->DisableArray(name); >- } >- return; >-} >+ *bufPtr_ = c; >+ } > >-void vtkOpenFOAMReader::DisableAllCellArrays() >-{ >- this->CellDataArraySelection->DisableAllArrays(); >- return; >-} >+ // get a character >+ int getc() { return bufPtr_ == bufEndPtr_ ? readNext() : *bufPtr_++; } > >-void vtkOpenFOAMReader::EnableAllCellArrays() >-{ >- this->CellDataArraySelection->EnableAllArrays(); >- return; >-} >+ vtkFoamError stackString() >+ { >+ vtksys_ios::ostringstream os; >+ if(stackI_ > 0) >+ { >+ os << "\n included"; > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::CombineOwnerNeigbor >-// >-// Purpose: >-// add Owner faces to the faces of a cell and then add the neighor faces >-// >-// **************************************************************************** >-void vtkOpenFOAMReader::CombineOwnerNeigbor() >-{ >- vtkDebugMacro(<<"Combine owner & neighbor faces"); >- //reintialize faces of the cells >- face tempFace; >- this->FacesOfCell->value.clear(); >- this->FacesOfCell->value.resize(this->NumCells); >+ for(int stackI = stackI_ - 1; stackI >= 0; stackI--) >+ { >+ os << " from line " << stack_[stackI]->lineNumber() << " of " >+ << stack_[stackI]->fileName() << "\n"; >+ } >+ os << ": "; >+ } >+ return vtkFoamError() << os.str(); >+ } > >- //add owner faces to cell >- for(int i = 0; i < (int)this->FacesOwnerCell->value.size(); i++) >- { >- for(int j = 0; j < (int)this->FacesOwnerCell->value[i].size(); j++) >+ bool closeIncludedFile() >+ { >+ if(stackI_ == 0) > { >- tempFace.faceIndex = this->FacesOwnerCell->value[i][j]; >- tempFace.neighborFace = false; >- this->FacesOfCell->value[i].push_back(tempFace); >+ return false; > } >- } >+ clear(); >+ stackI_--; >+ // use the default bitwise assignment operator >+ vtkFoamFileStack::operator=(*stack_[stackI_]); >+ delete stack_[stackI_]; >+ return true; >+ } > >- //add neighbor faces to cell >- for(int i = 0; i < (int)this->FacesNeighborCell->value.size(); i++) >- { >- for(int j = 0; j < (int)this->FacesNeighborCell->value[i].size(); j++) >+ void clear() >+ { >+ if(isCompressed_) > { >- tempFace.faceIndex = this->FacesNeighborCell->value[i][j]; >- tempFace.neighborFace = true; >- this->FacesOfCell->value[i].push_back(tempFace); >+ inflateEnd(&z_); > } >- } >- >- //clean up memory >- this->FacesOwnerCell->value.clear(); >- this->FacesNeighborCell->value.clear(); >- return; >-} > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::MakeInternalMesh >-// >-// Purpose: >-// derive cell types and create the internal mesh >-// >-// **************************************************************************** >-vtkUnstructuredGrid * vtkOpenFOAMReader::MakeInternalMesh() >-{ >- vtkDebugMacro(<<"Make internal mesh"); >- //initialize variables >- bool foundDup = false; >- vtkstd::vector< int > cellPoints; >- vtkstd::vector< int > tempFaces[2]; >- vtkstd::vector< int > firstFace; >- int pivotPoint = 0; >- int i, j, k, l, pCount; >- int faceCount = 0; >+ delete [] inbuf_; >+ delete [] outbuf_; >+ inbuf_ = outbuf_ = NULL; > >- //Create Mesh >- vtkUnstructuredGrid * internalMesh = vtkUnstructuredGrid::New(); >- //loop through each cell, derive type and insert it into the mesh >- //hexahedron, prism, pyramid, tetrahedron, wedge&tetWedge >- for(i = 0; i < (int)this->FacesOfCell->value.size(); i++) //each cell >- { >+ if(file_ != NULL) >+ { >+ fclose(file_); >+ file_ = NULL; >+ } >+ // don't reset the line number so that the last line number is >+ // retained after close >+ // lineNumber_ = 0; >+ } > >- //calculate the total points for the cell >- //used to derive cell type >- int totalPointCount = 0; >- for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++) //each face >+ const vtkStdString extractPath(const vtkStdString& path) const >+ { >+#if defined(_WIN32) && PARAVIEW_VERSION_MAJOR >= 3 >+ const vtkStdString pathFindSeparator = "/\\", pathSeparator = "\\"; >+#else >+ const vtkStdString pathFindSeparator = "/", pathSeparator = "/"; >+#endif >+ const size_t pos = path.find_last_of(pathFindSeparator); >+ return pos == vtkStdString::npos ? vtkStdString(".") + pathSeparator >+ : path.substr(0, pos + 1); >+ } >+ >+public: >+ vtkFoamFile(const vtkStdString& casePath) >+ : vtkFoamFileStack(), is13Positions_(false), inputMode_(INPUT_MODE_ERROR), >+ stackI_(0), casePath_(casePath) >+ {} >+ ~vtkFoamFile() { close(); } >+ >+ void setIs13Positions(const bool is13Positions) >+ { is13Positions_ = is13Positions; } >+ const bool getIs13Positions() const { return is13Positions_; } >+ inputModes getInputMode() const { return inputMode_; } >+ const vtkStdString casePath() const { return casePath_; } >+ const vtkStdString filePath() const { return extractPath(fileName_); } >+ >+ vtkStdString expandPath(const vtkStdString& pathIn, >+ const vtkStdString& defaultPath) >+ { >+ vtkStdString expandedPath; >+ bool isExpanded = false, wasPathSeparator = true; >+ const int nChars = pathIn.length(); >+ for(int charI = 0; charI < nChars;) >+ { >+ char c = pathIn[charI]; >+ switch(c) >+ { >+ case '$': // $-variable expansion >+ { >+ vtkStdString variable; >+ while(++charI < nChars && (isalnum(pathIn[charI]) >+ || pathIn[charI] == '_')) >+ { >+ variable += pathIn[charI]; >+ } >+ if(variable == "FOAM_CASE") // discard path until the variable >+ { >+ expandedPath = casePath_; >+ wasPathSeparator = true; >+ isExpanded = true; >+ } >+ else >+ { >+ const char *value = getenv(variable.c_str()); >+ if(value != NULL) >+ { >+ expandedPath += value; >+ } >+ const size_t len = expandedPath.length(); >+ if(len > 0) >+ { >+ const char c = expandedPath[len - 1]; >+ wasPathSeparator = (c == '/' || c == '\\'); >+ } >+ else >+ { >+ wasPathSeparator = false; >+ } >+ } >+ } >+ break; >+ case '~': // home directory expansion >+ // not using kwsys::SystemTools::ConvertToUnixSlashes() for >+ // a bit better handling of "~" >+ if(wasPathSeparator) >+ { >+ vtkStdString userName; >+ while(++charI < nChars && (pathIn[charI] != '/' >+ && pathIn[charI] != '\\') && pathIn[charI] != '$') >+ { >+ userName += pathIn[charI]; >+ } >+ if(userName == "") >+ { >+ const char *homePtr = getenv("HOME"); >+ if(homePtr == NULL) >+ { >+#if defined(_WIN32) && !defined(__CYGWIN__) || defined(__LIBCATAMOUNT__) >+ expandedPath = ""; >+#else >+ const struct passwd *pwentry = getpwuid(getuid()); >+ if(pwentry == NULL) >+ { >+ throw stackString() << "Home directory path not found"; >+ } >+ expandedPath = pwentry->pw_dir; >+#endif >+ } >+ else >+ { >+ expandedPath = homePtr; >+ } >+ } >+ else >+ { >+#if defined(_WIN32) && !defined(__CYGWIN__) || defined(__LIBCATAMOUNT__) >+ const char *homePtr = getenv("HOME"); >+ expandedPath = extractPath(homePtr ? homePtr : "") + userName; >+#else >+ if(userName == "OpenFOAM") >+ { >+ // so far only "~/.OpenFOAM" expansion is supported >+ const char *homePtr = getenv("HOME"); >+ if(homePtr == NULL) >+ { >+ expandedPath = ""; >+ } >+ else >+ { >+ expandedPath = vtkStdString(homePtr) + "/.OpenFOAM"; >+ } >+ } >+ else >+ { >+ const struct passwd *pwentry = getpwnam(userName.c_str()); >+ if(pwentry == NULL) >+ { >+ throw stackString() << "Home directory for user " >+ << userName.c_str() << " not found"; >+ } >+ expandedPath = pwentry->pw_dir; >+ } >+#endif >+ } >+ wasPathSeparator = false; >+ isExpanded = true; >+ break; >+ } >+ // fall through >+ default: >+ wasPathSeparator = (c == '/' || c == '\\'); >+ expandedPath += c; >+ charI++; >+ } >+ } >+ if(isExpanded || expandedPath.substr(0, 1) == "/" >+ || expandedPath.substr(0, 1) == "\\") >+ { >+ return expandedPath; >+ } >+ else > { >- totalPointCount += >- (int)this->FacePoints-> >- value[this->FacesOfCell->value[i][j].faceIndex].size(); >+ return defaultPath + expandedPath; > } >+ } > >- // using cell type - order points, create cell, & add to mesh >- //OFhex | vtkHexahedron >- if (totalPointCount == 24) >+ void includeFile(const vtkStdString& includedFileName, >+ const vtkStdString& defaultPath) >+ { >+ if(stackI_ >= VTK_FOAMFILE_INCLUDE_STACK_SIZE) >+ { >+ throw stackString() << "Exceeded maximum #include recursions of " >+ << VTK_FOAMFILE_INCLUDE_STACK_SIZE; >+ } >+ // use the default bitwise copy constructor >+ stack_[stackI_++] = new vtkFoamFileStack(*this); >+ vtkFoamFileStack::reset(); >+ >+ open(expandPath(includedFileName, defaultPath)); >+ } >+ >+ // the tokenizer >+ // returns true if success, false if encountered EOF >+ bool read(vtkFoamToken& token) >+ { >+ // expanded the outermost loop in nextTokenHead() for performance >+ int c; >+ while(isspace(c = getc())) // isspace() accepts -1 as EOF >+ { >+ if(c == '\n') >+ { >+ ++lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif >+ } >+ } >+ if(c == 47) // '/' == 47 >+ { >+ putBack(c); >+ c = nextTokenHead(); >+ } >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ if(c != '#') > { >- faceCount = 0; >+ wasNewline_ = false; >+ } >+#endif > >- //get first face >- for(j = 0; j < >- (int)this->FacePoints-> >- value[this->FacesOfCell->value[i][0].faceIndex].size(); j++) >- { >- firstFace.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][0].faceIndex][j]); >+ const int MAXLEN = 1024; >+ char buf[MAXLEN + 1]; >+ int charI = 0; >+ switch(c) >+ { >+ case '(': case ')': >+ // high-priority punctuation token >+ token = (char)c; >+ return true; >+ case '1': case '2': case '3': case '4': case '5': case '6': case '7': >+ case '8': case '9': case '0': case '-': >+ // undetermined number token >+ do >+ { >+ buf[charI++] = c; >+ } while(isdigit(c = getc()) && charI < MAXLEN); >+ if(c != '.' && c != 'e' && c != 'E' && charI < MAXLEN && c != EOF) >+ { >+ // label token >+ buf[charI] = '\0'; >+ token = static_cast<int>(strtol(buf, NULL, 10)); >+ putBack(c); >+ return true; >+ } >+ // fall through >+ case '.': >+ // scalar token >+ if(c == '.' && charI < MAXLEN) >+ { >+ // read decimal fraction part >+ buf[charI++] = c; >+ while(isdigit(c = getc()) && charI < MAXLEN) >+ { >+ buf[charI++] = c; >+ } >+ } >+ if((c == 'e' || c == 'E') && charI < MAXLEN) >+ { >+ // read exponent part >+ buf[charI++] = c; >+ if(((c = getc()) == '+' || c == '-') && charI < MAXLEN) >+ { >+ buf[charI++] = c; >+ c = getc(); >+ } >+ while(isdigit(c) && charI < MAXLEN) >+ { >+ buf[charI++] = c; >+ c = getc(); >+ } >+ } >+ if(charI == 1 && buf[0] == '-') >+ { >+ token = '-'; >+ putBack(c); >+ return true; >+ } >+ buf[charI] = '\0'; >+ token = strtod(buf, NULL); >+ putBack(c); >+ break; >+ case ';': case '{': case '}': case '[': case ']': case ':': case ',': >+ case '=': case '+': case '*': case '/': >+ // low-priority punctuation token >+ token = (char)c; >+ return true; >+ case '"': >+ { >+ // string token >+ bool wasEscape = false; >+ while((c = getc()) != EOF && charI < MAXLEN) >+ { >+ if(c == '\\' && !wasEscape) >+ { >+ wasEscape = true; >+ continue; >+ } >+ else if(c == '"' && !wasEscape) >+ { >+ break; >+ } >+ else if(c == '\n') >+ { >+ ++lineNumber_; >+ if(!wasEscape) >+ { >+ throw stackString() << "Unescaped newline in string constant"; >+ } >+ } >+ buf[charI++] = c; >+ wasEscape = false; >+ } >+ buf[charI] = '\0'; >+ token = buf; >+ } >+ break; >+ case EOF: >+ // end of file >+ token.setBad(); >+ return false; >+ case '$': >+ { >+ vtkFoamToken identifierToken; >+ if(!read(identifierToken)) >+ { >+ throw stackString() << "Unexpected EOF reading identifier"; >+ } >+ if(identifierToken.type() != vtkFoamToken::STRING) >+ { >+ throw stackString() << "Expected a word, found " << identifierToken; >+ } >+ token.setIdentifier(identifierToken.toString()); >+ return true; >+ } >+ case '#': >+ { >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ // placing #-directives in the middle of a line looks like >+ // valid for the genuine OF 1.5 parser >+ if(!wasNewline_) >+ { >+ throw stackString() >+ << "Encountered #-directive in the middle of a line"; >+ } >+ wasNewline_ = false; >+#endif >+ // read directive >+ vtkFoamToken directiveToken; >+ if(!read(directiveToken)) >+ { >+ throw stackString() << "Unexpected EOF reading directive"; >+ } >+ if(directiveToken == "include") >+ { >+ vtkFoamToken fileNameToken; >+ if(!read(fileNameToken)) >+ { >+ throw stackString() << "Unexpected EOF reading filename"; >+ } >+ includeFile(fileNameToken.toString(), extractPath(fileName_)); >+ } >+ else if(directiveToken == "inputMode") >+ { >+ vtkFoamToken modeToken; >+ if(!read(modeToken)) >+ { >+ throw stackString() << "Unexpected EOF reading inputMode specifier"; >+ } >+ if(modeToken == "merge") >+ { >+ inputMode_ = INPUT_MODE_MERGE; >+ } >+ else if(modeToken == "overwrite") >+ { >+ inputMode_ = INPUT_MODE_OVERWRITE; >+ } >+ else if(modeToken == "error" || modeToken == "default") >+ { >+ inputMode_ = INPUT_MODE_ERROR; >+ } >+ else >+ { >+ throw stackString() << "Expected one of inputMode specifiers " >+ "(merge, overwrite, error, default), found " << modeToken; >+ } >+ } >+ else >+ { >+ throw stackString() << "Unsupported directive " << directiveToken; >+ } >+ return read(token); >+ } >+ default: >+ // parses as a word token, but gives the STRING type for simplicity >+ int inBrace = 0; >+ do >+ { >+ if(c == '(') >+ { >+ inBrace++; >+ } >+ else if(c == ')' && --inBrace == -1) >+ { >+ break; >+ } >+ buf[charI++] = c; >+ // valid characters that constitutes a word >+ // cf. src/OpenFOAM/primitives/strings/word/wordI.H >+ } while((c = getc()) != EOF && !isspace(c) && c != '"' && c != '/' >+ && c != ';' && c != '{' && c != '}' && charI < MAXLEN); >+ buf[charI] = '\0'; >+ token = buf; >+ putBack(c); >+ } >+ >+ if(c == EOF) >+ { >+ throwUnexpectedEOFException(); >+ } >+ if(charI == MAXLEN) >+ { >+ throw stackString() << "Exceeded maximum allowed length of " << MAXLEN >+ << " chars"; >+ } >+ return true; >+ } >+ >+ void open(const vtkStdString& fileName) >+ { >+ // reset line number to indicate the beginning of the file when an >+ // exception is thrown >+ lineNumber_ = 0; >+ fileName_ = fileName; >+ >+ if(file_ != NULL) >+ { >+ throw stackString() << "File already opened within this object"; >+ } >+ >+ if((file_ = fopen(fileName.c_str(), "rb")) == NULL) >+ { >+ throw stackString() << "Can't open"; >+ } >+ >+ unsigned char zMagic[2]; >+ if(fread(zMagic, 1, 2, file_) == 2 >+ && zMagic[0] == 0x1f && zMagic[1] == 0x8b) >+ { >+ // gzip-compressed format >+ z_.avail_in = 0; >+ z_.next_in = Z_NULL; >+ // + 32 to automatically recognize gzip format >+ if(inflateInit2(&z_, 15 + 32) == Z_OK) >+ { >+ isCompressed_ = true; >+ inbuf_ = new unsigned char[VTK_FOAMFILE_INBUFSIZE]; >+ } >+ else >+ { >+ fclose(file_); >+ file_ = NULL; >+ throw stackString() << "Can't init zstream " << (z_.msg ? z_.msg : ""); >+ } >+ } >+ else >+ { >+ // uncompressed format >+ isCompressed_ = false; >+ } >+ rewind(file_); >+ >+ zStatus_ = Z_OK; >+ outbuf_ = new unsigned char[VTK_FOAMFILE_OUTBUFSIZE + 1]; >+ bufPtr_ = outbuf_ + 1; >+ bufEndPtr_ = bufPtr_; >+ lineNumber_ = 1; >+ } >+ >+ void close() >+ { >+ while(closeIncludedFile()); >+ clear(); >+ } >+ >+ // gzread with buffering handling >+ int read(unsigned char *buf, const int len) >+ { >+ int readlen; >+ const int buflen = bufEndPtr_ - bufPtr_; >+ if(len > buflen) >+ { >+ memcpy(buf, bufPtr_, buflen); >+ readlen = inflateNext(buf + buflen, len - buflen); >+ if(readlen >= 0) >+ { >+ readlen += buflen; >+ } >+ else >+ { >+ if(buflen == 0) // return EOF >+ { >+ readlen = -1; >+ } >+ else >+ { >+ readlen = buflen; >+ } >+ } >+ bufPtr_ = bufEndPtr_; >+ } >+ else >+ { >+ memcpy(buf, bufPtr_, len); >+ bufPtr_ += len; >+ readlen = len; >+ } >+ for(int i = 0; i < readlen; i++) >+ { >+ if(buf[i] == '\n') >+ { >+ lineNumber_++; >+ } >+ } >+ return readlen; >+ } >+ >+ void readExpecting(const char expected) >+ { >+ // skip prepending invalid chars >+ // expanded the outermost loop in nextTokenHead() for performance >+ int c; >+ while(isspace(c = getc())) // isspace() accepts -1 as EOF >+ { >+ if(c == '\n') >+ { >+ ++lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif >+ } >+ } >+ if(c == 47) // '/' == 47 >+ { >+ putBack(c); >+ c = nextTokenHead(); >+ } >+ if(c != expected) >+ { >+ throwUnexpectedTokenException(expected, c); >+ } >+ } >+ >+ void readExpecting(const char* str) >+ { >+ vtkFoamToken t; >+ if(!read(t) || t != str) >+ { >+ throw stackString() << "Expected string \"" << str << "\", found " << t; >+ } >+ } >+ >+ template<class T> T readValue(); //{ return static_cast<T>(0); } >+}; >+ >+int vtkOpenFOAMReader::vtkFoamFile::readNext() >+{ >+ if(!inflateNext(outbuf_ + 1, VTK_FOAMFILE_OUTBUFSIZE)) >+ { >+ return closeIncludedFile() ? getc() : EOF; >+ } >+ return *bufPtr_++; >+} >+ >+// specialized for reading an integer value. >+// not using the standard strtol() for speed reason. >+template<> int vtkOpenFOAMReader::vtkFoamFile::readValue() >+{ >+ // skip prepending invalid chars >+ // expanded the outermost loop in nextTokenHead() for performance >+ int c; >+ while(isspace(c = getc())) // isspace() accepts -1 as EOF >+ { >+ if(c == '\n') >+ { >+ ++lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif >+ } >+ } >+ if(c == 47) // '/' == 47 >+ { >+ putBack(c); >+ c = nextTokenHead(); >+ } >+ >+ int nonNegative = c - 45; // '-' == 45 >+ if(nonNegative == 0 || c == 43) // '+' == 43 >+ { >+ c = getc(); >+ if(c == '\n') >+ { >+ ++lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif >+ } >+ } >+ >+ if(!isdigit(c)) // isdigit() accepts -1 as EOF >+ { >+ if(c == EOF) >+ { >+ throwUnexpectedEOFException(); >+ } >+ else >+ { >+ throwUnexpectedNondigitCharExecption(c); >+ } >+ } >+ >+ int num = c - 48; // '0' == 48 >+ while(isdigit(c = getc())) >+ { >+ num = 10 * num + c - 48; >+ } >+ >+ if(c == EOF) >+ { >+ throwUnexpectedEOFException(); >+ } >+ putBack(c); >+ >+ return nonNegative ? num : -num; >+} >+ >+// extreamely simplified high-performing string to floating point >+// conversion code based on >+// ParaView3/VTK/Utilities/vtksqlite/vtk_sqlite3.c >+template<> float vtkOpenFOAMReader::vtkFoamFile::readValue() >+{ >+ // skip prepending invalid chars >+ // expanded the outermost loop in nextTokenHead() for performance >+ int c; >+ while(isspace(c = getc())) // isspace() accepts -1 as EOF >+ { >+ if(c == '\n') >+ { >+ ++lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif >+ } >+ } >+ if(c == 47) // '/' == 47 >+ { >+ putBack(c); >+ c = nextTokenHead(); >+ } >+ >+ // determine sign >+ int nonNegative = c - 45; // '-' == 45 >+ if(nonNegative == 0 || c == 43) // '+' == 43 >+ { >+ c = getc(); >+ if(c == '\n') >+ { >+ ++lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif >+ } >+ } >+ >+ if(!isdigit(c) && c != 46) // '.' == 46, isdigit() accepts EOF >+ { >+ throwUnexpectedNondigitCharExecption(c); >+ } >+ >+ // read integer part >+ double num = c - 48; // '0' == 48 >+ while(isdigit(c = getc())) >+ { >+ num = num * 10.0 + (c - 48); >+ } >+ >+ // read decimal part >+ if(c == 46) // '.' >+ { >+ double divisor = 1.0; >+ >+ while(isdigit(c = getc())) >+ { >+ num = num * 10.0 + (c - 48); >+ divisor *= 10.0; >+ } >+ num /= divisor; >+ } >+ >+ // read exponent part >+ if(c == 69 || c == 101) // 'E' == 69, 'e' == 101 >+ { >+ int esign = 1; >+ int eval = 0; >+ double scale = 1.0; >+ >+ c = getc(); >+ if(c == 45) // '-' >+ { >+ esign = -1; >+ c = getc(); >+ } >+ else if(c == 43) // '+' >+ { >+ c = getc(); >+ } >+ >+ while(isdigit(c)) >+ { >+ eval = eval * 10 + (c - 48); >+ c = getc(); >+ } >+ >+ // fast exponent multiplication! >+ while(eval >= 64) >+ { >+ scale *= 1.0e+64; >+ eval -= 64; >+ } >+ while(eval >= 16) >+ { >+ scale *= 1.0e+16; >+ eval -= 16; >+ } >+ while(eval >= 4) >+ { >+ scale *= 1.0e+4; >+ eval -= 4; >+ } >+ while(eval >= 1) >+ { >+ scale *= 1.0e+1; >+ eval -= 1; >+ } >+ >+ if(esign < 0) >+ { >+ num /= scale; >+ } >+ else >+ { >+ num *= scale; >+ } >+ } >+ >+ if(c == EOF) >+ { >+ throwUnexpectedEOFException(); >+ } >+ putBack(c); >+ >+ return static_cast<float>(nonNegative ? num : -num); >+} >+ >+// hacks to keep exception throwing code out-of-line to make >+// putBack() and readExpecting() inline expandable >+void vtkOpenFOAMReader::vtkFoamFile::throwUnexpectedEOFException() >+{ throw stackString() << "Unexpected EOF"; } >+ >+void vtkOpenFOAMReader::vtkFoamFile::throwUnexpectedNondigitCharExecption( >+ const int c) >+{ >+ throw stackString() << "Expected a number, found a non-digit character " >+ << static_cast<char>(c); >+} >+ >+void vtkOpenFOAMReader::vtkFoamFile::throwUnexpectedTokenException( >+ const char expected, const int c) >+{ >+ vtkFoamError sstr; >+ sstr << stackString() << "Expected punctuation token '" << expected >+ << "', found "; >+ if(c == EOF) >+ { >+ sstr << "EOF"; >+ } >+ else >+ { >+ sstr << static_cast<char>(c); >+ } >+ throw sstr; >+} >+ >+void vtkOpenFOAMReader::vtkFoamFile::throwDuplicatedPutBackException() >+{ throw stackString() << "Attempted duplicated putBack()"; } >+ >+bool vtkOpenFOAMReader::vtkFoamFile::inflateNext(unsigned char *buf, >+ int requestSize) >+{ >+ int size; >+ if(isCompressed_) >+ { >+ if(zStatus_ != Z_OK) >+ { >+ return false; >+ } >+ z_.next_out = buf; >+ z_.avail_out = requestSize; >+ >+ do >+ { >+ if(z_.avail_in == 0) >+ { >+ z_.next_in = inbuf_; >+ z_.avail_in = fread(inbuf_, 1, VTK_FOAMFILE_INBUFSIZE, file_); >+ if(ferror(file_)) >+ { >+ throw stackString() << "Fread failed"; >+ } >+ } >+ zStatus_ = inflate(&z_, Z_NO_FLUSH); >+ if(zStatus_ == Z_STREAM_END >+#if VTK_FOAMFILE_OMIT_CRCCHECK >+ // the dummy CRC function causes data error when finalizing >+ // so we have to proceed even when a data error is detected >+ || zStatus_ == Z_DATA_ERROR >+#endif >+ ) >+ { >+ break; >+ } >+ if(zStatus_ != Z_OK) >+ { >+ throw stackString() << "Inflation failed: " << (z_.msg ? z_.msg : ""); >+ } >+ } >+ while(z_.avail_out > 0); >+ >+ size = requestSize - z_.avail_out; >+ } >+ else >+ { >+ // not compressed >+ size = fread(buf, 1, requestSize, file_); >+ } >+ >+ if(size <= 0) >+ { >+ // retain the current location bufPtr_ to the end of the buffer so that >+ // getc() returns EOF again when called next time >+ return false; >+ } >+ // size > 0 >+ bufPtr_ = outbuf_ + 1; // reserve the first byte for getback char >+ bufEndPtr_ = bufPtr_ + size; >+ return true; >+} >+ >+// get next semantically valid character >+int vtkOpenFOAMReader::vtkFoamFile::nextTokenHead() >+{ >+ for(;;) >+ { >+ int c; >+ while(isspace(c = getc())) // isspace() accepts -1 as EOF >+ { >+ if(c == '\n') >+ { >+ ++lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif >+ } >+ } >+ if(c == '/') >+ { >+ if((c = getc()) == '/') >+ { >+ while((c = getc()) != EOF && c != '\n'); >+ if(c == EOF) >+ { >+ return c; >+ } >+ ++lineNumber_; >+#if VTK_FOAMFILE_RECOGNIZE_LINEHEAD >+ wasNewline_ = true; >+#endif >+ } >+ else if(c == '*') >+ { >+ for(;;) >+ { >+ while((c = getc()) != EOF && c != '*') >+ { >+ if(c == '\n') >+ { >+ ++lineNumber_; >+ } >+ } >+ if(c == EOF) >+ { >+ return c; >+ } >+ else if((c = getc()) == '/') >+ { >+ break; >+ } >+ putBack(c); >+ } >+ } >+ else >+ { >+ putBack(c); // may be an EOF >+ return '/'; >+ } >+ } >+ else // may be an EOF >+ { >+ return c; >+ } >+ } >+} >+ >+//----------------------------------------------------------------------------- >+// class vtkFoamIOobject >+// holds file handle, file format, name of the object the file holds and >+// type of the object. >+struct vtkOpenFOAMReader::vtkFoamIOobject: public vtkFoamFile >+{ >+public: >+ enum fileFormat { UNDEFINED, ASCII, BINARY }; >+ >+private: >+ fileFormat format_; >+ vtkStdString objectName_; >+ vtkStdString headerClassName_; >+ vtkFoamError e_; >+ >+ vtkFoamIOobject(); >+ void readHeader(); // defined later >+public: >+ vtkFoamIOobject(const vtkStdString& casePath) >+ : vtkFoamFile(casePath), format_(UNDEFINED), e_() {} >+ ~vtkFoamIOobject() { close(); } >+ >+ bool open(const vtkStdString& file) >+ { >+ try >+ { >+ vtkFoamFile::open(file); >+ } >+ catch(vtkFoamError& e) >+ { >+ e_ = e; >+ return false; >+ } >+ >+ try >+ { >+ readHeader(); >+ } >+ catch(vtkFoamError& e) >+ { >+ vtkFoamFile::close(); >+ e_ = e; >+ return false; >+ } >+ return true; >+ } >+ >+ void close() >+ { >+ vtkFoamFile::close(); >+ format_ = UNDEFINED; >+ objectName_.erase(); >+ headerClassName_.erase(); >+ e_.erase(); >+ } >+ const fileFormat format() const { return format_; } >+ const vtkStdString& className() const { return headerClassName_; } >+ const vtkStdString& objectName() const { return objectName_; } >+ const vtkFoamError& error() const { return e_; } >+ void setError(const vtkFoamError& e) { e_ = e; } >+}; >+ >+//----------------------------------------------------------------------------- >+// class vtkFoamEntryValue >+// a class that represents a value of a dictionary entry that corresponds to >+// its keyword. note that an entry can have more than one value. >+struct vtkOpenFOAMReader::vtkFoamEntryValue: public vtkFoamToken >+{ >+private: >+ bool isUniform_; >+ bool managed_; >+ vtkFoamEntry *upperEntryPtr_; >+ >+ vtkFoamEntryValue(); >+ vtkObjectBase *toVTKObject() { return vtkObjectPtr_; } >+ void clear(); >+ void readList(vtkFoamIOobject& io); >+ >+protected: >+ // reads primitive int/float lists >+ template <typename listT, typename primitiveT> class listTraits >+ { >+ listT *ptr_; >+ >+ public: >+ listTraits(): ptr_(listT::New()) {} >+ listT *ptr() { return ptr_; } >+ void readUniformValues(vtkFoamIOobject& io, const int size) >+ { >+ primitiveT value = io.readValue<primitiveT>(); >+ for(int i = 0; i < size; i++) >+ { >+ ptr_->SetValue(i, value); >+ } >+ } >+ void readAsciiList(vtkFoamIOobject& io, const int size) >+ { >+ for(int i = 0; i < size; i++) >+ { >+ ptr_->SetValue(i, io.readValue<primitiveT>()); >+ } >+ } >+ void readBinaryList(vtkFoamIOobject& io, const int size) >+ { >+ io.read(reinterpret_cast<unsigned char *>(ptr_->GetPointer(0)), >+ size * sizeof(primitiveT)); >+ } >+ void readValue(vtkFoamIOobject&, vtkFoamToken& currToken) >+ { >+ if(!currToken.is<primitiveT>()) >+ { >+ throw vtkFoamError() << "Expected an integer or a (, found " >+ << currToken; >+ } >+ ptr_->InsertNextValue(currToken.to<primitiveT>()); >+ } >+ }; >+ >+ // reads rank 1 lists of types vector, sphericalTensor, symmTensor >+ // and tensor. if isPositions is true it reads Cloud type of data as >+ // particle positions. cf. (the positions format) >+ // src/lagrangian/basic/particle/particleIO.C >+ template <typename listT, typename primitiveT, >+ int nComponents, bool isPositions> class vectorListTraits >+ { >+ listT *ptr_; >+ >+ public: >+ vectorListTraits(): ptr_(listT::New()) >+ { ptr_->SetNumberOfComponents(nComponents); } >+ listT *ptr() { return ptr_; } >+ void readUniformValues(vtkFoamIOobject& io, const int size) >+ { >+ io.readExpecting('('); >+ primitiveT vectorValue[nComponents]; >+ for(int j = 0; j < nComponents; j++) >+ { >+ vectorValue[j] = io.readValue<primitiveT>(); >+ } >+ for(int i = 0; i < size; i++) >+ { >+ ptr_->SetTuple(i, vectorValue); >+ } >+ io.readExpecting(')'); >+ if(isPositions) >+ { >+ // skip label celli >+ io.readValue<int>(); >+ } >+ } >+ void readAsciiList(vtkFoamIOobject& io, const int size) >+ { >+ for(int i = 0; i < size; i++) >+ { >+ io.readExpecting('('); >+ primitiveT *vectorTupleI = ptr_->GetPointer(nComponents * i); >+ for(int j = 0; j < nComponents; j++) >+ { >+ vectorTupleI[j] = io.readValue<primitiveT>(); >+ } >+ io.readExpecting(')'); >+ if(isPositions) >+ { >+ // skip label celli >+ io.readValue<int>(); >+ } >+ } >+ } >+ void readBinaryList(vtkFoamIOobject& io, const int size) >+ { >+ if(isPositions) // lagrangian/positions (class Cloud) >+ { >+ // allocate space along with the larger 1.4 format since the >+ // size must be determined at compile-time. we allocate on the >+ // stack to avoid leak when an exception is thrown. >+ unsigned char buffer[sizeof(double) * (nComponents + 1) >+ + 2 * sizeof(int)]; >+ const int nBytes = (io.getIs13Positions() >+ // skip label celli >+ ? sizeof(double) * nComponents + sizeof(int) >+ // skip label celli, label facei and scalar stepFraction >+ : sizeof(double) * (nComponents + 1) + 2 * sizeof(int)); >+ for(int i = 0; i < size; i++) >+ { >+ io.readExpecting('('); >+ io.read(buffer, nBytes); >+ ptr_->SetTuple(i, reinterpret_cast<double *>(buffer)); >+ io.readExpecting(')'); >+ } >+ } >+ else >+ { >+ for(int i = 0; i < size; i++) >+ { >+ double buffer[nComponents]; >+ io.read(reinterpret_cast<unsigned char *>(buffer), >+ sizeof(double) * nComponents); >+ ptr_->SetTuple(i, buffer); >+ } >+ } >+ } >+ void readValue(vtkFoamIOobject& io, vtkFoamToken& currToken) >+ { >+ if(currToken != '(') >+ { >+ throw vtkFoamError() << "Expected '(', found " << currToken; >+ } >+ primitiveT v[nComponents]; >+ for(int j = 0; j < nComponents; j++) >+ { >+ v[j] = io.readValue<primitiveT>(); >+ } >+ ptr_->InsertNextTuple(v); >+ io.readExpecting(')'); >+ } >+ }; >+ >+public: >+ vtkFoamEntryValue(vtkFoamEntry *upperEntryPtr) >+ : vtkFoamToken(), isUniform_(false), managed_(true), >+ upperEntryPtr_(upperEntryPtr) {} >+ vtkFoamEntryValue(vtkFoamEntryValue&, vtkFoamEntry *); >+ ~vtkFoamEntryValue() { clear(); } >+ >+ void setEmptyList() { clear(); isUniform_ = false; type_ = EMPTYLIST; } >+ bool isUniform() const { return isUniform_; } >+ void read(vtkFoamIOobject& io); >+ void readDictionary(vtkFoamIOobject& io, const vtkFoamToken& firstKeyword); >+ vtkIntArray& labelList() const { return *labelListPtr_; } >+ const intVectorVector& labelListList() const { return *labelListListPtr_; } >+ vtkFloatArray& scalarList() { return *scalarListPtr_; } >+ vtkFloatArray& vectorList() { return *vectorListPtr_; } >+ vtkFoamDict& dictionary() { return *dictPtr_; } >+ >+ void *ptr() >+ { >+ managed_ = false; // the returned pointer will not be deleted by the d'tor >+ return (void *)labelListPtr_; // all list pointers are in a single union >+ } >+ >+ vtkStdString toString() const >+ { return type_ == STRING ? vtkFoamToken::toString() : vtkStdString(); } >+ float toFloat() const >+ { >+ return type_ == SCALAR || type_ == LABEL ? vtkFoamToken::to<float>() : 0.0F; >+ } >+ double toDouble() const >+ { >+ return type_ == SCALAR || type_ == LABEL ? vtkFoamToken::to<double>() : 0.0; >+ } >+ int toInt() const >+ { return type_ == LABEL ? vtkFoamToken::to<int>() : 0; } >+ >+ // the following two are for an exceptional expression of >+ // `LABEL{LABELorSCALAR}' without type prefix (e. g. `2{-0}' in >+ // mixedRhoE B.C. in rhopSonicFoam/shockTube) >+ void makeLabelList(const int labelValue, const int size) >+ { >+ labelListPtr_ = vtkIntArray::New(); >+ type_ = LABELLIST; >+ vtkIntArray &ll = *labelListPtr_; >+ ll.SetNumberOfValues(size); >+ for(int i = 0; i < size; i++) >+ { >+ ll.SetValue(i, labelValue); >+ } >+ } >+ void makeScalarList(const float scalarValue, const int size) >+ { >+ scalarListPtr_ = vtkFloatArray::New(); >+ type_ = SCALARLIST; >+ vtkFloatArray& sl = *scalarListPtr_; >+ sl.SetNumberOfValues(size); >+ for(int i = 0; i < size; i++) >+ { >+ sl.SetValue(i, scalarValue); >+ } >+ } >+ >+ // reads dimensionSet >+ void readDimensionSet(vtkFoamIOobject& io) >+ { >+ const int nDims = 7; >+ labelListPtr_ = vtkIntArray::New(); >+ type_ = LABELLIST; >+ labelListPtr_->SetNumberOfValues(nDims); >+ for(int dimI = 0; dimI < nDims; dimI++) >+ { >+ labelListPtr_->SetValue(dimI, io.readValue<int>()); >+ } >+ io.readExpecting(']'); >+ } >+ >+ // generic reader for nonuniform lists. requires size prefix of the >+ // list to be present in the stream if the format is binary. >+ template <vtkFoamToken::tokenType listType, typename traitsT> >+ void readNonuniformList(vtkFoamIOobject& io) >+ { >+ vtkFoamToken currToken; >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ traitsT list; >+ type_ = listType; >+ vtkObjectPtr_ = list.ptr(); >+ if(currToken.is<int>()) >+ { >+ const int size = currToken.to<int>(); >+ if(size < 0) >+ { >+ throw vtkFoamError() << "List size must not be negative: size = " >+ << size; >+ } >+ list.ptr()->SetNumberOfTuples(size); >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ // some objects have lists with only one element enclosed by {} >+ // e. g. simpleFoam/pitzDaily3Blocks/constant/polyMesh/faceZones >+ if(currToken == '{') >+ { >+ list.readUniformValues(io, size); >+ io.readExpecting('}'); >+ return; >+ } >+ else if(currToken != '(') >+ { >+ throw vtkFoamError() << "Expected '(', found " << currToken; >+ } >+ else if(io.format() == vtkFoamIOobject::ASCII) >+ { >+ list.readAsciiList(io, size); >+ } >+ else >+ { >+ if(size > 0) // avoid invalid access to ll.at(0) >+ { >+ list.readBinaryList(io, size); >+ } >+ } >+ io.readExpecting(')'); >+ } >+ else if(currToken == '(') >+ { >+ while(io.read(currToken) && currToken != ')') >+ { >+ list.readValue(io, currToken); >+ } >+ list.ptr()->Squeeze(); >+ } >+ else >+ { >+ throw vtkFoamError() << "Expected integer or '(', found " << currToken; >+ } >+ } >+ >+ // reads a list of labelLists. requires size prefix of the listList >+ // to be present. size of each sublist must also be present in the >+ // stream if the format is binary. >+ void readLabelListList(vtkFoamIOobject& io) >+ { >+ vtkFoamToken currToken; >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ if(currToken.type() == vtkFoamToken::LABEL) >+ { >+ const int sizeI = currToken.to<int>(); >+ if(sizeI < 0) >+ { >+ throw vtkFoamError() << "List size must not be negative: size = " >+ << sizeI; >+ } >+ // gives initial guess for list size >+ labelListListPtr_ = new intVectorVector(sizeI, 4 * sizeI); >+ type_ = LABELLISTLIST; >+ io.readExpecting('('); >+ int bodyI = 0; >+ for(int i = 0; i < sizeI; i++) >+ { >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ if(currToken.type() == vtkFoamToken::LABEL) >+ { >+ const int sizeJ = currToken.to<int>(); >+ if(sizeJ < 0) >+ { >+ throw vtkFoamError() << "List size must not be negative: size = " >+ << sizeJ; >+ } >+ if(bodyI + sizeJ > labelListListPtr_->bodySize()) >+ { >+ const int newSize = labelListListPtr_->bodySize() + sizeJ; >+ labelListListPtr_->resizeBody(newSize); >+ } >+ io.readExpecting('('); >+ int *listI = labelListListPtr_->setIndex(i, bodyI); >+ if(io.format() == vtkFoamIOobject::ASCII) >+ { >+ for(int j = 0; j < sizeJ; j++) >+ { >+ listI[j] = io.readValue<int>(); >+ } >+ } >+ else >+ { >+ if(sizeJ > 0) // avoid invalid reference to labelListI.at(0) >+ { >+ io.read(reinterpret_cast<unsigned char*>(listI), >+ sizeJ * sizeof(int)); >+ } >+ } >+ bodyI += sizeJ; >+ io.readExpecting(')'); >+ } >+ else if(currToken == '(') >+ { >+ labelListListPtr_->setIndex(i, bodyI); >+ while(io.read(currToken) && currToken != ')') >+ { >+ if(currToken.type() != vtkFoamToken::LABEL) >+ { >+ throw vtkFoamError() << "Expected an integer, found " >+ << currToken; >+ } >+ if(bodyI >= labelListListPtr_->bodySize()) >+ { >+ const int newSize = labelListListPtr_->bodySize() + 1; >+ labelListListPtr_->resizeBody(newSize); >+ } >+ labelListListPtr_->setValue(bodyI++, currToken.to<int>()); >+ } >+ } >+ else >+ { >+ throw vtkFoamError() << "Expected integer or '(', found " >+ << currToken; >+ } >+ } >+ // set the next index of the last element to calculate the last >+ // subarray size >+ labelListListPtr_->setIndex(sizeI, bodyI); >+ // shrink to the actually used size >+ labelListListPtr_->resizeBody(bodyI); >+ io.readExpecting(')'); >+ } >+ else >+ { >+ throw vtkFoamError() << "Expected integer, found " << currToken; >+ } >+ } >+}; >+ >+template<> >+void vtkOpenFOAMReader::vtkFoamEntryValue::listTraits<vtkFloatArray, float> >+::readBinaryList(vtkFoamIOobject& io, const int size) >+{ >+ for(int i = 0; i < size; i++) >+ { >+ double buffer; >+ io.read(reinterpret_cast<unsigned char *>(&buffer), sizeof(double)); >+ ptr_->SetValue(i, static_cast<float>(buffer)); >+ } >+} >+ >+//----------------------------------------------------------------------------- >+// class vtkFoamEntry >+// a class that represents an entry of a dictionary. note that an >+// entry can have more than one value. >+struct vtkOpenFOAMReader::vtkFoamEntry >+{ >+private: >+ vtkStdString keyword_; >+ vtkstd::vector<vtkFoamEntryValue*> valuePtrs_; >+ vtkFoamDict *upperDictPtr_; >+ >+ vtkFoamEntry(); >+ >+public: >+ vtkFoamEntry(vtkFoamDict *upperDictPtr): upperDictPtr_(upperDictPtr) {} >+ vtkFoamEntry(const vtkFoamEntry& entry, vtkFoamDict *upperDictPtr) >+ : keyword_(entry.keyword()), valuePtrs_(entry.size()), >+ upperDictPtr_(upperDictPtr) >+ { >+ for(size_t valueI = 0; valueI < entry.size(); valueI++) >+ { >+ valuePtrs_[valueI] = new vtkFoamEntryValue(entry.value(valueI), this); >+ } >+ } >+ >+ ~vtkFoamEntry() { clear(); } >+ >+ void clear() >+ { >+ for(size_t i = 0; i < valuePtrs_.size(); i++) >+ { >+ delete valuePtrs_[i]; >+ } >+ valuePtrs_.clear(); >+ } >+ const vtkStdString& keyword() const { return keyword_; } >+ vtkStdString& keyword() { return keyword_; } >+ size_t size() const { return valuePtrs_.size(); } >+ // returns false if the number of the values is 0 to simplify things >+ bool found() const { return valuePtrs_.size() > 0; } >+ vtkFoamEntryValue& value(const int i) const { return *valuePtrs_[i]; } >+ vtkFoamEntryValue& firstValue() const { return *valuePtrs_[0]; } >+ vtkIntArray& labelList() const >+ { return firstValue().labelList(); } >+ const intVectorVector& labelListList() const >+ { return firstValue().labelListList(); } >+ vtkFloatArray& scalarList() >+ { return firstValue().scalarList(); } >+ vtkFloatArray& vectorList() >+ { return firstValue().vectorList(); } >+ vtkFoamDict& dictionary() // not using firstValue() for breaking constness >+ { return valuePtrs_[0]->dictionary(); } >+ void *ptr() { return firstValue().ptr(); } >+ vtkFoamDict *upperDictPtr() { return upperDictPtr_; } >+ >+ vtkStdString toString() const >+ { return found() ? firstValue().toString() : vtkStdString(); } >+ float toFloat() const >+ { return found() ? firstValue().toFloat() : 0.0F; } >+ double toDouble() const >+ { return found() ? firstValue().toDouble() : 0.0; } >+ int toInt() const >+ { return found() ? firstValue().toInt() : 0; } >+ >+ void readDictionary(vtkFoamIOobject& io) >+ { >+ valuePtrs_.push_back(new vtkFoamEntryValue(this)); >+ valuePtrs_.back()->readDictionary(io, vtkFoamToken()); >+ } >+ >+ // read values of an entry >+ void read(vtkFoamIOobject& io); >+}; >+ >+//----------------------------------------------------------------------------- >+// class vtkFoamDict >+// a class that holds a FoamFile data structure >+struct vtkOpenFOAMReader::vtkFoamDict: public vtkFoamEntryValue >+{ >+private: >+ vtkstd::vector<vtkFoamEntry*> entryPtrs_; >+ vtkFoamEntry *dummyEntryPtr_; >+ vtkFoamDict *upperDictPtr_; >+ >+ vtkFoamDict(const vtkFoamDict &); >+ >+public: >+ vtkFoamDict(vtkFoamDict *upperDictPtr = NULL) >+ : vtkFoamEntryValue(NULL), dummyEntryPtr_(NULL), upperDictPtr_(upperDictPtr) >+ { dictPtr_ = NULL; } // avoid destruction in vtkFoamEntryValue::clear() >+ vtkFoamDict(vtkFoamDict& dict, vtkFoamDict *upperDictPtr) >+ : vtkFoamEntryValue(dict, NULL), entryPtrs_(dict.size()), >+ dummyEntryPtr_(NULL), upperDictPtr_(upperDictPtr) >+ { >+ if(dict.type() == vtkFoamToken::DICTIONARY) >+ { >+ for(size_t entryI = 0; entryI < dict.size(); entryI++) >+ { >+ entryPtrs_[entryI] = new vtkFoamEntry(dict.entry(entryI), this); >+ } >+ } >+ } >+ >+ ~vtkFoamDict() >+ { >+ if(type_ == DICTIONARY) >+ { >+ for(size_t i = 0; i < entryPtrs_.size(); i++) >+ { >+ delete entryPtrs_[i]; >+ } >+ } >+ delete dummyEntryPtr_; >+ } >+ >+ size_t size() const { return entryPtrs_.size(); } >+ vtkFoamDict *upperDictPtr() { return upperDictPtr_; } >+ const vtkFoamEntry& entry(const int i) const { return *entryPtrs_[i]; } >+ vtkFoamEntry& entry(const int i) { return *entryPtrs_[i]; } >+ vtkFoamEntry& lookup(const vtkStdString& keyword) >+ { >+ if(type_ == DICTIONARY) >+ { >+ for(size_t i = 0; i < entryPtrs_.size(); i++) >+ { >+ if(entryPtrs_[i]->keyword() == keyword) // found >+ { >+ return *entryPtrs_[i]; >+ } >+ } >+ } >+ >+ // not found >+ if(dummyEntryPtr_ == NULL) >+ { >+ dummyEntryPtr_ = new vtkFoamEntry(NULL); >+ } >+ return *dummyEntryPtr_; >+ } >+ >+ // reads a FoamFile or a subdictionary. if the stream to be read is >+ // a subdictionary the preceding '{' is assumed to have already been >+ // thrown away. >+ bool read(vtkFoamIOobject& io, const bool isSubDictionary = false, >+ const vtkFoamToken& firstToken = vtkFoamToken()) >+ { >+ try >+ { >+ vtkFoamToken currToken; >+ if(firstToken.type() == vtkFoamToken::UNDEFINED) >+ { >+ if(!isSubDictionary) >+ { >+ if(io.className() == "scalarField") // lagrangian scalars >+ { >+ readNonuniformList<SCALARLIST, listTraits<vtkFloatArray, float> >( >+ io); >+ return true; >+ } >+ // polyMesh/points, lagrangian vectors >+ else if(io.className() == "sphericalTensorField") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 1, false> >(io); >+ return true; >+ } >+ else if(io.className() == "vectorField") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 3, false> >(io); >+ return true; >+ } >+ else if(io.className() == "symmTensorField") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 6, false> >(io); >+ return true; >+ } >+ else if(io.className() == "tensorField") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 9, false> >(io); >+ return true; >+ } >+ // lagrangian positions. there are many concrete class names >+ // e. g. Cloud<parcel>, basicKinematicCloud etc. >+ else if(io.className().find("Cloud") != vtkStdString::npos >+ && io.objectName() == "positions") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 3, true> >(io); >+ return true; >+ } >+ else if(io.className() == "faceList") // polyMesh/faces >+ { >+ readLabelListList(io); >+ return true; >+ } >+ else if(io.className() == "labelList") // polyMesh/{owner|neighbour} >+ { >+ readNonuniformList<LABELLIST, listTraits<vtkIntArray, int> >(io); >+ return true; >+ } >+ } >+ >+ // read the first token >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ >+ // list of dictionaries is read as a usual dictionary >+ // polyMesh/boundary, point/face/cell-Zones >+ if(!isSubDictionary && currToken.type() == vtkFoamToken::LABEL) >+ { >+ io.readExpecting('('); >+ if(currToken.to<int>() > 0) >+ { >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ // continue to read as a usual dictionary >+ } >+ else // return as empty dictionary >+ { >+ io.readExpecting(')'); >+ type_ = DICTIONARY; >+ return true; >+ } >+ } >+ // some boundary files does not have the number of boundary >+ // patches (e.g. settlingFoam/tank3D). in this case we need to >+ // explicitly read the file as a dictionary. >+ else if(!isSubDictionary && currToken == '(' >+ && io.className() == "polyBoundaryMesh") // polyMesh/boundary >+ { >+ if(!io.read(currToken)) // read the first keyword >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ if(currToken == ')') // return as empty dictionary >+ { >+ type_ = DICTIONARY; >+ return true; >+ } >+ } >+ // the following two else-if clauses are for an exceptional >+ // expression of `LABEL{LABELorSCALAR}' without type prefix >+ // (e. g. `2{-0}' in mixedRhoE B.C. in >+ // rhopSonicFoam/shockTube) >+ else if(isSubDictionary && currToken.type() == vtkFoamToken::LABEL) >+ { >+ vtkFoamToken::operator=(currToken.to<int>()); >+ type_ = UNIFORMLABELLIST; >+ io.readExpecting('}'); >+ return true; >+ } >+ else if(isSubDictionary && currToken.type() == vtkFoamToken::SCALAR) >+ { >+ vtkFoamToken::operator=(currToken.to<float>()); >+ type_ = UNIFORMSCALARLIST; >+ io.readExpecting('}'); >+ return true; >+ } >+ // return as empty dictionary >+ else if(isSubDictionary && currToken == '}') >+ { >+ type_ = DICTIONARY; >+ return true; >+ } >+ } >+ // if firstToken is given as string set read the following stream >+ // as subdictionary >+ else if(firstToken.type() == vtkFoamToken::STRING) >+ { >+ type_ = DICTIONARY; >+ entryPtrs_.push_back(new vtkFoamEntry(this)); >+ entryPtrs_.back()->keyword() = firstToken.toString(); >+ entryPtrs_.back()->readDictionary(io); >+ if(!io.read(currToken) || currToken == '}' || currToken == ')') >+ { >+ return true; >+ } >+ } >+ else // quite likely an identifier >+ { >+ currToken = firstToken; >+ } >+ >+ if(currToken == ';' || currToken.type() == vtkFoamToken::STRING >+ || currToken.type() == vtkFoamToken::IDENTIFIER) // general dictionary >+ { >+ // type must be set first so that lookup() works >+ type_ = DICTIONARY; >+ do >+ { >+ if(currToken.type() == vtkFoamToken::STRING) >+ { >+ vtkFoamEntry& previousEntry = lookup(currToken.toString()); >+ if(previousEntry.found()) >+ { >+ if(io.getInputMode() == vtkFoamFile::INPUT_MODE_MERGE) >+ { >+ if(previousEntry.firstValue().type() >+ == vtkFoamToken::DICTIONARY) >+ { >+ io.readExpecting('{'); >+ previousEntry.firstValue().dictionary().read(io, true); >+ } >+ else >+ { >+ previousEntry.clear(); >+ previousEntry.read(io); >+ } >+ } >+ else if(io.getInputMode() == vtkFoamFile::INPUT_MODE_OVERWRITE) >+ { >+ previousEntry.clear(); >+ previousEntry.read(io); >+ } >+ else // INPUT_MODE_ERROR >+ { >+ throw vtkFoamError() << "Found duplicated entries with keyword " >+ << currToken.toString(); >+ } >+ } >+ else >+ { >+ entryPtrs_.push_back(new vtkFoamEntry(this)); >+ entryPtrs_.back()->keyword() = currToken.toString(); >+ entryPtrs_.back()->read(io); >+ } >+ >+ if(currToken == "FoamFile") >+ { >+ // delete the FoamFile header subdictionary entry >+ delete entryPtrs_.back(); >+ entryPtrs_.pop_back(); >+ } >+ else if(currToken == "include") >+ { >+ // include the named file. Exiting the included file at >+ // EOF will be handled automatically by >+ // vtkFoamFile::closeIncludedFile() >+ if(entryPtrs_.back()->firstValue().type() != vtkFoamToken::STRING) >+ { >+ throw vtkFoamError() >+ << "Expected string as the file name to be included, found " >+ << entryPtrs_.back()->firstValue(); >+ } >+ vtkStdString includeFileName(entryPtrs_.back()->toString()); >+ delete entryPtrs_.back(); >+ entryPtrs_.pop_back(); >+ io.includeFile(includeFileName, io.filePath()); >+ } >+ } >+ else if(currToken.type() == vtkFoamToken::IDENTIFIER) >+ { >+ // substitute identifier >+ const vtkStdString identifier(currToken.toIdentifier()); >+ >+ for(vtkFoamDict *uDictPtr = this;;) >+ { >+ const vtkFoamEntry& >+ identifiedEntry = uDictPtr->lookup(identifier); >+ >+ if(identifiedEntry.found()) >+ { >+ if(identifiedEntry.firstValue().type() >+ != vtkFoamToken::DICTIONARY) >+ { >+ throw vtkFoamError() >+ << "Expected dictionary for substituting entry " >+ << identifier; >+ } >+ vtkFoamDict& identifiedDict >+ = identifiedEntry.firstValue().dictionary(); >+ for(size_t entryI = 0; entryI < identifiedDict.size(); entryI++) >+ { >+ // I think #inputMode handling should be done here >+ // as well, but the genuine FoamFile parser for OF >+ // 1.5 does not seem to be doing it. >+ entryPtrs_.push_back( >+ new vtkFoamEntry(identifiedDict.entry(entryI), this)); >+ } >+ break; >+ } >+ else >+ { >+ uDictPtr = uDictPtr->upperDictPtr(); >+ if(uDictPtr == NULL) >+ { >+ throw vtkFoamError() << "Substituting entry " << identifier >+ << " not found"; >+ } >+ } >+ } >+ } >+ // skip empty entry only with ';' >+ } while(io.read(currToken) >+ && (currToken.type() == vtkFoamToken::STRING >+ || currToken.type() == vtkFoamToken::IDENTIFIER || currToken == ';')); >+ >+ if(currToken.type() == vtkFoamToken::ERROR || currToken == '}' >+ || currToken == ')') >+ { >+ return true; >+ } >+ type_ = UNDEFINED; >+ throw vtkFoamError() >+ << "Expected keyword, closing brace, ';' or EOF, found " << currToken; >+ } >+ throw vtkFoamError() << "Expected keyword or identifier, found " >+ << currToken; >+ } >+ catch(vtkFoamError& e) >+ { >+ if(isSubDictionary) >+ { >+ throw; >+ } >+ else >+ { >+ io.setError(e); >+ return false; >+ } >+ } >+ } >+}; >+ >+void vtkOpenFOAMReader::vtkFoamIOobject::readHeader() >+{ >+ vtkFoamToken firstToken; >+ >+ readExpecting("FoamFile"); >+ readExpecting('{'); >+ >+ vtkFoamDict headerDict; >+ // throw exception in case of error >+ headerDict.read(*this, true, vtkFoamToken()); >+ >+ const vtkFoamEntry& formatEntry = headerDict.lookup("format"); >+ if(!formatEntry.found()) >+ { >+ throw vtkFoamError() >+ << "format entry (binary/ascii) not found in FoamFile header"; >+ } >+ // case does matter (e. g. "BINARY" is treated as ascii) >+ // cf. src/OpenFOAM/db/IOstreams/IOstreams/IOstream.C >+ format_ = (formatEntry.toString() == "binary" ? BINARY : ASCII); >+ >+ const vtkFoamEntry& classEntry = headerDict.lookup("class"); >+ if(!classEntry.found()) >+ { >+ throw vtkFoamError() << "class name not found in FoamFile header"; >+ } >+ headerClassName_ = classEntry.toString(); >+ >+ const vtkFoamEntry& objectEntry = headerDict.lookup("object"); >+ if(!objectEntry.found()) >+ { >+ throw vtkFoamError() << "object name not found in FoamFile header"; >+ } >+ objectName_ = objectEntry.toString(); >+} >+ >+vtkOpenFOAMReader::vtkFoamEntryValue::vtkFoamEntryValue( >+ vtkFoamEntryValue& value, vtkFoamEntry *upperEntryPtr) >+ : vtkFoamToken(value), isUniform_(value.isUniform()), managed_(true), >+ upperEntryPtr_(upperEntryPtr) >+{ >+ switch(type_) >+ { >+ case LABELLIST: case SCALARLIST: case VECTORLIST: case STRINGLIST: >+ vtkObjectPtr_ = value.toVTKObject(); >+ vtkObjectPtr_->Register(0); // increase reference count +1 >+ break; >+ case LABELLISTLIST: >+ labelListListPtr_ = new intVectorVector(*value.labelListListPtr_); >+ break; >+ case ENTRYVALUELIST: >+ { >+ const int nValues = value.entryValuePtrs_->size(); >+ entryValuePtrs_ = new vtkstd::vector<vtkFoamEntryValue*>(nValues); >+ for(int valueI = 0; valueI < nValues; valueI++) >+ { >+ entryValuePtrs_->operator[](valueI) = new vtkFoamEntryValue( >+ *value.entryValuePtrs_->operator[](valueI), upperEntryPtr_); >+ } >+ } >+ break; >+ case DICTIONARY: >+ // upperEntryPtr_ is null when called from vtkFoamDict constructor >+ if(upperEntryPtr_ != NULL) >+ { >+ dictPtr_ >+ = new vtkFoamDict(*value.dictPtr_, upperEntryPtr_->upperDictPtr()); >+ } >+ else >+ { >+ dictPtr_ = NULL; >+ } >+ break; >+ case EMPTYLIST: >+ break; >+ } >+} >+ >+void vtkOpenFOAMReader::vtkFoamEntryValue::clear() >+{ >+ if(managed_) >+ { >+ switch(type_) >+ { >+ case LABELLIST: case SCALARLIST: case VECTORLIST: case STRINGLIST: >+ vtkObjectPtr_->Delete(); >+ break; >+ case LABELLISTLIST: >+ delete labelListListPtr_; >+ break; >+ case ENTRYVALUELIST: >+ for(size_t valueI = 0; valueI < entryValuePtrs_->size() ; valueI++) >+ { >+ delete entryValuePtrs_->operator[](valueI); >+ } >+ delete entryValuePtrs_; >+ break; >+ case DICTIONARY: >+ delete dictPtr_; >+ break; >+ } >+ } >+} >+ >+// general-purpose list reader - guess the type of the list and read >+// it. only supports ascii format and assumes the preceding '(' has >+// already been thrown away. the reader supports nested list with >+// variable lengths (e. g. `((token token) (token token token)).' >+// also supports compound of tokens and lists (e. g. `((token token) >+// token)') only if a list comes as the first value. >+void vtkOpenFOAMReader::vtkFoamEntryValue::readList(vtkFoamIOobject& io) >+{ >+ vtkFoamToken currToken; >+ io.read(currToken); >+ >+ // initial guess of the list type >+ if(currToken.type() == vtkFoamToken::LABEL) >+ { >+ // if the first token is of type LABEL it might be either an element of >+ // a labelList or the size of a sublist so proceed to the next token >+ vtkFoamToken nextToken; >+ if(!io.read(nextToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ if(nextToken.type() == vtkFoamToken::LABEL) >+ { >+ labelListPtr_ = vtkIntArray::New(); >+ labelListPtr_->InsertNextValue(currToken.to<int>()); >+ labelListPtr_->InsertNextValue(nextToken.to<int>()); >+ type_ = LABELLIST; >+ } >+ else if(nextToken.type() == vtkFoamToken::SCALAR) >+ { >+ scalarListPtr_ = vtkFloatArray::New(); >+ scalarListPtr_->InsertNextValue(currToken.to<float>()); >+ scalarListPtr_->InsertNextValue(nextToken.to<float>()); >+ type_ = SCALARLIST; >+ } >+ else if(nextToken == '(') // list of list: read recursively >+ { >+ entryValuePtrs_ = new vtkstd::vector<vtkFoamEntryValue*>; >+ entryValuePtrs_->push_back(new vtkFoamEntryValue(upperEntryPtr_)); >+ entryValuePtrs_->back()->readList(io); >+ type_ = ENTRYVALUELIST; >+ } >+ else if(nextToken == ')') // list with only one label element >+ { >+ labelListPtr_ = vtkIntArray::New(); >+ labelListPtr_->SetNumberOfValues(1); >+ labelListPtr_->SetValue(0, currToken.to<int>()); >+ type_ = LABELLIST; >+ return; >+ } >+ else >+ { >+ throw vtkFoamError() << "Expected number, '(' or ')', found " >+ << nextToken; >+ } >+ } >+ else if(currToken.type() == vtkFoamToken::SCALAR) >+ { >+ scalarListPtr_ = vtkFloatArray::New(); >+ scalarListPtr_->InsertNextValue(currToken.to<float>()); >+ type_ = SCALARLIST; >+ } >+ // if the first word is a string we have to read another token to determine >+ // if the first word is a keyword for the following dictionary >+ else if(currToken.type() == vtkFoamToken::STRING) >+ { >+ vtkFoamToken nextToken; >+ if(!io.read(nextToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ if(nextToken.type() == vtkFoamToken::STRING) // list of strings >+ { >+ stringListPtr_ = vtkStringArray::New(); >+ stringListPtr_->InsertNextValue(currToken.toString()); >+ stringListPtr_->InsertNextValue(nextToken.toString()); >+ type_ = STRINGLIST; >+ } >+ // dictionary with the already read stringToken as the first keyword >+ else if(nextToken == '{') >+ { >+ if(currToken.toString() == "") >+ { >+ throw "Empty string is invalid as a keyword for dictionary entry"; >+ } >+ readDictionary(io, currToken); >+ // the dictionary read as list has the entry terminator ';' so >+ // we have to skip it >+ return; >+ } >+ else if(nextToken == ')') // list with only one string element >+ { >+ stringListPtr_ = vtkStringArray::New(); >+ stringListPtr_->SetNumberOfValues(1); >+ stringListPtr_->SetValue(0, currToken.toString()); >+ type_ = STRINGLIST; >+ return; >+ } >+ else >+ { >+ throw vtkFoamError() << "Expected string, '{' or ')', found " >+ << nextToken; >+ } >+ } >+ else if(currToken == '(') // list of lists: read recursively >+ { >+ entryValuePtrs_ = new vtkstd::vector<vtkFoamEntryValue*>; >+ entryValuePtrs_->push_back(new vtkFoamEntryValue(upperEntryPtr_)); >+ entryValuePtrs_->back()->readList(io); >+ // read all the following values as arbitrary entryValues >+ // the alphaContactAngle b.c. in multiphaseInterFoam/damBreak4phase >+ // reaquires this treatment (reading by readList() is not enough) >+ do >+ { >+ entryValuePtrs_->push_back(new vtkFoamEntryValue(upperEntryPtr_)); >+ entryValuePtrs_->back()->read(io); >+ } >+ while(*entryValuePtrs_->back() != ')' && *entryValuePtrs_->back() != '}' >+ && *entryValuePtrs_->back() != ';'); >+ >+ if(*entryValuePtrs_->back() != ')') >+ { >+ throw vtkFoamError() << "Expected ')' before " >+ << *entryValuePtrs_->back(); >+ } >+ >+ // delete ')' >+ delete entryValuePtrs_->back(); >+ entryValuePtrs_->pop_back(); >+ type_ = ENTRYVALUELIST; >+ return; >+ } >+ else if(currToken == ')') // empty list >+ { >+ type_ = EMPTYLIST; >+ return; >+ } >+ // FIXME: may (or may not) need identifier handling >+ >+ while(io.read(currToken) && currToken != ')') >+ { >+ if(type_ == LABELLIST) >+ { >+ if(currToken.type() == vtkFoamToken::SCALAR) // switch to scalarList >+ { >+ // labelListPtr_ and scalarListPtr_ are packed into a single union so >+ // we need a temprary pointer >+ vtkFloatArray* slPtr = vtkFloatArray::New(); >+ const int size = labelListPtr_->GetNumberOfTuples(); >+ slPtr->SetNumberOfValues(size + 1); >+ for(int i = 0; i < size; i++) >+ { >+ slPtr->SetValue(i, static_cast<float>(labelListPtr_->GetValue(i))); >+ } >+ labelListPtr_->Delete(); >+ slPtr->SetValue(size, currToken.to<float>()); >+ scalarListPtr_ = slPtr; // copy after labelListPtr_ is deleted >+ type_ = SCALARLIST; >+ } >+ else if(currToken.type() == vtkFoamToken::LABEL) >+ { >+ labelListPtr_->InsertNextValue(currToken.to<int>()); >+ } >+ else >+ { >+ throw vtkFoamError() << "Expected a number, found " << currToken; >+ } >+ } >+ else if(type_ == SCALARLIST) >+ { >+ if(currToken.is<float>()) >+ { >+ scalarListPtr_->InsertNextValue(currToken.to<float>()); >+ } >+ else >+ { >+ throw vtkFoamError() << "Expected a number, found " << currToken; >+ } >+ } >+ else if(type_ == STRINGLIST) >+ { >+ if(currToken.type() == vtkFoamToken::STRING) >+ { >+ stringListPtr_->InsertNextValue(currToken.toString()); >+ } >+ else >+ { >+ throw vtkFoamError() << "Expected a string, found " << currToken; >+ } >+ } >+ else if(type_ == ENTRYVALUELIST) >+ { >+ if(currToken.type() == vtkFoamToken::LABEL) >+ { >+ // skip the number of elements to make things simple >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ } >+ if(currToken != '(') >+ { >+ throw vtkFoamError() << "Expected '(', found " << currToken; >+ } >+ entryValuePtrs_->push_back(new vtkFoamEntryValue(upperEntryPtr_)); >+ entryValuePtrs_->back()->readList(io); >+ } >+ else >+ { >+ throw vtkFoamError() << "Unexpected token " << currToken; >+ } >+ } >+ >+ if(type_ == LABELLIST) >+ { >+ labelListPtr_->Squeeze(); >+ } >+ else if(type_ == SCALARLIST) >+ { >+ scalarListPtr_->Squeeze(); >+ } >+ else if(type_ == STRINGLIST) >+ { >+ stringListPtr_->Squeeze(); >+ } >+} >+ >+// a list of dictionaries is actually read as a dictionary >+void vtkOpenFOAMReader::vtkFoamEntryValue::readDictionary(vtkFoamIOobject& io, >+ const vtkFoamToken& firstKeyword) >+{ >+ dictPtr_ = new vtkFoamDict(upperEntryPtr_->upperDictPtr()); >+ type_ = DICTIONARY; >+ dictPtr_->read(io, true, firstKeyword); >+} >+ >+// guess the type of the given entry value and read it >+void vtkOpenFOAMReader::vtkFoamEntryValue::read(vtkFoamIOobject& io) >+{ >+ vtkFoamToken currToken; >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Unexpected EOF"; >+ } >+ >+ if(currToken == '{') >+ { >+ readDictionary(io, vtkFoamToken()); >+ return; >+ } >+ // for reading sublist from vtkFoamEntryValue::readList() or there >+ // are cases where lists without the (non)uniform keyword appear >+ // (e. g. coodles/pitsDaily/0/U, uniformFixedValue b.c.) >+ else if(currToken == '(') >+ { >+ readList(io); >+ return; >+ } >+ else if(currToken == '[') >+ { >+ readDimensionSet(io); >+ return; >+ } >+ else if(currToken == "uniform") >+ { >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() >+ << "Expected a uniform value or a list, found unexpected EOF"; >+ } >+ if(currToken == '(') >+ { >+ readList(io); >+ } >+ else if(currToken.type() == vtkFoamToken::LABEL >+ || currToken.type() == vtkFoamToken::SCALAR >+ || currToken.type() == vtkFoamToken::STRING) >+ { >+ vtkFoamToken::operator=(currToken); >+ } >+ else // unexpected punctuation token >+ { >+ throw vtkFoamError() << "Expected number, string or (, found " >+ << currToken; >+ } >+ isUniform_ = true; >+ } >+ else if(currToken == "nonuniform") >+ { >+ if(!io.read(currToken)) >+ { >+ throw vtkFoamError() << "Expected list type specifier, found EOF"; >+ } >+ isUniform_ = false; >+ if(currToken == "List<scalar>") >+ { >+ readNonuniformList<SCALARLIST, listTraits<vtkFloatArray, float> >(io); >+ } >+ else if(currToken == "List<sphericalTensor>") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 1, false> >(io); >+ } >+ else if(currToken == "List<vector>") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 3, false> >(io); >+ } >+ else if(currToken == "List<symmTensor>") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 6, false> >(io); >+ } >+ else if(currToken == "List<tensor>") >+ { >+ readNonuniformList<VECTORLIST, >+ vectorListTraits<vtkFloatArray, float, 9, false> >(io); >+ } >+ // List<bool> is read as List<label> >+ else if(currToken =="List<label>" || currToken == "List<bool>") >+ { >+ readNonuniformList<LABELLIST, listTraits<vtkIntArray, int> >(io); >+ } >+ // an empty list doesn't have a list type specifier >+ else if(currToken.type() == vtkFoamToken::LABEL >+ && currToken.to<int>() == 0) >+ { >+ type_ = EMPTYLIST; >+ io.readExpecting('('); >+ io.readExpecting(')'); >+ } >+ else >+ { >+ throw vtkFoamError() << "Unsupported nonuniform list type " << currToken; >+ } >+ } >+ // zones have list without a uniform/nonuniform keyword >+ // List<bool> is read as List<label> >+ // (e. g. flipMap entry in faceZones) >+ else if(currToken == "List<label>" || currToken == "List<bool>") >+ { >+ isUniform_ = false; >+ readNonuniformList<LABELLIST, listTraits<vtkIntArray, int> >(io); >+ } >+ else if(currToken.type() == vtkFoamToken::PUNCTUATION >+ || currToken.type() == vtkFoamToken::LABEL >+ || currToken.type() == vtkFoamToken::SCALAR >+ || currToken.type() == vtkFoamToken::STRING >+ || currToken.type() == vtkFoamToken::IDENTIFIER) >+ { >+ vtkFoamToken::operator=(currToken); >+ } >+} >+ >+// read values of an entry >+void vtkOpenFOAMReader::vtkFoamEntry::read(vtkFoamIOobject& io) >+{ >+ for(;;) >+ { >+ valuePtrs_.push_back(new vtkFoamEntryValue(this)); >+ valuePtrs_.back()->read(io); >+ >+ if(valuePtrs_.size() >= 2) >+ { >+ vtkFoamEntryValue& secondLastValue >+ = *valuePtrs_[valuePtrs_.size() - 2]; >+ if(secondLastValue.type() == vtkFoamToken::LABEL) >+ { >+ vtkFoamEntryValue& lastValue = *valuePtrs_.back(); >+ >+ // a zero-sized nonuniform list without prefixing "nonuniform" >+ // keyword nor list type specifier (i. e. `0()'; >+ // e. g. simpleEngine/0/polyMesh/pointZones) requires special >+ // care (one with nonuniform prefix is treated within >+ // vtkFoamEntryValue::read()). still this causes errornous >+ // behavior for `0 nonuniform 0()' but this should be extremely >+ // rare >+ if(lastValue.type() == vtkFoamToken::EMPTYLIST >+ && secondLastValue == 0) >+ { >+ delete valuePtrs_.back(); >+ valuePtrs_.pop_back(); // delete the last value >+ valuePtrs_.back()->setEmptyList(); // mark new last value as empty >+ } >+ // for an exceptional expression of `LABEL{LABELorSCALAR}' without >+ // type prefix (e. g. `2{-0}' in mixedRhoE B.C. in >+ // rhopSonicFoam/shockTube) >+ else if(lastValue.type() == vtkFoamToken::DICTIONARY) >+ { >+ if(lastValue.dictionary().type() == vtkFoamToken::UNIFORMLABELLIST) >+ { >+ const int size = secondLastValue.to<int>(); >+ const int value = lastValue.dictionary().to<int>(); >+ // delete last two values >+ delete valuePtrs_.back(); >+ valuePtrs_.pop_back(); >+ delete valuePtrs_.back(); >+ valuePtrs_.pop_back(); >+ // make new labelList >+ valuePtrs_.push_back(new vtkFoamEntryValue(this)); >+ valuePtrs_.back()->makeLabelList(value, size); >+ } >+ else if(lastValue.dictionary().type() >+ == vtkFoamToken::UNIFORMSCALARLIST) >+ { >+ const int size = secondLastValue.to<int>(); >+ const float value = lastValue.dictionary().to<float>(); >+ // delete last two values >+ delete valuePtrs_.back(); >+ valuePtrs_.pop_back(); >+ delete valuePtrs_.back(); >+ valuePtrs_.pop_back(); >+ // make new labelList >+ valuePtrs_.push_back(new vtkFoamEntryValue(this)); >+ valuePtrs_.back()->makeScalarList(value, size); >+ } >+ } >+ } >+ } >+ >+ if(valuePtrs_.back()->type() == vtkFoamToken::IDENTIFIER) >+ { >+ // substitute identifier >+ const vtkStdString identifier(valuePtrs_.back()->toIdentifier()); >+ delete valuePtrs_.back(); >+ valuePtrs_.pop_back(); >+ >+ for(vtkFoamDict *uDictPtr = upperDictPtr_;;) >+ { >+ const vtkFoamEntry& identifiedEntry = uDictPtr->lookup(identifier); >+ >+ if(identifiedEntry.found()) >+ { >+ for(size_t valueI = 0; valueI < identifiedEntry.size(); valueI++) >+ { >+ valuePtrs_.push_back( >+ new vtkFoamEntryValue(identifiedEntry.value(valueI), this)); >+ } >+ break; >+ } >+ else >+ { >+ uDictPtr = uDictPtr->upperDictPtr(); >+ if(uDictPtr == NULL) >+ { >+ throw vtkFoamError() << "substituting entry " << identifier >+ << " not found"; >+ } >+ } >+ } >+ } >+ else if(*valuePtrs_.back() == ';') >+ { >+ delete valuePtrs_.back(); >+ valuePtrs_.pop_back(); >+ break; >+ } >+ else if(valuePtrs_.back()->type() == vtkFoamToken::DICTIONARY) >+ { >+ // subdictionary is not suffixed by an entry terminator ';' >+ break; >+ } >+ else if(*valuePtrs_.back() == '}' || *valuePtrs_.back() == ')') >+ { >+ throw vtkFoamError() << "Unmatched " << *valuePtrs_.back(); >+ } >+ } >+} >+ >+//----------------------------------------------------------------------------- >+// constructor >+vtkOpenFOAMReader::vtkOpenFOAMReader() >+{ >+ vtkDebugMacro(<<"Constructor"); >+ this->SetNumberOfInputPorts(0); >+ >+ // INTIALIZE FILE NAME >+ this->FileName = NULL; >+ >+ // VTK CLASSES >+ this->PatchDataArraySelection = vtkDataArraySelection::New(); >+ this->CellDataArraySelection = vtkDataArraySelection::New(); >+ this->PointDataArraySelection = vtkDataArraySelection::New(); >+ this->LagrangianDataArraySelection = vtkDataArraySelection::New(); >+ >+ // Setup the Selection observer for the above selection arrays >+ this->SelectionObserver = vtkCallbackCommand::New(); >+ this->SelectionObserver >+ ->SetCallback(&vtkOpenFOAMReader::SelectionModifiedCallback); >+ this->SelectionObserver->SetClientData(this); >+ >+ this->PatchDataArraySelection >+ ->AddObserver(vtkCommand::ModifiedEvent,this->SelectionObserver); >+ this->CellDataArraySelection >+ ->AddObserver(vtkCommand::ModifiedEvent,this->SelectionObserver); >+ this->PointDataArraySelection >+ ->AddObserver(vtkCommand::ModifiedEvent,this->SelectionObserver); >+ this->LagrangianDataArraySelection >+ ->AddObserver(vtkCommand::ModifiedEvent,this->SelectionObserver); >+ >+ // Initialise the Selection status arrays >+ this->CellSelectionOldStatus = 0xffffffff; >+ this->PointSelectionOldStatus = 0xffffffff; >+ this->LagrangianSelectionOldStatus = 0xffffffff; >+ this->PatchSelectionOldStatus = 0xffffffff; >+ this->CellSelectionStatus = 0; >+ this->PointSelectionStatus = 0; >+ this->LagrangianSelectionStatus = 0; >+ this->PatchSelectionStatus = 0; >+ >+ // DATA COUNTS >+ this->NumCells = 0; >+ this->NumPoints = 0; >+ >+ this->VolFieldFiles = vtkStringArray::New(); >+ this->PointFieldFiles = vtkStringArray::New(); >+ this->LagrangianPaths = vtkStringArray::New(); >+ this->LagrangianFieldFiles = vtkStringArray::New(); >+ this->OldFileName = new vtkStdString; >+ this->PathPrefix = new vtkStdString; >+ this->PolyMeshPointsDir = vtkStringArray::New(); >+ this->PolyMeshFacesDir = vtkStringArray::New(); >+ >+ // DATA TIMES >+ this->NumberOfTimeSteps = 0; >+ this->Steps = NULL; >+ this->TimeNames = vtkStringArray::New(); >+ this->TimeStep = 0; >+ this->TimeStepRange[0] = 0; >+ this->TimeStepRange[1] = 0; >+ >+ // for creating cell-to-point translated data >+ this->CreateCellToPoint = 1; >+ this->CreateCellToPointOld = 1; >+ this->BoundaryPointMap = NULL; >+ this->AllBoundaries = NULL; >+ this->AllBoundariesPointMap = NULL; >+ this->InternalPoints = NULL; >+ >+ // for caching mesh >+ this->CacheMesh = 1; >+ this->TimeStepOld = -1; >+ this->InternalMesh = NULL; >+ this->BoundaryMesh = NULL; >+ this->BoundaryDict = NULL; >+ this->BoundaryPointMap = NULL; >+ this->FaceOwner = NULL; >+ this->PointZoneMesh = NULL; >+ this->FaceZoneMesh = NULL; >+ this->CellZoneMesh = NULL; >+ >+ // for decomposing polyhedra >+ this->DecomposePolyhedra = 1; >+ this->DecomposePolyhedraOld = 1; >+ this->AdditionalCellIds = NULL; >+ this->AdditionalCellPoints = NULL; >+ >+ // for accumulating patches across time-steps (Turned on by default) >+ // As of now, only accumulation of patches is implemented >+ this->KeepPatches = 1; >+ this->KeepPatchesOld = 1; >+ >+ // for reading old binary lagrangian/positions format >+ this->PositionsIsIn13Format = 0; // turned off by default >+ this->PositionsIsIn13FormatOld = 0; >+ >+ // for reading zones >+ this->ReadZones = 0; // turned off by default >+ this->ReadZonesOld = 0; >+ >+ // determine if time directories are to be listed according to controlDict >+ this->ListTimeStepsByControlDict = 0; >+ this->ListTimeStepsByControlDictOld = 0; >+ >+ // add dimensions to array names >+ this->AddDimensionsToArrayNames = 0; >+ this->AddDimensionsToArrayNamesOld = 0; >+} >+ >+//----------------------------------------------------------------------------- >+// destructor >+vtkOpenFOAMReader::~vtkOpenFOAMReader() >+{ >+ vtkDebugMacro(<<"DeConstructor"); >+ >+ // Delete the Observers before deleting the Selection Arrays !!! >+ this->PatchDataArraySelection->RemoveObserver(this->SelectionObserver); >+ this->CellDataArraySelection->RemoveObserver(this->SelectionObserver); >+ this->PointDataArraySelection->RemoveObserver(this->SelectionObserver); >+ this->LagrangianDataArraySelection->RemoveObserver(this->SelectionObserver); >+ >+ // Now delete the Selection Observer itself >+ this->SelectionObserver->Delete(); >+ >+ // Finally delete the Selection Arrays >+ this->PatchDataArraySelection->Delete(); >+ this->CellDataArraySelection->Delete(); >+ this->PointDataArraySelection->Delete(); >+ this->LagrangianDataArraySelection->Delete(); >+ >+ this->SetFileName(0); >+ delete this->OldFileName; >+ delete this->PathPrefix; >+ this->PolyMeshPointsDir->Delete(); >+ this->PolyMeshFacesDir->Delete(); >+ >+ delete [] this->Steps; >+ this->TimeNames->Delete(); >+ this->VolFieldFiles->Delete(); >+ this->PointFieldFiles->Delete(); >+ this->LagrangianPaths->Delete(); >+ this->LagrangianFieldFiles->Delete(); >+ >+ this->ClearMeshes(); >+ delete this->BoundaryDict; >+} >+ >+void vtkOpenFOAMReader::ClearInternalMeshes() >+{ >+ if(this->FaceOwner != NULL) >+ { >+ this->FaceOwner->Delete(); >+ this->FaceOwner = NULL; >+ } >+ if(this->InternalMesh != NULL) >+ { >+ this->InternalMesh->Delete(); >+ this->InternalMesh = NULL; >+ } >+ if(this->AdditionalCellIds != NULL) >+ { >+ this->AdditionalCellIds->Delete(); >+ this->AdditionalCellIds = NULL; >+ } >+ delete this->AdditionalCellPoints; >+ this->AdditionalCellPoints = NULL; >+ >+ delete this->PointZoneMesh; >+ this->PointZoneMesh = NULL; >+ delete this->FaceZoneMesh; >+ this->FaceZoneMesh = NULL; >+ delete this->CellZoneMesh; >+ this->CellZoneMesh = NULL; >+} >+ >+void vtkOpenFOAMReader::ClearBoundaryMeshes() >+{ >+ delete this->BoundaryMesh; >+ this->BoundaryMesh = NULL; >+ >+ delete this->BoundaryPointMap; >+ this->BoundaryPointMap = NULL; >+ >+ if(this->InternalPoints != NULL) >+ { >+ this->InternalPoints->Delete(); >+ this->InternalPoints = NULL; >+ } >+ if(this->AllBoundaries != NULL) >+ { >+ this->AllBoundaries->Delete(); >+ this->AllBoundaries = NULL; >+ } >+ if(this->AllBoundariesPointMap != NULL) >+ { >+ this->AllBoundariesPointMap->Delete(); >+ this->AllBoundariesPointMap = NULL; >+ } >+} >+ >+void vtkOpenFOAMReader::ClearMeshes() >+{ >+ this->ClearInternalMeshes(); >+ this->ClearBoundaryMeshes(); >+} >+ >+//----------------------------------------------------------------------------- >+// CanReadFile >+int vtkOpenFOAMReader::CanReadFile(const char * /* fileName */) >+{ >+ // so far CanReadFile does nothing. >+ return 1; >+} >+ >+//----------------------------------------------------------------------------- >+// RequestInformation >+int vtkOpenFOAMReader::RequestInformation( >+ vtkInformation *vtkNotUsed(request), >+ vtkInformationVector **vtkNotUsed(inputVector), >+ vtkInformationVector *outputVector) >+{ >+ if(!this->FileName || strlen(this->FileName) == 0) >+ { >+ vtkErrorMacro("FileName has to be specified!"); >+ return 0; >+ } >+ vtkDebugMacro(<<"Request Info: " <<this->FileName); >+ >+ if(*this->OldFileName != vtkStdString(this->FileName) >+ || this->ListTimeStepsByControlDict != this->ListTimeStepsByControlDictOld) >+ { >+ // updated this->OldFileName >+ *this->OldFileName = vtkStdString(this->FileName); >+ >+ // clear prior case information >+ this->TimeStepOld = -1; >+ delete [] this->Steps; >+ this->Steps = NULL; >+ >+ this->ClearMeshes(); >+ delete this->BoundaryDict; >+ this->BoundaryDict = NULL; >+ >+ this->CellDataArraySelection->RemoveAllArrays(); >+ this->PointDataArraySelection->RemoveAllArrays(); >+ this->LagrangianDataArraySelection->RemoveAllArrays(); >+ this->PatchDataArraySelection->RemoveAllArrays(); >+ >+ // make case information >+ if(!this->ReadControlDict(this->FileName)) >+ { >+ return 0; >+ } >+ if(this->NumberOfTimeSteps == 0) >+ { >+ vtkErrorMacro(<< this->FileName << " contains no timestep data."); >+ return 0; >+ } >+ this->TimeStepRange[0] = 0; >+ this->TimeStepRange[1] = this->NumberOfTimeSteps; >+ this->PopulatePolyMeshDirArrays(); >+ outputVector->GetInformationObject(0)->Set( >+ vtkStreamingDemandDrivenPipeline::TIME_STEPS(), this->Steps, >+ this->NumberOfTimeSteps); >+#if PARAVIEW_VERSION_MAJOR >= 3 >+ double timeRange[2]; >+ timeRange[0] = this->Steps[0]; >+ timeRange[1] = this->Steps[this->NumberOfTimeSteps - 1]; >+ outputVector->GetInformationObject(0)->Set( >+ vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2); >+#endif >+ } >+ >+ return this->MakeTimeStepData(true); >+} >+ >+//----------------------------------------------------------------------------- >+// RequestData >+int vtkOpenFOAMReader::RequestData( >+ vtkInformation *vtkNotUsed(request), >+ vtkInformationVector **vtkNotUsed(inputVector), >+ vtkInformationVector *outputVector) >+{ >+ vtkDebugMacro(<<"Request Data"); >+ vtkInformation* outInfo = outputVector->GetInformationObject(0); >+ vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::SafeDownCast( >+ outInfo->Get(vtkDataObject::DATA_OBJECT())); >+ >+ if(!this->FileName) >+ { >+ vtkErrorMacro("FileName has to be specified!"); >+ return 0; >+ } >+ >+ if(this->NumberOfTimeSteps == 0) >+ { >+ vtkErrorMacro(<< this->FileName << " contains no timestep data."); >+ return 0; >+ } >+ >+ if(this->TimeStep < this->TimeStepRange[0] >+ || this->TimeStep > this->TimeStepRange[1]) >+ { >+ vtkErrorMacro("TimeStep out of range"); >+ return 0; >+ } >+ >+#if PARAVIEW_VERSION_MAJOR >= 3 >+ if(outInfo->Has(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS())) >+ { >+ double* requestedTimeValues >+ = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_TIME_STEPS()); >+ int nSteps >+ = outInfo->Length(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); >+ double* steps >+ = outInfo->Get(vtkStreamingDemandDrivenPipeline::TIME_STEPS()); >+#if 0 >+ int timeI = 0; >+ while(timeI < nSteps - 1 && steps[timeI] < requestedTimeValues[0]) >+ { >+ timeI++; >+ } >+ this->TimeStep = timeI; >+ outInfo->Set(vtkDataObject::DATA_TIME_STEPS(), &steps[timeI], 1); >+#else >+ int minTimeI = 0; >+ if(nSteps > 0) >+ { >+ const double requestedTime = requestedTimeValues[0]; >+ double minTimeDiff = fabs(steps[0] - requestedTime); >+ for(int timeI = 1; timeI < nSteps; timeI++) >+ { >+ const double timeDiff = fabs(steps[timeI] - requestedTime); >+ if(timeDiff < minTimeDiff) >+ { >+ minTimeI = timeI; >+ minTimeDiff = timeDiff; >+ } >+ } >+ } >+ this->TimeStep = minTimeI; >+ outInfo->Set(vtkDataObject::DATA_TIME_STEPS(), &steps[minTimeI], 1); >+#endif >+ } >+#endif >+ >+ // find fields in this timestep >+ if(!this->MakeTimeStepData(false)) >+ { >+ return 0; >+ } >+ >+ // create dataset >+ const int ret = this->CreateDataSet(output, this->TimeStep); >+ >+ if(ret == 0) >+ { >+ return ret; >+ } >+ >+ // update selection status >+ this->CellSelectionOldStatus = this->CellSelectionStatus; >+ this->PointSelectionOldStatus = this->PointSelectionStatus; >+ this->LagrangianSelectionOldStatus = this->LagrangianSelectionStatus; >+ this->PatchSelectionOldStatus = this->PatchSelectionStatus; >+ this->CreateCellToPointOld = this->CreateCellToPoint; >+ this->DecomposePolyhedraOld = this->DecomposePolyhedra; >+ this->KeepPatchesOld = this->KeepPatches; >+ this->PositionsIsIn13FormatOld = this->PositionsIsIn13Format; >+ this->ReadZonesOld = this->ReadZones; >+ this->ListTimeStepsByControlDictOld = this->ListTimeStepsByControlDict; >+ this->AddDimensionsToArrayNamesOld = this->AddDimensionsToArrayNames; >+ >+ return ret; >+} >+ >+//----------------------------------------------------------------------------- >+// PrintSelf >+void vtkOpenFOAMReader::PrintSelf(ostream& os, vtkIndent indent) >+{ >+ vtkDebugMacro(<<"Print Self"); >+ this->Superclass::PrintSelf(os,indent); >+ os << indent << "File Name: " >+ << (this->FileName ? this->FileName : "(none)") << "\n"; >+// os << indent << "Number Of Nodes: " << this->NumPoints << "\n"; >+ os << indent << "Number Of Cells: " << this->NumCells << "\n"; >+ os << indent << "Number of Time Steps: " << this->NumberOfTimeSteps << endl; >+ os << indent << "TimeStepRange: " >+ << this->TimeStepRange[0] << " - " << this->TimeStepRange[1] >+ << endl; >+ os << indent << "TimeStep: " << this->TimeStep << endl; >+ return; >+} >+ >+//----------------------------------------------------------------------------- >+// cell selection list handlers >+int vtkOpenFOAMReader::GetNumberOfCellArrays() >+{ >+ return this->CellDataArraySelection->GetNumberOfArrays(); >+} >+ >+const char* vtkOpenFOAMReader::GetCellArrayName(int index) >+{ >+ return this->CellDataArraySelection->GetArrayName(index); >+} >+ >+int vtkOpenFOAMReader::GetCellArrayStatus(const char* name) >+{ >+ return this->CellDataArraySelection->ArrayIsEnabled(name); >+} >+ >+void vtkOpenFOAMReader::SetCellArrayStatus(const char* name, int status) >+{ >+ if(status) >+ { >+ this->CellDataArraySelection->EnableArray(name); >+ } >+ else >+ { >+ this->CellDataArraySelection->DisableArray(name); >+ } >+} >+ >+void vtkOpenFOAMReader::DisableAllCellArrays() >+{ >+ this->CellDataArraySelection->DisableAllArrays(); >+} >+ >+void vtkOpenFOAMReader::EnableAllCellArrays() >+{ >+ this->CellDataArraySelection->EnableAllArrays(); >+} >+ >+//----------------------------------------------------------------------------- >+// point selection list handlers >+int vtkOpenFOAMReader::GetNumberOfPointArrays() >+{ >+ return this->PointDataArraySelection->GetNumberOfArrays(); >+} >+ >+const char* vtkOpenFOAMReader::GetPointArrayName(int index) >+{ >+ return this->PointDataArraySelection->GetArrayName(index); >+} >+ >+int vtkOpenFOAMReader::GetPointArrayStatus(const char* name) >+{ >+ return this->PointDataArraySelection->ArrayIsEnabled(name); >+} >+ >+void vtkOpenFOAMReader::SetPointArrayStatus(const char* name, int status) >+{ >+ if(status) >+ { >+ this->PointDataArraySelection->EnableArray(name); >+ } >+ else >+ { >+ this->PointDataArraySelection->DisableArray(name); >+ } >+} >+ >+void vtkOpenFOAMReader::DisableAllPointArrays() >+{ >+ this->PointDataArraySelection->DisableAllArrays(); >+} >+ >+void vtkOpenFOAMReader::EnableAllPointArrays() >+{ >+ this->PointDataArraySelection->EnableAllArrays(); >+} >+ >+ >+//----------------------------------------------------------------------------- >+// lagrangian selection list handlers >+int vtkOpenFOAMReader::GetNumberOfLagrangianArrays() >+{ >+ return this->LagrangianDataArraySelection->GetNumberOfArrays(); >+} >+ >+const char* vtkOpenFOAMReader::GetLagrangianArrayName(int index) >+{ >+ return this->LagrangianDataArraySelection->GetArrayName(index); >+} >+ >+int vtkOpenFOAMReader::GetLagrangianArrayStatus(const char* name) >+{ >+ return this->LagrangianDataArraySelection->ArrayIsEnabled(name); >+} >+ >+void vtkOpenFOAMReader::SetLagrangianArrayStatus(const char* name, int status) >+{ >+ if(status) >+ { >+ this->LagrangianDataArraySelection->EnableArray(name); >+ } >+ else >+ { >+ this->LagrangianDataArraySelection->DisableArray(name); >+ } >+} >+ >+void vtkOpenFOAMReader::DisableAllLagrangianArrays() >+{ >+ this->LagrangianDataArraySelection->DisableAllArrays(); >+} >+ >+void vtkOpenFOAMReader::EnableAllLagrangianArrays() >+{ >+ this->LagrangianDataArraySelection->EnableAllArrays(); >+} >+ >+ >+//----------------------------------------------------------------------------- >+// patch selection list handlers >+int vtkOpenFOAMReader::GetNumberOfPatchArrays() >+{ >+ return this->PatchDataArraySelection->GetNumberOfArrays(); >+} >+ >+const char* vtkOpenFOAMReader::GetPatchArrayName(int index) >+{ >+ return this->PatchDataArraySelection->GetArrayName(index); >+} >+ >+int vtkOpenFOAMReader::GetPatchArrayStatus(const char* name) >+{ >+ return this->PatchDataArraySelection->ArrayIsEnabled(name); >+} >+ >+void vtkOpenFOAMReader::SetPatchArrayStatus(const char* name, int status) >+{ >+ if(status) >+ { >+ this->PatchDataArraySelection->EnableArray(name); >+ } >+ else >+ { >+ this->PatchDataArraySelection->DisableArray(name); >+ } >+} >+ >+void vtkOpenFOAMReader::DisableAllPatchArrays() >+{ >+ this->PatchDataArraySelection->DisableAllArrays(); >+} >+ >+void vtkOpenFOAMReader::EnableAllPatchArrays() >+{ >+ this->PatchDataArraySelection->EnableAllArrays(); >+} >+ >+//----------------------------------------------------------------------------- >+// selection observer >+void vtkOpenFOAMReader::SelectionModifiedCallback(vtkObject*, >+ unsigned long, void* clientdata, void*) >+{ >+ static_cast<vtkOpenFOAMReader*>(clientdata)->SelectionModified(true); >+} >+ >+unsigned long vtkOpenFOAMReader::CreateSelectionStatus( >+ vtkDataArraySelection *dataArraySelection, unsigned long selectionOldStatus) >+{ >+ // Change the pipeline modification time to force update >+ // Update the selection status to detect changes >+ >+ // Cell Selection Arrays >+ // we loop from the last element of the selection array since we'd >+ // like to place newly added variables to extra higher bits (we >+ // wouldn't like to move the locations of already existing variables) >+ unsigned long selectionStatus = 0; >+ for(int i = dataArraySelection->GetNumberOfArrays() - 1; i >= 0; i--) >+ { >+ selectionStatus = (selectionStatus << 1) >+ + dataArraySelection->GetArraySetting(i); >+ } >+ // if the status flag overflows we'd like to fall onto the safe side >+ // (properly refresh the dataset without mesh caching) so we use the >+ // last bit (LSB) as overflow control flag. if overflow occurs the >+ // LSB is negated from the old status >+ if(dataArraySelection->GetNumberOfArrays() >+ <= static_cast<int>(sizeof(selectionStatus) * 8 - 1)) >+ { >+ selectionStatus = (selectionStatus << 1) + (selectionOldStatus & 0x1); >+ } >+ else >+ { >+ selectionStatus = (selectionStatus << 1) + ((~selectionOldStatus) & 0x1); >+ } >+ >+ return selectionStatus; >+} >+ >+void vtkOpenFOAMReader::SelectionModified(const bool setModified) >+{ >+ this->CellSelectionStatus = this->CreateSelectionStatus( >+ this->CellDataArraySelection, this->CellSelectionOldStatus); >+ this->PointSelectionStatus = this->CreateSelectionStatus( >+ this->PointDataArraySelection, this->PointSelectionOldStatus); >+ this->LagrangianSelectionStatus = this->CreateSelectionStatus( >+ this->LagrangianDataArraySelection, this->LagrangianSelectionOldStatus); >+ this->PatchSelectionStatus = this->CreateSelectionStatus( >+ this->PatchDataArraySelection, this->PatchSelectionOldStatus); >+ >+ // Indicate that the pipeline needs to be updated (VTK Command) >+ if(setModified) >+ { >+ this->Modified(); >+ } >+} >+ >+ >+//----------------------------------------------------------------------------- >+void vtkOpenFOAMReader::GetFieldNames(const char *pathIn, >+ const bool isLagrangian, vtkStringArray *cellObjectNames, >+ vtkStringArray *pointObjectNames) >+{ >+ const vtkStdString tempPath(pathIn); >+ >+ // open the directory and get num of files >+ vtkDirectory * directory = vtkDirectory::New(); >+ if(!directory->Open(tempPath.c_str())) >+ { >+ // no data >+ directory->Delete(); >+ return; >+ } >+ >+ // loop over all files and locate valid fields >+ int nFieldFiles = directory->GetNumberOfFiles(); >+ for(int j = 0; j < nFieldFiles; j++) >+ { >+ const vtkStdString fieldFile(directory->GetFile(j)); >+ const int len = fieldFile.length(); >+ >+ // excluded extensions cf. src/OpenFOAM/OSspecific/Unix/Unix.C >+ if(!directory->FileIsDirectory(fieldFile.c_str()) >+ && fieldFile.substr(len - 1) != "~" >+ && (len < 4 || (fieldFile.substr(len - 4) != ".bak" >+ && fieldFile.substr(len - 4) != ".BAK" >+ && fieldFile.substr(len - 4) != ".old")) >+ && (len < 5 || fieldFile.substr(len - 5) != ".save")) >+ { >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(io.open(tempPath + "/" + fieldFile)) // file exists and readable >+ { >+ const vtkStdString& cn = io.className(); >+ if(isLagrangian) >+ { >+ if(cn == "scalarField" || cn == "vectorField" >+ || cn == "sphericalTensorField" || cn == "symmTensorField" >+ || cn == "tensorField") >+ { >+ // real file name >+ this->LagrangianFieldFiles->InsertNextValue(fieldFile); >+ // object name >+ pointObjectNames->InsertNextValue(io.objectName()); >+ } >+ } >+ else >+ { >+ if(cn == "volScalarField" || cn == "pointScalarField" >+ || cn == "volVectorField" || cn == "pointVectorField" >+ || cn == "volSphericalTensorField" >+ || cn == "pointSphericalTensorField" >+ || cn == "volSymmTensorField" || cn == "pointSymmTensorField" >+ || cn == "volTensorField" || cn == "pointTensorField") >+ { >+ if(cn.substr(0, 3) == "vol") >+ { >+ // real file name >+ this->VolFieldFiles->InsertNextValue(fieldFile); >+ // object name >+ cellObjectNames->InsertNextValue(io.objectName()); >+ } >+ else >+ { >+ this->PointFieldFiles->InsertNextValue(fieldFile); >+ pointObjectNames->InsertNextValue(io.objectName()); >+ } >+ } >+ } >+ io.close(); >+ } >+ } >+ } >+ pointObjectNames->Squeeze(); >+ if(isLagrangian) >+ { >+ this->LagrangianFieldFiles->Squeeze(); >+ } >+ else >+ { >+ this->VolFieldFiles->Squeeze(); >+ this->PointFieldFiles->Squeeze(); >+ cellObjectNames->Squeeze(); >+ } >+ directory->Delete(); >+} >+ >+//----------------------------------------------------------------------------- >+// locate laglangian clouds >+void vtkOpenFOAMReader::LocateLagrangianClouds( >+ vtkStringArray *lagrangianObjectNames, const vtkStdString &tempPath) >+{ >+ vtkDirectory *directory = vtkDirectory::New(); >+ if(directory->Open((tempPath + "/lagrangian").c_str())) >+ { >+ // search for sub-clouds (OF 1.5 format) >+ const int nFiles = directory->GetNumberOfFiles(); >+ bool isSubCloud = false; >+ for(int fileI = 0; fileI < nFiles; fileI++) >+ { >+ const vtkStdString fileNameI(directory->GetFile(fileI)); >+ const vtkStdString subCloudPath(vtkStdString("lagrangian/") + fileNameI); >+ if(fileNameI != "." && fileNameI != ".." >+ && directory->FileIsDirectory(fileNameI.c_str())) >+ { >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(io.open(tempPath + "/" + subCloudPath + "/positions") >+ && io.className().find("Cloud") != vtkStdString::npos >+ && io.objectName() == "positions") >+ { >+ isSubCloud = true; >+ if(this->LagrangianPaths->LookupValue(subCloudPath) == -1) >+ { >+ this->LagrangianPaths->InsertNextValue(subCloudPath.c_str()); >+ } >+ this->GetFieldNames((tempPath + "/" + subCloudPath).c_str(), true, >+ NULL, lagrangianObjectNames); >+ this->PatchDataArraySelection->AddArray(subCloudPath.c_str()); >+ } >+ } >+ } >+ // if there's no sub-cloud then OF < 1.5 format >+ if(!isSubCloud) >+ { >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(io.open(tempPath + "/lagrangian/positions") >+ && io.className() == "Cloud" && io.objectName() == "positions") >+ { >+ if(this->LagrangianPaths->LookupValue("lagrangian") == -1) >+ { >+ this->LagrangianPaths->InsertNextValue("lagrangian"); >+ } >+ this->GetFieldNames((tempPath + "/lagrangian").c_str(), true, NULL, >+ lagrangianObjectNames); >+ this->PatchDataArraySelection->AddArray("lagrangian"); >+ } >+ } >+ this->LagrangianPaths->Squeeze(); >+ } >+ directory->Delete(); >+} >+ >+//----------------------------------------------------------------------------- >+// create field data lists and cell/point array selection lists >+int vtkOpenFOAMReader::MakeTimeStepData(const bool listNextTimeStep) >+{ >+ // Read the patches from the boundary file into selection array >+ int timeState = this->TimeStep; >+ >+ if(this->BoundaryDict == NULL >+ || this->PolyMeshFacesDir->GetValue(timeState) != this->BoundaryDict->timeDir >+ || this->PatchSelectionStatus != this->PatchSelectionOldStatus) >+ { >+ delete this->BoundaryDict; >+ vtkFoamDict *boundaryDict = this->GatherBlocks("polyMesh/boundary", >+ timeState, true); >+ if(boundaryDict == NULL) >+ { >+ return 0; >+ } >+ this->BoundaryDict = new vtkFoamBoundaryDict; >+ this->BoundaryDict->timeDir = this->PolyMeshFacesDir->GetValue(timeState); >+ >+ // Add the internal mesh by default always >+ this->PatchDataArraySelection->AddArray("Internal Mesh"); >+ >+ // iterate through each entry in the boundary file >+ vtkFoamDict& boundaryDictRef = *boundaryDict; >+ int allBoundariesNextStartFace = 0; >+ for(size_t i = 0; i < boundaryDictRef.size(); i++) >+ { >+ vtkFoamEntry& boundaryEntryI = boundaryDictRef.entry(i); >+ vtkFoamEntry& nFacesEntry = boundaryEntryI.dictionary().lookup("nFaces"); >+ if(!nFacesEntry.found()) >+ { >+ vtkErrorMacro(<< "nFaces entry not found in boundary entry " >+ << boundaryEntryI.keyword().c_str()); >+ return 0; >+ } >+ const int nFaces = nFacesEntry.toInt(); >+ >+ // extract name of the current patch for insertion >+ const vtkStdString& boundaryNameI = boundaryEntryI.keyword(); >+ >+ // create BoundaryDict entry >+ this->BoundaryDict->push_back(vtkFoamBoundaryEntry()); >+ vtkFoamBoundaryEntry& BoundaryDictRef = this->BoundaryDict->back(); >+ BoundaryDictRef.nFaces = nFaces; >+ BoundaryDictRef.boundaryName = boundaryNameI; >+ vtkFoamEntry& startFaceEntry >+ = boundaryEntryI.dictionary().lookup("startFace"); >+ if(!startFaceEntry.found()) >+ { >+ vtkErrorMacro(<< "startFace entry not found in boundary entry " >+ << boundaryEntryI.keyword().c_str()); >+ return 0; >+ } >+ >+ BoundaryDictRef.startFace = startFaceEntry.toInt(); >+ vtkFoamEntry& typeEntry = boundaryEntryI.dictionary().lookup("type"); >+ if(!typeEntry.found()) >+ { >+ vtkErrorMacro(<< "type entry not found in boundary entry " >+ << boundaryEntryI.keyword().c_str()); >+ return 0; >+ } >+ const vtkStdString& typeNameI = typeEntry.toString(); >+ BoundaryDictRef.isPhysicalBoundary >+ = (typeNameI == "patch" || typeNameI == "wall"); >+ BoundaryDictRef.allBoundariesStartFace = allBoundariesNextStartFace; >+ if(BoundaryDictRef.isPhysicalBoundary) >+ { >+ allBoundariesNextStartFace += nFaces; >+ } >+ BoundaryDictRef.isActive = false; >+ // If the size of patch becomes zero, but KeepPatches is selected, >+ // do not remove from list, else, remove patch from list >+ if(this->PatchDataArraySelection->ArrayExists(boundaryNameI.c_str())) >+ { >+ if(nFaces <= 0 && !this->KeepPatches) >+ { >+ this->PatchDataArraySelection >+ ->RemoveArrayByName(boundaryNameI.c_str()); >+ } >+ // Mark boundary if selected for display >+ else if(this->GetPatchArrayStatus(boundaryNameI.c_str())) >+ { >+ BoundaryDictRef.isActive = true; >+ } >+ } >+ // the patch is added to list even if its size is zero, if >+ // KeepPatches is set to true >+ else >+ { >+ this->PatchDataArraySelection->AddArray(boundaryNameI.c_str()); >+ // patch selections are off by default >+ this->PatchDataArraySelection->DisableArray(boundaryNameI.c_str()); >+ } >+ } >+ >+ delete boundaryDict; >+ } >+ >+ // Add scalars and vectors to metadata >+ vtkStdString tempPath >+ = *this->PathPrefix + this->TimeNames->GetValue(this->TimeStep); >+ // do not do "RemoveAllArrays()" to accumulate array selections >+ // this->CellDataArraySelection->RemoveAllArrays(); >+ this->VolFieldFiles->Initialize(); >+ this->PointFieldFiles->Initialize(); >+ vtkStringArray *cellObjectNames = vtkStringArray::New(); >+ vtkStringArray *pointObjectNames = vtkStringArray::New(); >+ this->GetFieldNames(tempPath.c_str(), false, cellObjectNames, >+ pointObjectNames); >+ >+ vtkStringArray *lagrangianObjectNames = vtkStringArray::New(); >+ this->LagrangianFieldFiles->Initialize(); >+ if(listNextTimeStep) >+ { >+ this->LagrangianPaths->Initialize(); >+ } >+ this->LocateLagrangianClouds(lagrangianObjectNames, tempPath); >+ >+ // if the requested timestep is 0 then we also look at the next >+ // timestep to add extra objects that don't exist at timestep 0 into >+ // selection lists. Note the ObjectNames array will be recreated in >+ // RequestData() so we don't have to worry about duplicated fields. >+ if(listNextTimeStep && this->NumberOfTimeSteps >= 2 && this->TimeStep == 0) >+ { >+ const vtkStdString tempPath >+ = *this->PathPrefix + this->TimeNames->GetValue(1); >+ this->GetFieldNames(tempPath.c_str(), false, cellObjectNames, >+ pointObjectNames); >+ // if lagrangian clouds were not found at timestep 0 >+ if(this->LagrangianPaths->GetNumberOfTuples() == 0) >+ { >+ this->LocateLagrangianClouds(lagrangianObjectNames, tempPath); >+ } >+ } >+ >+#if PARAVIEW_VERSION_MAJOR >= 3 >+ // sort array names >+ vtkSortDataArray::Sort(cellObjectNames, this->VolFieldFiles); >+#endif >+ for(int nameI = 0; nameI < cellObjectNames->GetNumberOfValues(); nameI++) >+ { >+ this->CellDataArraySelection >+ ->AddArray(cellObjectNames->GetValue(nameI).c_str()); >+ } >+ cellObjectNames->Delete(); >+#if PARAVIEW_VERSION_MAJOR >= 3 >+ vtkSortDataArray::Sort(pointObjectNames, this->PointFieldFiles); >+#endif >+ for(int nameI = 0; nameI < pointObjectNames->GetNumberOfValues(); nameI++) >+ { >+ this->PointDataArraySelection >+ ->AddArray(pointObjectNames->GetValue(nameI).c_str()); >+ } >+ pointObjectNames->Delete(); >+#if PARAVIEW_VERSION_MAJOR >= 3 >+ vtkSortDataArray::Sort(lagrangianObjectNames, this->LagrangianFieldFiles); >+#endif >+ for(int nameI = 0; nameI < lagrangianObjectNames->GetNumberOfValues(); >+ nameI++) >+ { >+ this->LagrangianDataArraySelection >+ ->AddArray(lagrangianObjectNames->GetValue(nameI).c_str()); >+ } >+ lagrangianObjectNames->Delete(); >+ >+ // refresh selection status: should not change the Modified status >+ // when called from RequestInformation() nor RequestData(). >+ this->SelectionModified(false); >+ return 1; >+} >+ >+//----------------------------------------------------------------------------- >+// list time directories according to controlDict >+bool vtkOpenFOAMReader::ListTimeDirectoriesByControlDict(vtkFoamDict* dictPtr) >+{ >+ vtkFoamDict& dict = *dictPtr; >+ >+ vtkFoamEntry& startTimeEntry = dict.lookup("startTime"); >+ if(!startTimeEntry.found()) >+ { >+ vtkErrorMacro(<< "startTime entry not found in controlDict"); >+ return false; >+ } >+ // using double to precisely handle time values >+ const double startTime = startTimeEntry.toDouble(); >+ >+ vtkFoamEntry& endTimeEntry = dict.lookup("endTime"); >+ if(!endTimeEntry.found()) >+ { >+ vtkErrorMacro(<< "endTime entry not found in controlDict"); >+ return false; >+ } >+ const double endTime = endTimeEntry.toDouble(); >+ >+ vtkFoamEntry& deltaTEntry = dict.lookup("deltaT"); >+ if(!deltaTEntry.found()) >+ { >+ vtkErrorMacro(<< "deltaT entry not found in controlDict"); >+ return false; >+ } >+ const double deltaT = deltaTEntry.toDouble(); >+ >+ vtkFoamEntry& writeIntervalEntry = dict.lookup("writeInterval"); >+ if(!writeIntervalEntry.found()) >+ { >+ vtkErrorMacro(<< "writeInterval entry not found in controlDict"); >+ return false; >+ } >+ const double writeInterval = writeIntervalEntry.toDouble(); >+ >+ vtkFoamEntry& timeFormatEntry = dict.lookup("timeFormat"); >+ if(!timeFormatEntry.found()) >+ { >+ vtkErrorMacro(<< "timeFormat entry not found in controlDict"); >+ return false; >+ } >+ const vtkStdString timeFormat(timeFormatEntry.toString()); >+ >+ vtkFoamEntry& timePrecisionEntry = dict.lookup("timePrecision"); >+ const int timePrecision // default is 6 >+ = (timePrecisionEntry.found() ? timePrecisionEntry.toInt() : 6); >+ >+ // calculate the time step increment based on type of run >+ const vtkStdString writeControl(dict.lookup("writeControl").toString()); >+ double timeStepIncrement; >+ if(writeControl == "timeStep") >+ { >+ vtkDebugMacro(<<"Time step type data"); >+ timeStepIncrement = writeInterval * deltaT; >+ } >+ else if(writeControl == "runTime" || writeControl == "adjustableRunTime") >+ { >+ vtkDebugMacro(<<"Run time type data"); >+ timeStepIncrement = writeInterval; >+ } >+ else >+ { >+ vtkErrorMacro(<<"Time step can't be determined because writeControl is" >+ " set to " << writeControl.c_str()); >+ return false; >+ } >+ >+ // calculate how many timesteps there should be >+ const double tempResult = (endTime - startTime) / timeStepIncrement; >+ // +0.5 to round up >+ const int tempNumTimeSteps = static_cast<int>(tempResult + 0.5) + 1; >+ >+ // make sure time step dir exists >+ vtkstd::vector<double> tempSteps; >+ vtkDirectory *test = vtkDirectory::New(); >+ this->TimeNames->Initialize(); >+ >+ // determine time name based on Foam::Time::timeName() >+ // cf. src/OpenFOAM/db/Time/Time.C >+ vtksys_ios::ostringstream parser; >+#ifdef _MSC_VER >+ bool correctExponent = true; >+#endif >+ if(timeFormat == "general") >+ { >+ // "do not use std:: or vtkstd:: when using anything declared in >+ // iostream," according to VTK coding standards, but following >+ // the instruction causes errors... >+ parser.setf(vtkstd::ios_base::fmtflags(0), vtkstd::ios_base::floatfield); >+ } >+ else if(timeFormat == "fixed") >+ { >+ parser.setf(vtkstd::ios_base::fmtflags(vtkstd::ios_base::fixed), >+ vtkstd::ios_base::floatfield); >+#ifdef _MSC_VER >+ correctExponent = false; >+#endif >+ } >+ else if(timeFormat == "scientific") >+ { >+ parser.setf(vtkstd::ios_base::fmtflags(vtkstd::ios_base::scientific), >+ vtkstd::ios_base::floatfield); >+ } >+ else >+ { >+ vtkWarningMacro("Warning: unsupported time format. Assuming general."); >+ parser.setf(vtkstd::ios_base::fmtflags(0), vtkstd::ios_base::floatfield); >+ } >+ parser.precision(timePrecision); >+ >+ for(int i = 0; i < tempNumTimeSteps; i++) >+ { >+ parser.str(""); >+ const double tempStep = i * timeStepIncrement + startTime; >+ parser << tempStep; // stringstream doesn't require ends >+#ifdef _MSC_VER >+ // workaround for format difference in MSVC++: >+ // remove an extra 0 from exponent >+ if(correctExponent) >+ { >+ vtkStdString tempStr(parser.str()); >+ size_t pos = tempStr.find('e'); >+ if(pos != vtkStdString::npos && tempStr.length() >= pos + 3 >+ && tempStr[pos + 2] == '0') >+ { >+ tempStr.erase(pos + 2, 1); >+ parser.str(tempStr); >+ } >+ } >+#endif >+ if(test->Open((*this->PathPrefix + parser.str()).c_str())) >+ { >+ tempSteps.push_back(tempStep); >+ this->TimeNames->InsertNextValue(parser.str()); >+ } >+ // necessary for reading the case/0 directory whatever the timeFormat is >+ // based on Foam::Time::operator++() cf. src/OpenFOAM/db/Time/Time.C >+ else if((fabs(tempStep) < 1.0e-14L) // 10*SMALL >+ && test->Open((*this->PathPrefix + vtkStdString("0")).c_str())) >+ { >+ tempSteps.push_back(tempStep); >+ this->TimeNames->InsertNextValue(vtkStdString("0")); >+ } >+ } >+ test->Delete(); >+ this->TimeNames->Squeeze(); >+ >+ // Add the time steps that actually exist to steps >+ // allows the run to be stopped short of controlDict spec >+ // allows for removal of timesteps >+ this->NumberOfTimeSteps = tempSteps.size(); >+ if(this->NumberOfTimeSteps > 0) >+ { >+ this->Steps = new double[this->NumberOfTimeSteps]; >+ for(int i = 0; i < this->NumberOfTimeSteps; i++) >+ { >+ this->Steps[i] = tempSteps[i]; >+ } >+ } >+ else >+ { >+ // dummy for safely deleting later >+ this->Steps = new double[1]; >+ this->Steps[0] = startTime; >+ >+ // set the number of timesteps to 1 if the constant subdirectory exists >+ test = vtkDirectory::New(); >+ if(test->Open((*this->PathPrefix + "constant").c_str())) >+ { >+ parser.str(""); >+ parser << startTime; >+ this->TimeNames->InsertNextValue(parser.str()); >+ this->TimeNames->Squeeze(); >+ this->NumberOfTimeSteps = 1; >+ } >+ test->Delete(); >+ } >+ return true; >+} >+ >+//----------------------------------------------------------------------------- >+// list time directories by searching all valid time instances in a >+// case directory >+bool vtkOpenFOAMReader::ListTimeDirectoriesByInstances() >+{ >+ // open the case directory >+ vtkDirectory* test = vtkDirectory::New(); >+ if(!test->Open(this->PathPrefix->c_str())) >+ { >+ test->Delete(); >+ vtkErrorMacro(<< "Can't open directory " << this->PathPrefix->c_str()); >+ return false; >+ } >+ >+ // search all the directories in the case directory and detect >+ // directories with names convertible to numbers >+ this->TimeNames->Initialize(); >+ vtkDoubleArray* timeValues = vtkDoubleArray::New(); >+ const int nFiles = test->GetNumberOfFiles(); >+ for(int i = 0; i < nFiles; i++) >+ { >+ const vtkStdString dir = test->GetFile(i); >+ if(test->FileIsDirectory(dir.c_str())) >+ { >+ // check if the name is convertible to a number >+ bool isTimeDir = true; >+ for(size_t j = 0; j < dir.length(); j++) >+ { >+ const char c = dir[j]; >+ if(!isdigit(c) && c != '+' && c != '-' && c != '.' && c != 'e' >+ && c != 'E') >+ { >+ isTimeDir = false; >+ break; >+ } >+ } >+ if(!isTimeDir) >+ { >+ continue; >+ } >+ >+ // convert to a number >+ char *endptr; >+ double timeValue = strtod(dir.c_str(), &endptr); >+ // check if the value really was converted to a number >+ if(timeValue == 0.0 && endptr == dir.c_str()) >+ { >+ continue; >+ } >+ >+ // add to the instance list >+ timeValues->InsertNextValue(timeValue); >+ this->TimeNames->InsertNextValue(dir); >+ } >+ } >+ test->Delete(); >+ timeValues->Squeeze(); >+ this->TimeNames->Squeeze(); >+ >+ // sort the detected time directories and set as timesteps >+ this->NumberOfTimeSteps = this->TimeNames->GetSize(); >+ if(this->NumberOfTimeSteps > 0) >+ { >+ if(this->NumberOfTimeSteps > 1) >+ { >+ vtkSortDataArray::Sort(timeValues, this->TimeNames); >+ } >+ this->Steps = new double[this->NumberOfTimeSteps]; >+ for(int i = 0; i < this->NumberOfTimeSteps; i++) >+ { >+ this->Steps[i] = timeValues->GetValue(i); >+ } >+ } >+ else >+ { >+ // dummy for safely deleting later >+ this->Steps = new double[1]; >+ this->Steps[0] = 0.0; >+ >+ // set the number of timesteps to 1 if the constant subdirectory exists >+ test = vtkDirectory::New(); >+ if(test->Open((*this->PathPrefix + "constant").c_str())) >+ { >+ this->TimeNames->InsertNextValue("0"); >+ this->TimeNames->Squeeze(); >+ this->NumberOfTimeSteps = 1; >+ } >+ test->Delete(); >+ } >+ timeValues->Delete(); >+ >+ return true; >+} >+ >+//----------------------------------------------------------------------------- >+// reads the controlDict file >+// gather the necessary information to create a path to the data >+bool vtkOpenFOAMReader::ReadControlDict(const char* pathIn) >+{ >+#if defined(_WIN32) && PARAVIEW_VERSION_MAJOR >= 3 >+ const vtkStdString pathFindSeparator = "/\\", pathSeparator = "\\"; >+#else >+ const vtkStdString pathFindSeparator = "/", pathSeparator = "/"; >+#endif >+ vtkStdString path(pathIn); >+ >+ // determine the case directory and path to controlDict >+ size_t pos = path.find_last_of(pathFindSeparator); >+ if(pos == vtkStdString::npos) >+ { >+ // if there's no prepending path, prefix with the current directory >+ path = "." + pathSeparator + path; >+ pos = 1; >+ } >+ if(path.substr(pos + 1, 11) == "controlDict") >+ { >+ // remove trailing "/controlDict*" >+ *this->PathPrefix = path.substr(0, pos - 1); >+ if(*this->PathPrefix == ".") >+ { >+ *this->PathPrefix = ".." + pathSeparator; >+ } >+ else >+ { >+ pos = this->PathPrefix->find_last_of(pathFindSeparator); >+ if(pos == vtkStdString::npos) >+ { >+ *this->PathPrefix = "." + pathSeparator; >+ } >+ else >+ { >+ // remove trailing "system" (or any other directory name) >+ this->PathPrefix->erase(pos + 1); // preserve the last "/" >+ } >+ } >+ } >+ else >+ { >+ // if the file is named other than controlDict*, use the directory >+ // containing the file as case directory >+ *this->PathPrefix = path.substr(0, pos + 1); >+ path = *this->PathPrefix + "system" + pathSeparator + "controlDict"; >+ } >+ >+ // list timesteps (skip parsing controlDict entirely if >+ // ListTimeStepsByControlDict is set to 0) >+ if(this->ListTimeStepsByControlDict) >+ { >+ vtkFoamIOobject io(*this->PathPrefix); >+ >+ // open and check if controlDict is readable >+ if(!io.open(path)) >+ { >+ vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " >+ << io.error().c_str()); >+ return false; >+ } >+ vtkFoamDict dict; >+ if(!dict.read(io)) >+ { >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ return false; >+ } >+ if(dict.type() != vtkFoamToken::DICTIONARY) >+ { >+ vtkErrorMacro(<<"The file type of " << io.fileName().c_str() >+ << " is not a dictionary"); >+ return false; >+ } >+ >+ vtkFoamEntry& writeControlEntry = dict.lookup("writeControl"); >+ if(!writeControlEntry.found()) >+ { >+ vtkErrorMacro(<< "writeControl entry not found in " << pathIn); >+ return false; >+ } >+ const vtkStdString writeControl(writeControlEntry.toString()); >+ >+ // empty if not found >+ const vtkStdString adjustTimeStep(dict.lookup("adjustTimeStep").toString()); >+ >+ // list time directories according to controlDict if (adjustTimeStep >+ // writeControl) == (off, timeStep) or (on, adjustableRunTime); list >+ // by time instances in the case directory otherwise (different behavior >+ // from paraFoam) >+ // valid switching words cf. src/OpenFOAM/db/Switch/Switch.C >+ if((((adjustTimeStep == "off" || adjustTimeStep == "no" >+ || adjustTimeStep == "n" || adjustTimeStep == "false" >+ || adjustTimeStep == "") && writeControl == "timeStep") >+ || ((adjustTimeStep == "on" || adjustTimeStep == "yes" >+ || adjustTimeStep == "y" || adjustTimeStep == "true") >+ && writeControl == "adjustableRunTime"))) >+ { >+ return this->ListTimeDirectoriesByControlDict(&dict); >+ } >+ else >+ { >+ return this->ListTimeDirectoriesByInstances(); >+ } >+ } >+ >+ return this->ListTimeDirectoriesByInstances(); >+} >+ >+//----------------------------------------------------------------------------- >+void vtkOpenFOAMReader::AppendMeshDirToArray(vtkStringArray* polyMeshDir, >+ const char *pathIn, const int timeI) >+{ >+ vtkStdString path(pathIn); >+ vtkFoamIOobject io(*this->PathPrefix); >+ >+ if(io.open(path) || io.open(path + ".gz")) >+ { >+ io.close(); >+ // set points/faces location to current timesteps value >+ polyMeshDir->SetValue(timeI, this->TimeNames->GetValue(timeI)); >+ } >+ else >+ { >+ if(timeI != 0) >+ { >+ // set points/faces location to previous timesteps value >+ polyMeshDir->SetValue(timeI, polyMeshDir->GetValue(timeI - 1)); >+ } >+ else >+ { >+ // set points/faces to constant >+ polyMeshDir->SetValue(timeI, "constant"); >+ } >+ } >+} >+ >+//----------------------------------------------------------------------------- >+// create a Lookup Table containing the location of the points >+// and faces files for each time steps mesh >+void vtkOpenFOAMReader::PopulatePolyMeshDirArrays() >+{ >+ vtkDebugMacro(<<"Create list of points/faces file directories"); >+ >+ // intialize size to number of timesteps >+ this->PolyMeshPointsDir->SetNumberOfValues(this->NumberOfTimeSteps); >+ this->PolyMeshFacesDir->SetNumberOfValues(this->NumberOfTimeSteps); >+ >+ // loop through each timestep >+ for(int i = 0; i < this->NumberOfTimeSteps; i++) >+ { >+ // create the path to the timestep >+ vtkStdString polyMeshPath >+ = *this->PathPrefix + this->TimeNames->GetValue(i) + "/polyMesh/"; >+ AppendMeshDirToArray(this->PolyMeshPointsDir, >+ (polyMeshPath + "points").c_str(), i); >+ AppendMeshDirToArray(this->PolyMeshFacesDir, >+ (polyMeshPath + "faces").c_str(), i); >+ } >+ vtkDebugMacro(<<"Points/faces list created"); >+ return; >+} >+ >+//----------------------------------------------------------------------------- >+// read the points file into a vtkFloatArray >+vtkFloatArray* vtkOpenFOAMReader::ReadPointsFile(int timeState) >+{ >+ // path to points file >+ vtkStdString pointPath = *this->PathPrefix + >+ this->PolyMeshPointsDir->GetValue(timeState) + "/polyMesh/points"; >+ vtkDebugMacro(<<"Read points file: "<<pointPath.c_str()); >+ >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(!(io.open(pointPath) || io.open(pointPath + ".gz"))) >+ { >+ vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " >+ << io.error().c_str()); >+ return NULL; >+ } >+ vtkFoamDict dict; >+ if(!dict.read(io)) >+ { >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ return NULL; >+ } >+ if(dict.type() != vtkFoamToken::VECTORLIST) >+ { >+ vtkErrorMacro(<<"The file type of " << io.fileName().c_str() >+ << " is not a vectorList"); >+ return NULL; >+ } >+ >+ vtkFloatArray *pointArray = static_cast<vtkFloatArray *>(dict.ptr()); >+ >+ // set the number of points >+ this->NumPoints = pointArray->GetNumberOfTuples(); >+ >+ vtkDebugMacro(<<"Point file read"); >+ return pointArray; >+} >+ >+//----------------------------------------------------------------------------- >+// read the faces into a intVectorVector >+vtkOpenFOAMReader::intVectorVector* vtkOpenFOAMReader::ReadFacesFile( >+ const char* facePathIn) >+{ >+ const vtkStdString facePath(facePathIn); >+ vtkDebugMacro(<<"Read faces file: "<<facePath.c_str()); >+ >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(!(io.open(facePath) || io.open(facePath + ".gz"))) >+ { >+ vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " >+ << io.error().c_str()); >+ return NULL; >+ } >+ vtkFoamDict dict; >+ if(!dict.read(io)) >+ { >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ return NULL; >+ } >+ if(dict.type() != vtkFoamToken::LABELLISTLIST) >+ { >+ vtkErrorMacro(<<"The file type of " << io.fileName().c_str() >+ << " is not a labelListList"); >+ return NULL; >+ } >+ >+ vtkDebugMacro(<<"Faces read"); >+ return static_cast<intVectorVector *>(dict.ptr()); >+} >+ >+//----------------------------------------------------------------------------- >+// read the owner and neighbor file and create cellFaces >+bool vtkOpenFOAMReader::ReadOwnerNeighborFiles(vtkIntArray *cellFacesList, >+ vtkIntArray *cellFacesIndices, const char* ownerPathIn, >+ const char* neighborPathIn) >+{ >+ const vtkStdString ownerPath(ownerPathIn); >+ vtkDebugMacro(<<"Read owner file: "<<ownerPath.c_str()); >+ >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(!(io.open(ownerPath) || io.open(ownerPath + ".gz"))) >+ { >+ vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " >+ << io.error().c_str()); >+ return false; >+ } >+ vtkFoamDict ownerDict; >+ if(!ownerDict.read(io)) >+ { >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ return false; >+ } >+ if(ownerDict.type() != vtkFoamToken::LABELLIST) >+ { >+ vtkErrorMacro(<<"The file type of " << io.fileName().c_str() >+ << " is not a labelList"); >+ return false; >+ } >+ io.close(); >+ >+ const vtkStdString neighborPath(neighborPathIn); >+ vtkDebugMacro(<<"Read neighbor file: "<<neighborPath.c_str()); >+ >+ if(!(io.open(neighborPath) || io.open(neighborPath + ".gz"))) >+ { >+ vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " >+ << io.error().c_str()); >+ return false; >+ } >+ vtkFoamDict neighborDict; >+ if(!neighborDict.read(io)) >+ { >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ return false; >+ } >+ if(neighborDict.type() != vtkFoamToken::LABELLIST) >+ { >+ vtkErrorMacro(<<"The file type of " << io.fileName().c_str() >+ << " is not a labelList"); >+ return false; >+ } >+ >+ this->FaceOwner = static_cast<vtkIntArray *>(ownerDict.ptr()); >+ vtkIntArray &faceOwner = *this->FaceOwner; >+ vtkIntArray &faceNeighbor = neighborDict.labelList(); >+ >+ const int nFaces = faceOwner.GetNumberOfTuples(); >+ const int nNeiFaces = faceNeighbor.GetNumberOfTuples(); >+ >+ if(nFaces < nNeiFaces) >+ { >+ vtkErrorMacro(<<"Numbers of owner faces (" << nFaces >+ << ") must be equal or larger than number of neighbor faces (" >+ << nNeiFaces << ")"); >+ return false; >+ } >+ >+ if(nFaces == 0) >+ { >+ vtkWarningMacro(<<"The mesh contains no faces"); >+ } >+ >+ // add the face numbers to the correct cell >+ // cf. Terry's code and src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCells.C >+ >+ // find the number of cells >+ int nCells = -1; >+ for(int faceI = 0; faceI < nNeiFaces; faceI++) >+ { >+ const int ownerCell = faceOwner.GetValue(faceI); >+ if(nCells < ownerCell) // max(nCells, faceOwner[i]) >+ { >+ nCells = ownerCell; >+ } >+ // we do need to take neighbor faces into account since all the >+ // surrounding faces of a cell can be neighbors for a valid mesh >+ const int neighborCell = faceNeighbor.GetValue(faceI); >+ if(nCells < neighborCell) // max(nCells, faceNeighbor[i]) >+ { >+ nCells = neighborCell; >+ } >+ } >+ for(int faceI = nNeiFaces; faceI < nFaces; faceI++) >+ { >+ const int ownerCell = faceOwner.GetValue(faceI); >+ if(nCells < ownerCell) // max(nCells, faceOwner[i]) >+ { >+ nCells = ownerCell; >+ } >+ } >+ nCells++; >+ >+ if(nCells == 0) >+ { >+ vtkWarningMacro(<<"The mesh contains no cells"); >+ } >+ >+ // set the number of cells >+ this->NumCells = nCells; >+ >+ // count number of faces for each cell >+ cellFacesIndices->SetNumberOfValues(nCells + 1); >+ int *cfiPtr = cellFacesIndices->GetPointer(0); >+ for(int cellI = 0; cellI <= nCells; cellI++) >+ { >+ cfiPtr[cellI] = 0; >+ } >+ int nTotalCellFaces = 0; >+ cfiPtr++; // offset +1 >+ for(int faceI = 0; faceI < nNeiFaces; faceI++) >+ { >+ const int ownerCell = faceOwner.GetValue(faceI); >+ // simpleFoam/pitzDaily3Blocks has faces with owner cell number -1 >+ if(ownerCell >= 0) >+ { >+ cfiPtr[ownerCell]++; >+ nTotalCellFaces++; >+ } >+ const int neighborCell=faceNeighbor.GetValue(faceI); >+ if(neighborCell >= 0) >+ { >+ cfiPtr[neighborCell]++; >+ nTotalCellFaces++; >+ } >+ } >+ for(int faceI = nNeiFaces; faceI < nFaces; faceI++) >+ { >+ const int ownerCell = faceOwner.GetValue(faceI); >+ if(ownerCell >= 0) >+ { >+ cfiPtr[ownerCell]++; >+ nTotalCellFaces++; >+ } >+ } >+ cfiPtr--; // revert offset +1 >+ >+ // allocate cellFaces. To reduce the numbers of new/delete operations we >+ // allocate memory space for all faces linearly >+ cellFacesList->SetNumberOfValues(nTotalCellFaces); >+ >+ // accumulate the number of cellFaces to create cellFaces indices >+ // and copy them to a temporary array >+ vtkIntArray *tmpFaceIndices = vtkIntArray::New(); >+ tmpFaceIndices->SetNumberOfValues(nCells + 1); >+ int *tfiPtr = tmpFaceIndices->GetPointer(0); >+ tfiPtr[0] = 0; >+ for(int cellI = 1; cellI <= nCells; cellI++) >+ { >+ tfiPtr[cellI] = (cfiPtr[cellI] += cfiPtr[cellI - 1]); >+ } >+ >+ // add face numbers to cell-faces list >+ for(int faceI = 0; faceI < nNeiFaces; faceI++) >+ { >+ const int ownerCell = faceOwner.GetValue(faceI); // must be a signed int >+ // simpleFoam/pitzDaily3Blocks has faces with owner cell number -1 >+ if(ownerCell >= 0) >+ { >+ cellFacesList->SetValue(tfiPtr[ownerCell]++, faceI); >+ } >+ const int neighborCell = faceNeighbor.GetValue(faceI); >+ if(neighborCell >= 0) >+ { >+ cellFacesList->SetValue(tfiPtr[neighborCell]++, faceI); >+ } >+ } >+ for(int faceI = nNeiFaces; faceI < nFaces; faceI++) >+ { >+ const int ownerCell = faceOwner.GetValue(faceI); // must be a signed int >+ // simpleFoam/pitzDaily3Blocks has faces with owner cell number -1 >+ if(ownerCell >= 0) >+ { >+ cellFacesList->SetValue(tfiPtr[ownerCell]++, faceI); >+ } >+ } >+ tmpFaceIndices->Delete(); >+ >+ vtkDebugMacro(<<"Owner and neighbour files read"); >+ return true; >+} >+ >+//----------------------------------------------------------------------------- >+// determine cell shape and insert the cell into the mesh >+// hexahedron, prism, pyramid, tetrahedron and decompose polyhedron >+void vtkOpenFOAMReader::InsertCellsToGrid(vtkUnstructuredGrid* internalMesh, >+ vtkIntArray *cellFacesList, vtkIntArray *cellFacesIndices, >+ const intVectorVector *facesPoints, vtkFloatArray *pointArray, >+ vtkIdTypeArray *additionalCells, vtkIntArray *cellList) >+{ >+ const int maxNPoints = 128; // assume max number of points per cell >+ vtkIdList* cellPoints = vtkIdList::New(); >+ cellPoints->SetNumberOfIds(maxNPoints); >+ const int nCells >+ = (cellList == NULL ? this->NumCells : cellList->GetNumberOfTuples()); >+ int nAdditionalPoints = 0; >+ >+ // alias >+ const intVectorVector& facePoints = *facesPoints; >+ >+ for(int cellI = 0; cellI < nCells ; cellI++) >+ { >+ int cellId; >+ if(cellList == NULL) >+ { >+ cellId = cellI; >+ } >+ else >+ { >+ cellId = cellList->GetValue(cellI); >+ if(cellId >= this->NumCells) >+ { >+ vtkWarningMacro(<<"cellLabels id " << cellId >+ << " exceeds the number of cells " << nCells); >+ internalMesh->InsertNextCell(VTK_EMPTY_CELL, 0, >+ cellPoints->GetPointer(0)); >+ continue; >+ } >+ } >+ const int cfi = cellFacesIndices->GetValue(cellId); >+ const int *cellFaces = cellFacesList->GetPointer(cfi); >+ const int nCellFaces = cellFacesIndices->GetValue(cellId + 1) - cfi; >+ >+ // determine type of the cell >+ // cf. src/OpenFOAM/meshes/meshShapes/cellMatcher/{hex|prism|pyr|tet}- >+ // Matcher.C >+ int cellType = VTK_CONVEX_POINT_SET; >+ if(nCellFaces == 6) >+ { >+ int j = 0; >+ for(; j < nCellFaces; j++) >+ { >+ if(facePoints.size(cellFaces[j]) != 4) >+ { >+ break; >+ } >+ } >+ if(j == nCellFaces) >+ { >+ cellType = VTK_HEXAHEDRON; >+ } >+ } >+ else if(nCellFaces == 5) >+ { >+ int nTris = 0, nQuads = 0; >+ for(int j = 0; j < nCellFaces; j++) >+ { >+ const int nPoints = facePoints.size(cellFaces[j]); >+ if(nPoints == 3) >+ { >+ nTris++; >+ } >+ else if(nPoints == 4) >+ { >+ nQuads++; >+ } >+ else >+ { >+ break; >+ } >+ } >+ if(nTris == 2 && nQuads == 3) >+ { >+ cellType = VTK_WEDGE; >+ } >+ else if(nTris == 4 && nQuads == 1) >+ { >+ cellType = VTK_PYRAMID; >+ } >+ } >+ else if(nCellFaces == 4) >+ { >+ int j = 0; >+ for(; j < nCellFaces; j++) >+ { >+ if(facePoints.size(cellFaces[j]) != 3) >+ { >+ break; >+ } >+ } >+ if(j == nCellFaces) >+ { >+ cellType = VTK_TETRA; >+ } >+ } >+ >+ // not an Hex/Wedge/Pyramid/Tetra >+ if(cellType == VTK_CONVEX_POINT_SET) >+ { >+ int nPoints = 0; >+ for(int j = 0; j < nCellFaces; j++) >+ { >+ nPoints += facePoints.size(cellFaces[j]); >+ } >+ if(nPoints == 0) >+ { >+ cellType = VTK_EMPTY_CELL; >+ } >+ } >+ >+ // Cell shape constructor based on the one implementd by Terry >+ // Jordan, with lots of improvements. Not as elegant as the one in >+ // OpenFOAM but it's simple and works reasonably fast. >+ >+ // OFhex | vtkHexahedron || OFprism | vtkWedge >+ if (cellType == VTK_HEXAHEDRON || cellType == VTK_WEDGE) >+ { >+ // find the base face number >+ int baseFaceId = 8, nPoints; >+ if(cellType == VTK_HEXAHEDRON) >+ { >+ nPoints = 8; >+ baseFaceId = 0; >+ } >+ else // VTK_WEDGE >+ { >+ nPoints = 6; >+ for(int j = 0; j < nCellFaces; j++) >+ { >+ if(facePoints.size(cellFaces[j]) == 3) >+ { >+ baseFaceId = j; >+ break; >+ } >+ } >+ } >+ >+ // get first face in correct order >+ const int cellBaseFaceId = cellFaces[baseFaceId]; >+ const int *face0Points = facePoints[cellBaseFaceId]; >+ const int nBaseFacePoints = facePoints.size(cellBaseFaceId); >+ >+ if(this->FaceOwner->GetValue(cellBaseFaceId) == cellId) >+ { >+ for(int j = 0; j < nBaseFacePoints; j++) >+ { >+ cellPoints->SetId(j, face0Points[j]); >+ } >+ } >+ else >+ { >+ // patch: if it is a neighbor face flip the points >+ for(int j = 0; j < nBaseFacePoints; j++) >+ { >+ // add base face to cell points >+ cellPoints->SetId(j, face0Points[nBaseFacePoints - 1 - j]); >+ } >+ } >+ const int baseFacePoint0 = cellPoints->GetId(0); >+ const int baseFacePoint2 = cellPoints->GetId(2); >+ int oppositeFaceI = -1, pivotPoint = -1; >+ bool dupPoint2 = false; >+ for(int faceI = 0; faceI < nCellFaces; faceI++) >+ { >+ if(faceI == baseFaceId) >+ { >+ continue; >+ } >+ const int cellFaceI = cellFaces[faceI]; >+ const int *faceIPoints = facePoints[cellFaceI]; >+ const int nFaceIPoints = facePoints.size(cellFaceI); >+ bool found0Dup = false, found2Dup = false; >+ int pointI = 0; >+ for(; pointI < nFaceIPoints; pointI++) // each point >+ { >+ const int faceIPointI = faceIPoints[pointI]; >+ // matching two points in base face is enough to find a >+ // duplicated point since neighboring faces share two >+ // neighboring points (i. e. an edge) >+ if(baseFacePoint0 == faceIPointI) >+ { >+ found0Dup = true; >+ break; >+ } >+ else if(baseFacePoint2 == faceIPointI) >+ { >+ found2Dup = true; >+ break; >+ } >+ } >+ if(found0Dup || found2Dup) >+ { >+ // find the pivot point if still haven't >+ if(pivotPoint == -1) >+ { >+ int baseFacePrevPoint, baseFaceNextPoint; >+ if(found0Dup) >+ { >+ baseFacePrevPoint = cellPoints->GetId(nBaseFacePoints - 1); >+ baseFaceNextPoint = cellPoints->GetId(1); >+ } >+ else >+ { >+ baseFacePrevPoint = cellPoints->GetId(1); >+ baseFaceNextPoint >+ = cellPoints->GetId(nBaseFacePoints == 3 ? 0 : 3); >+ dupPoint2 = true; >+ } >+ >+ const int faceINextPoint = faceIPoints[(pointI + 1) % nFaceIPoints]; >+ const int faceIPrevPoint >+ = faceIPoints[(nFaceIPoints + pointI - 1) % nFaceIPoints]; >+ >+ // if the next point of the faceI-th face matches the >+ // previous point of the base face use the previous point >+ // of the faceI-th face as the pivot point; or use the >+ // next point otherwise >+ if(faceINextPoint == (this->FaceOwner->GetValue(cellFaceI) >+ == cellId ? baseFacePrevPoint : baseFaceNextPoint)) >+ { >+ pivotPoint = faceIPrevPoint; >+ } >+ else >+ { >+ pivotPoint = faceINextPoint; >+ } >+ } >+ } >+ else >+ { >+ // if no duplicated point found, faceI is the opposite face >+ if(oppositeFaceI == -1) >+ { >+ oppositeFaceI = faceI; >+ } >+ } >+ >+ // break when both of opposite face and pivot point are found >+ if(oppositeFaceI >= 0 && pivotPoint >= 0) >+ { >+ break; >+ } > } > >- //patch: if it is a neighbor face flip the points >- if(this->FacesOfCell->value[i][0].neighborFace) >+ // find the pivot point in opposite face >+ const int cellOppositeFaceI = cellFaces[oppositeFaceI]; >+ const int *oppositeFacePoints = facePoints[cellOppositeFaceI]; >+ const int nOppositeFacePoints = facePoints.size(cellOppositeFaceI); >+ int pivotPointI = 0; >+ for(; pivotPointI < nOppositeFacePoints; pivotPointI++) > { >- int tempPop; >- for(k = 0; k < (int)firstFace.size() - 1; k++) >+ if(oppositeFacePoints[pivotPointI] == pivotPoint) > { >- tempPop = firstFace[firstFace.size()-1]; >- firstFace.pop_back(); >- firstFace.insert(firstFace.begin()+1+k, tempPop); >+ break; > } > } > >- //add first face to cell points >- for(j =0; j < (int)firstFace.size(); j++) >+ if(this->FaceOwner->GetValue(cellOppositeFaceI) == cellId) > { >- cellPoints.push_back(firstFace[j]); >+ if(dupPoint2) >+ { >+ pivotPointI = (pivotPointI + 2) % nOppositeFacePoints; >+ } >+ int basePointI = nBaseFacePoints; >+ for(int pointI = pivotPointI; pointI >= 0; pointI--) >+ { >+ cellPoints->SetId(basePointI++, oppositeFacePoints[pointI]); >+ } >+ for(int pointI = nOppositeFacePoints - 1; pointI > pivotPointI; >+ pointI--) >+ { >+ cellPoints->SetId(basePointI++, oppositeFacePoints[pointI]); >+ } > } >- >- //find the opposite face and order the points correctly >- for(int pointCount = 0; pointCount < (int)firstFace.size(); pointCount++) >+ else > { >- >- //find the other 2 faces containing each point >- for(j = 1; j < (int)this->FacesOfCell->value[i].size(); j++) //each face >+ // shift the pivot point if the point corresponds to point 2 >+ // of the base face >+ if(dupPoint2) > { >- for(k = 0; k < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex].size(); k++) //each point >- { >- if(firstFace[pointCount] == this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][k]) >- { >- //ANOTHER FACE WITH THE POINT >- for(l = 0; l < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex].size(); l++) >- { >- tempFaces[faceCount].push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][l]); >- } >- faceCount++; >- } >- } >+ pivotPointI = (nOppositeFacePoints + pivotPointI - 2) >+ % nOppositeFacePoints; > } >- >- //locate the pivot point contained in faces 0 & 1 >- for(j = 0; j < (int)tempFaces[0].size(); j++) >+ // copy the face-point list of the opposite face to cell-point list >+ int basePointI = nBaseFacePoints; >+ for(int pointI = pivotPointI; pointI < nOppositeFacePoints; pointI++) > { >- for(k = 0; k < (int)tempFaces[1].size(); k++) >- { >- if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] != >- firstFace[pointCount]) >- { >- pivotPoint = tempFaces[0][j]; >- break; >- } >- } >+ cellPoints->SetId(basePointI++, oppositeFacePoints[pointI]); >+ } >+ for(int pointI = 0; pointI < pivotPointI; pointI++) >+ { >+ cellPoints->SetId(basePointI++, oppositeFacePoints[pointI]); > } >- cellPoints.push_back(pivotPoint); >- tempFaces[0].clear(); >- tempFaces[1].clear(); >- faceCount=0; > } > >- //create the hex cell and insert it into the mesh >- vtkHexahedron * hexahedron= vtkHexahedron::New(); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >- { >- hexahedron->GetPointIds()->SetId(pCount, cellPoints[pCount]); >- } >- internalMesh->InsertNextCell(hexahedron->GetCellType(), >- hexahedron->GetPointIds()); >- hexahedron->Delete(); >- cellPoints.clear(); >- firstFace.clear(); >+ // create the hex cell and insert it into the mesh >+ internalMesh->InsertNextCell(cellType, nPoints, >+ cellPoints->GetPointer(0)); > } > >- //OFprism | vtkWedge >- else if (totalPointCount == 18) >+ // OFpyramid | vtkPyramid || OFtet | vtkTetrahedron >+ else if (cellType == VTK_PYRAMID || cellType == VTK_TETRA) > { >- faceCount = 0; >- int index = 0; >- >- //find first triangular face >- for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++) //each face >+ int baseFaceId = -1, nPoints; >+ if(cellType == VTK_PYRAMID) > { >- if((int)this->FacePoints-> >- value[this->FacesOfCell->value[i][j].faceIndex].size() == 3) >+ for(int j = 0; j < nCellFaces; j++) > { >- for(k = 0; k < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex].size(); k++) >+ if(facePoints.size(cellFaces[j]) == 4) > { >- firstFace.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][k]); >- index = j; >+ baseFaceId = j; >+ break; > } >- break; > } >+ nPoints = 5; >+ } >+ else // VTK_TETRA >+ { >+ baseFaceId = 0; >+ nPoints = 4; > } > >- //patch: if it is a neighbor face flip the points >- if(this->FacesOfCell->value[i][0].neighborFace) >+ // add first face to cell points >+ const int cellBaseFaceId = cellFaces[baseFaceId]; >+ const int *baseFacePoints = facePoints[cellBaseFaceId]; >+ const size_t nBaseFacePoints = facePoints.size(cellBaseFaceId); >+ if(this->FaceOwner->GetValue(cellBaseFaceId) == cellId) > { >- int tempPop; >- for(k = 0; k < (int)firstFace.size() - 1; k++) >+ for(size_t j = 0; j < nBaseFacePoints; j++) > { >- tempPop = firstFace[firstFace.size()-1]; >- firstFace.pop_back(); >- firstFace.insert(firstFace.begin()+1+k, tempPop); >+ cellPoints->SetId(j, baseFacePoints[j]); >+ } >+ } >+ else >+ { >+ // if it is a neighbor face flip the points >+ for(size_t j = 0; j < nBaseFacePoints; j++) >+ { >+ cellPoints->SetId(j, baseFacePoints[nBaseFacePoints - 1 - j]); > } > } > >- //add first face to cell points >- for(j =0; j < (int)firstFace.size(); j++) >+ // compare an adjacent face (any non base face is ok) point 1 to >+ // base face points >+ const int adjacentFaceId = (baseFaceId == 0) ? 1 : baseFaceId - 1; >+ const int cellAdjacentFaceId = cellFaces[adjacentFaceId]; >+ const int *adjacentFacePoints = facePoints[cellAdjacentFaceId]; >+ const int adjacentFacePoint1 = adjacentFacePoints[1]; >+ bool foundDup = false; >+ for(size_t j = 0; j < nBaseFacePoints; j++) >+ { >+ // if point 1 of the adjacent face matches point j of the base face... >+ if(cellPoints->GetId(j) == adjacentFacePoint1) >+ { >+ // if point 2 of the adjacent face matches the previous point >+ // of the base face use point 0 of the adjacent face as the >+ // pivot point; use point 2 otherwise >+ cellPoints->SetId(nBaseFacePoints, (adjacentFacePoints[2] >+ == cellPoints->GetId((this->FaceOwner->GetValue(cellAdjacentFaceId) >+ == cellId ? (nBaseFacePoints + j - 1) : (j + 1)) % nBaseFacePoints)) >+ ? adjacentFacePoints[0] : adjacentFacePoints[2]); >+ foundDup = true; >+ break; >+ } >+ } >+ // if point 1 of the adjacent face does not match any points of >+ // the base face, it's the pivot point >+ if(!foundDup) > { >- cellPoints.push_back(firstFace[j]); >+ cellPoints->SetId(nBaseFacePoints, adjacentFacePoint1); > } > >- //find the opposite face and order the points correctly >- for(int pointCount = 0; pointCount < (int)firstFace.size(); pointCount++) >+ // create the tetra cell and insert it into the mesh >+ internalMesh->InsertNextCell(cellType, nPoints, >+ cellPoints->GetPointer(0)); >+ } >+ >+ // erronous cells >+ else if(cellType == VTK_EMPTY_CELL) >+ { >+ vtkWarningMacro("Warning: No points in cellId " << cellId); >+ internalMesh->InsertNextCell(VTK_EMPTY_CELL, 0, >+ cellPoints->GetPointer(0)); >+ } >+ >+ // OFpolyhedron || vtkConvexPointSet >+ else >+ { >+ if(additionalCells != NULL) // decompose into tets and pyramids > { >- //find the 2 other faces containing each point >- for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++) //each face >+ // calculate cell centroid and insert it to point list >+ this->AdditionalCellPoints->push_back(vtkIntArray::New()); >+ vtkIntArray *polyCellPoints = this->AdditionalCellPoints->back(); >+ float centroid[3]; >+ centroid[0] = centroid[1] = centroid[2] = 0.0F; >+ for(int j = 0; j < nCellFaces; j++) > { >- for(k = 0; k < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex].size(); k++) >+ // remove duplicate points from faces >+ const int cellFacesJ = cellFaces[j]; >+ const int *faceJPoints = facePoints[cellFacesJ]; >+ const size_t nFaceJPoints = facePoints.size(cellFacesJ); >+ for(size_t k = 0; k < nFaceJPoints; k++) > { >- if(firstFace[pointCount] == this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][k] && j != index) >+ const int faceJPointK = faceJPoints[k]; >+ bool foundDup = false; >+ for(size_t l = 0; l < polyCellPoints->GetDataSize(); l++) > { >- //ANOTHER FACE WITH POINT >- for(l = 0; l < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex].size(); l++) >+ if(polyCellPoints->GetValue(l) == faceJPointK) > { >- tempFaces[faceCount].push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][l]); >+ foundDup = true; >+ break; // look no more > } >- faceCount++; >+ } >+ if(!foundDup) >+ { >+ polyCellPoints->InsertNextValue(faceJPointK); >+ float *pointK = pointArray->GetPointer(3 * faceJPointK); >+ centroid[0] += pointK[0]; >+ centroid[1] += pointK[1]; >+ centroid[2] += pointK[2]; > } > } > } >- >- //locate the pivot point of faces 0 & 1 >- for(j = 0; j < (int)tempFaces[0].size(); j++) >+ polyCellPoints->Squeeze(); >+ float weight = 1.0F / static_cast<float>(polyCellPoints->GetDataSize()); >+ centroid[0] *= weight; >+ centroid[1] *= weight; >+ centroid[2] *= weight; >+ pointArray->InsertNextTuple(centroid); >+ >+ // polyhedron decomposition. >+ // a tweaked algorithm based on applications/utilities/postProcessing/ >+ // graphics/PVFoamReader/vtkFoam/vtkFoamAddInternalMesh.C >+ bool insertDecomposedCell = true; >+ for(int j = 0; j < nCellFaces; j++) > { >- for(k = 0; k < (int)tempFaces[1].size(); k++) >+ const int cellFacesJ = cellFaces[j]; >+ const int *faceJPoints = facePoints[cellFacesJ]; >+ const int nFaceJPoints = facePoints.size(cellFacesJ); >+ const int flipNeighbor >+ = (this->FaceOwner->GetValue(cellFacesJ) == cellId ? 1 : -1); >+ const int nTris = nFaceJPoints % 2; >+ >+ int vertI = 2; >+ >+ // shift the start and end of the vertex loop if the >+ // triangle of a decomposed face is going to be flat. Far >+ // from perfect but better than nothing to avoid flat cells >+ // which stops time integration of Stream Tracer especially >+ // for split-hex unstructured meshes created by >+ // e. g. autoRefineMesh >+ if(nFaceJPoints >= 5 && nTris) > { >- if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] != >- firstFace[pointCount]) >+ float *point0, *point1, *point2; >+ point0 = pointArray->GetPointer(3 * faceJPoints[nFaceJPoints - 1]); >+ point1 = pointArray->GetPointer(3 * faceJPoints[0]); >+ point2 = pointArray->GetPointer(3 * faceJPoints[nFaceJPoints - 2]); >+ float vsizeSqr1 = 0.0F, vsizeSqr2 = 0.0F, dotProduct = 0.0F; >+ for(int i = 0; i < 3; i++) > { >- pivotPoint = tempFaces[0][j]; >- break; >+ const float v1 = point1[i] - point0[i], >+ v2 = point2[i] - point0[i]; >+ vsizeSqr1 += v1 * v1; >+ vsizeSqr2 += v2 * v2; >+ dotProduct += v1 * v2; >+ } >+ // compare in squared representation to avoid using sqrt() >+ if(dotProduct * fabsf(dotProduct) / (vsizeSqr1 * vsizeSqr2) >+ < -1.0F + 1.0e-3F) >+ { >+ vertI = 1; > } > } >- } >- cellPoints.push_back(pivotPoint); >- tempFaces[0].clear(); >- tempFaces[1].clear(); >- faceCount=0; >- } >- >- //create the wedge cell and insert it into the mesh >- vtkWedge * wedge= vtkWedge::New(); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >- { >- wedge->GetPointIds()->SetId(pCount, cellPoints[pCount]); >- } >- internalMesh->InsertNextCell(wedge->GetCellType(), >- wedge->GetPointIds()); >- cellPoints.clear(); >- wedge->Delete(); >- firstFace.clear(); >- } > >- //OFpyramid | vtkPyramid >- else if (totalPointCount == 16) >- { >- foundDup = false; >+ cellPoints->SetId(0, faceJPoints[vertI == 2 ? 0 : nFaceJPoints - 1]); >+ cellPoints->SetId(4, this->NumPoints + nAdditionalPoints); > >- //find the quadratic face >- for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++) //each face >- { >- if((int)this->FacePoints-> >- value[this->FacesOfCell->value[i][j].faceIndex].size() == 4) >- { >- for(k = 0; k < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex].size(); k++) >+ // decompose a face into quads in order (flipping the >+ // decomposed face if neighbor) >+ const int nQuadVerts = nFaceJPoints - 1 - nTris; >+ for(; vertI < nQuadVerts; vertI += 2) > { >- cellPoints.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][k]); >+ cellPoints->SetId(1, faceJPoints[vertI - flipNeighbor]); >+ cellPoints->SetId(2, faceJPoints[vertI]); >+ cellPoints->SetId(3, faceJPoints[vertI + flipNeighbor]); >+ >+ // if the decomposed cell is the first one insert it to >+ // the original position; or append to the decomposed cell >+ // list otherwise >+ if(insertDecomposedCell) >+ { >+ internalMesh->InsertNextCell(VTK_PYRAMID, 5, >+ cellPoints->GetPointer(0)); >+ insertDecomposedCell = false; >+ } >+ else >+ { >+ this->AdditionalCellIds->InsertNextValue(cellId); >+ additionalCells->InsertNextTupleValue(cellPoints->GetPointer(0)); >+ } > } >- break; >- } >- } > >- //compare first face points to other faces >- for(j = 0; j < (int)cellPoints.size(); j++) //each point >- { >- for(k = 0; k < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][1].faceIndex].size(); k++) >- { >- if(cellPoints[j] == this->FacePoints->value[ >- this->FacesOfCell->value[i][1].faceIndex][k]) >+ // if the number of vertices is odd there's a triangle >+ if(nTris) > { >- foundDup = true; >+ if(flipNeighbor == -1) >+ { >+ cellPoints->SetId(1, faceJPoints[vertI]); >+ cellPoints->SetId(2, faceJPoints[vertI - 1]); >+ } >+ else >+ { >+ cellPoints->SetId(1, faceJPoints[vertI - 1]); >+ cellPoints->SetId(2, faceJPoints[vertI]); >+ } >+ cellPoints->SetId(3, this->NumPoints + nAdditionalPoints); >+ >+ if(insertDecomposedCell) >+ { >+ internalMesh->InsertNextCell(VTK_TETRA, 4, >+ cellPoints->GetPointer(0)); >+ insertDecomposedCell = false; >+ } >+ else >+ { >+ // set the 5th vertex number to -1 to distinguish a tetra cell >+ cellPoints->SetId(4, -1); >+ this->AdditionalCellIds->InsertNextValue(cellId); >+ additionalCells->InsertNextTupleValue(cellPoints->GetPointer(0)); >+ } > } > } >- if(!foundDup) >- { >- cellPoints.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][k]); >- break; >- } >- } >- >- //create the pyramid cell and insert it into the mesh >- vtkPyramid * pyramid = vtkPyramid::New(); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >- { >- pyramid->GetPointIds()->SetId(pCount, cellPoints[pCount]); >+ nAdditionalPoints++; > } >- internalMesh->InsertNextCell(pyramid->GetCellType(), >- pyramid->GetPointIds()); >- cellPoints.clear(); >- pyramid->Delete(); >- } >- >- //OFtet | vtkTetrahedron >- else if (totalPointCount == 12) >- { >- foundDup = false; >- >- //add first face to cell points >- for(j = 0; j < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][0].faceIndex].size(); j++) >+ else // don't decompose; use VTK_CONVEX_PONIT_SET > { >- cellPoints.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][0].faceIndex][j]); >- } >- >- //compare first face to the points of second face >- for(j = 0; j < (int)cellPoints.size(); j++) //each point >- { >- for(k = 0; k < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][1].faceIndex].size(); k++) >+ // get first face >+ const int cellFaces0 = cellFaces[0]; >+ const int *baseFacePoints = facePoints[cellFaces0]; >+ const int nBaseFacePoints = facePoints.size(cellFaces0); >+ int nPoints = nBaseFacePoints; >+ if(nPoints > maxNPoints) >+ { >+ vtkErrorMacro(<< "Too large polyhedron at cellId = " << cellId); >+ return; >+ } >+ // add first face to cell points >+ // not sure if flipping is necessary but do it anyway >+ if(this->FaceOwner->GetValue(cellFaces0) == cellId) > { >- if(cellPoints[j] == this->FacePoints->value[ >- this->FacesOfCell->value[i][1].faceIndex][k]) >+ for(int j = 0; j < nBaseFacePoints; j++) > { >- foundDup = true; >+ cellPoints->SetId(j, baseFacePoints[j]); > } > } >- if(!foundDup) >+ else > { >- cellPoints.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][k]); >- break; >+ // if it is a neighbor face flip the points >+ for(int j = 0; j < nBaseFacePoints; j++) >+ { >+ cellPoints->SetId(j, baseFacePoints[nBaseFacePoints - 1 - j]); >+ } > } >- } >- >- //create the wedge cell and insert it into the mesh >- vtkTetra * tetra = vtkTetra::New(); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >- { >- tetra->GetPointIds()->SetId(pCount, cellPoints[pCount]); >- } >- internalMesh->InsertNextCell(tetra->GetCellType(), >- tetra->GetPointIds()); >- cellPoints.clear(); >- tetra->Delete(); >- } >- >- //erronous cells >- else if(totalPointCount == 0) >- { >- vtkWarningMacro("Warning: No points in cell."); >- } >- >- //OFpolyhedron || vtkConvexPointSet >- else >- { >- vtkWarningMacro("Warning: Polyhedral Data is very Slow!"); >- foundDup = false; > >- //get first face >- for(j = 0; j < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][0].faceIndex].size(); j++) >- { >- firstFace.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][0].faceIndex][j]); >- } >- >- //add first face to cell points >- for(j =0; j < (int)firstFace.size(); j++) >- { >- cellPoints.push_back(firstFace[j]); >- } >- >- //loop through faces and create a list of all points >- //j = 1 skip firstFace >- for(j = 1; j < (int)this->FacesOfCell->value[i].size(); j++) >- { >- //remove duplicate points from faces >- for(k = 0; k < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex].size(); k++) >+ // loop through faces and create a list of all points >+ // j = 1 skip baseFace >+ for(int j = 1; j < nCellFaces; j++) > { >- for(l = 0; l < (int)cellPoints.size(); l++); >+ // remove duplicate points from faces >+ const int cellFacesJ = cellFaces[j]; >+ const int *faceJPoints = facePoints[cellFacesJ]; >+ const size_t nFaceJPoints = facePoints.size(cellFacesJ); >+ for(size_t k = 0; k < nFaceJPoints; k++) > { >- if(cellPoints[l] == this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][k]) >+ const int faceJPointK = faceJPoints[k]; >+ bool foundDup = false; >+ for(int l = 0; l < nPoints; l++) >+ { >+ if(cellPoints->GetId(l) == faceJPointK) >+ { >+ foundDup = true; >+ break; // look no more >+ } >+ } >+ if(!foundDup) > { >- foundDup = true; >+ if(nPoints >= maxNPoints) >+ { >+ vtkErrorMacro(<< "Too large polyhedron at cellId = " << cellId); >+ return; >+ } >+ cellPoints->SetId(nPoints++, faceJPointK); > } > } >- if(!foundDup) >- { >- cellPoints.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex][k]); >- foundDup = false; >- } > } >- } > >- //create the poly cell and insert it into the mesh >- vtkConvexPointSet * poly = vtkConvexPointSet::New(); >- poly->GetPointIds()->SetNumberOfIds(cellPoints.size()); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >- { >- poly->GetPointIds()->SetId(pCount, cellPoints[pCount]); >+ // create the poly cell and insert it into the mesh >+ internalMesh->InsertNextCell(VTK_CONVEX_POINT_SET, nPoints, >+ cellPoints->GetPointer(0)); > } >- internalMesh->InsertNextCell(poly->GetCellType(), >- poly->GetPointIds()); >- cellPoints.clear(); >- firstFace.clear(); >- poly->Delete(); > } > } >- >- //set the internal mesh points >- internalMesh->SetPoints(Points); >- vtkDebugMacro(<<"Internal mesh made"); >- return internalMesh; >+ cellPoints->Delete(); > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::ControlDictDataParser >-// >-// Purpose: >-// parse out double values for controlDict entries >-// utility function >-// >-// **************************************************************************** >-double vtkOpenFOAMReader::ControlDictDataParser(const char * lineIn) >+//----------------------------------------------------------------------------- >+void vtkOpenFOAMReader::SetDataObjectName(vtkDataObject *dataset, >+ const char *name) > { >- double value; >- vtkstd::string line(lineIn); >- line.erase(line.begin()+line.find(";")); >- vtkstd::string token; >- vtksys_ios::stringstream tokenizer(line); >- >- //parse to the final entry - double >- //while(tokenizer>>token); >- while(!tokenizer.eof()) >- { >- tokenizer >> token; >- } >- >- vtksys_ios::stringstream conversion(token); >- conversion >> value; >- return value; >+ vtkCharArray* nmArray = vtkCharArray::New(); >+ nmArray->SetName("Name"); >+ const size_t len = strlen(name); >+ nmArray->SetNumberOfTuples(static_cast<vtkIdType>(len)+1); >+ char* copy = nmArray->GetPointer(0); >+ memcpy(copy, name, len); >+ copy[len] = '\0'; >+ dataset->GetFieldData()->AddArray(nmArray); >+ nmArray->Delete(); > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::ReadControlDict >-// >-// Pupose: >-// reads the controlDict File >-// gather the necessary information to create a path to the data >-// >-// **************************************************************************** >-void vtkOpenFOAMReader::ReadControlDict () >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+//----------------------------------------------------------------------------- >+void vtkOpenFOAMReader::SetBlockName(vtkMultiBlockDataSet *blocks, >+ unsigned int blockI, const char *name) > { >- vtkDebugMacro(<<"Read controlDict"); >- //create variables >- vtkstd::string temp; >- double startTime; >- double endTime; >- double deltaT; >- double writeInterval; >- double timeStepIncrement; >- vtkstd::string writeControl; >- vtkstd::string timeFormat; >- stdString* tempStringStruct; >- >- ifstream * input = new ifstream(this->Path->value.c_str(), ios::in VTK_IOS_NOCREATE); >- >- //create the path to the data directory >- this->PathPrefix->value = this->Path->value; >- this->PathPrefix->value.erase(this->PathPrefix->value.begin()+ >- this->PathPrefix->value.find("system"),this->PathPrefix->value.end()); >- vtkDebugMacro(<<"Path: "<<this->PathPrefix->value.c_str()); >- >- //find Start Time >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- //while(!(temp.compare(0,8,"startTime",0,8) == 0)) >- while (strcmp(temp.substr(0,9).c_str(), "startTime")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- startTime = this->ControlDictDataParser(temp.c_str()); >- vtkDebugMacro(<<"Start time: "<<startTime); >- >- //find End Time >- //while(!(temp.compare(0,6,"endTime",0,6) == 0)) >- while (strcmp(temp.substr(0,7).c_str(), "endTime")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- endTime = this->ControlDictDataParser(temp.c_str()); >- vtkDebugMacro(<<"End time: "<<endTime); >- >- //find Delta T >- //while(!(temp.compare(0,5,"deltaT",0,5) == 0)) >- while (strcmp(temp.substr(0,6).c_str(), "deltaT")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- deltaT = this->ControlDictDataParser(temp.c_str()); >- vtkDebugMacro(<<"deltaT: "<<deltaT); >- >- //find write control >- //while(!(temp.compare(0,11,"writeControl",0,11) == 0)) >- while (strcmp(temp.substr(0,12).c_str(), "writeControl")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- >- temp.erase(temp.begin()+temp.find(";")); >- vtkstd::string token; >- vtksys_ios::stringstream tokenizer(temp); >- >- //while(tokenizer >> token); >- while(!tokenizer.eof()) >- { >- tokenizer >> token; >- } >- writeControl = token; >- vtkDebugMacro(<<"Write control: "<<writeControl.c_str()); >- >- //find write interval >- //while(!(temp.compare(0,12,"writeInterval",0,12) == 0)) >- while (strcmp(temp.substr(0,13).c_str(), "writeInterval")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- writeInterval = this->ControlDictDataParser(temp.c_str()); >- vtkDebugMacro(<<"Write interval: "<<writeInterval); >- >- //calculate the time step increment based on type of run >- //if(writeControl.compare(0,7,"timeStep",0,7) == 0) >- if(!strcmp(writeControl.substr(0,8).c_str(), "timeStep")) >- { >- vtkDebugMacro(<<"Time step type data"); >- timeStepIncrement = writeInterval * deltaT; >- } >- else >- { >- vtkDebugMacro(<<"Run time type data"); >- timeStepIncrement = writeInterval; >- } >- >- //find time format >- while(temp.find("timeFormat") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- timeFormat = temp; >- >- //calculate how many timesteps there should be >- float tempResult = ((endTime-startTime)/timeStepIncrement); >- int tempNumTimeSteps = (int)(tempResult+0.5)+1; //+0.1 to round up >- //make sure time step dir exists >- vtkstd::vector< double > tempSteps; >- vtkDirectory * test = vtkDirectory::New(); >- vtksys_ios::stringstream parser; >- double tempStep; >- for(int i = 0; i < tempNumTimeSteps; i++) >- { >- tempStep = i*timeStepIncrement + startTime; >- parser.clear(); >- if(timeFormat.find("general") != vtkstd::string::npos) >- { >- parser << tempStep; >- } >- else >- { >- parser << ios::scientific <<tempStep; >- } >- if(test->Open((this->PathPrefix->value+parser.str().c_str()).c_str())) >- { >- tempSteps.push_back(tempStep); >- } >- } >- test->Delete(); >- >- //Add the time steps that actually exist to steps >- //allows the run to be stopped short of controlDict spec >- //allows for removal of timesteps >- this->NumberOfTimeSteps = static_cast<int>(tempSteps.size()); >- this->Steps = new double[this->NumberOfTimeSteps]; >- for(int i = 0; i < this->NumberOfTimeSteps; i++) >- { >- this->Steps[i] =tempSteps[i]; >- } >- >- input->close(); >- delete input; >- vtkDebugMacro(<<"controlDict read"); >- return; >+ blocks->GetMetaData(blockI)->Set(vtkCompositeDataSet::NAME(), name); > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GetPoints >-// >-// Purpose: >-// read the points file into a vtkPoints >-// >-// **************************************************************************** >-void vtkOpenFOAMReader::GetPoints (int timeState) >+//----------------------------------------------------------------------------- >+void vtkOpenFOAMReader::SetBlockName(vtkMultiBlockDataSet *blocks, >+ unsigned int blockI, vtkDataObject *dataset) > { >- //path to points file >- vtkstd::string pointPath = this->PathPrefix->value + >- this->PolyMeshPointsDir->value[timeState] + >- "/polyMesh/points"; >- vtkDebugMacro(<<"Read points file: "<<pointPath.c_str()); >- >- vtkstd::string temp; >- bool binaryWriteFormat; >- stdString* tempStringStruct; >- ifstream * input = new ifstream(pointPath.c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >- { >- input->close(); >- delete input; >- return; >- } >- >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- input->close(); >- >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >- { >-#ifdef _WIN32 >- input->open(pointPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >-#else >- input->open(pointPath.c_str(), ios::in VTK_IOS_NOCREATE); >-#endif >- binaryWriteFormat = true; >- } >- else >- { >- input->open(pointPath.c_str(),ios::in); >- binaryWriteFormat = false; >- } >- >- double x,y,z; >- vtksys_ios::stringstream tokenizer; >- >- //instantiate the points class >- this->Points->Reset(); >- >- //find end of header >- //while(temp.compare(0,4, "// *", 0, 4) != 0) >- while (strcmp(temp.substr(0,4).c_str(), "// *")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- >- //find number of points >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- while(temp.empty()) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- >- //read number of points >- tokenizer << temp; >- tokenizer >> NumPoints; >- //binary data >- if(binaryWriteFormat) >- { >- input->get(); //parenthesis >- for(int i = 0; i < NumPoints; i++) >- { >- input->read((char *)&x,sizeof(double)); >- input->read((char *)&y,sizeof(double)); >- input->read((char *)&z,sizeof(double)); >- this->Points->InsertPoint(i,x,y,z); >- } >- } >- >- //ascii data >- else >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- for(int i = 0; i < this->NumPoints; i++) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- temp.erase(temp.begin()+temp.find("(")); >- temp.erase(temp.begin()+temp.find(")")); >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> x; >- tokenizer >> y; >- tokenizer >> z; >- this->Points->InsertPoint(i,x,y,z); >- } >- } >- >- input->close(); >- delete input; >- vtkDebugMacro(<<"Point file read"); >- return; >+ vtkCharArray *blockNameArray = vtkCharArray::SafeDownCast(dataset >+ ->GetFieldData()->GetArray("Name")); >+ this->SetBlockName(blocks, blockI, blockNameArray->GetPointer(0)); > } >- >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::ReadFacesFile >-// >-// Purpose: >-// read the faces into a vtkstd::vector >-// >-// **************************************************************************** >-void vtkOpenFOAMReader::ReadFacesFile (const char * facePathIn) >-{ >- vtkstd::string facePath(facePathIn); >- vtkDebugMacro(<<"Read faces file: "<<facePath.c_str()); >- vtkstd::string temp; >- stdString* tempStringStruct; >- bool binaryWriteFormat; >- ifstream * input = new ifstream(facePath.c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >- { >- input->close(); >- delete input; >- return; >- } >- >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- input->close(); >- >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >- { >-#ifdef _WIN32 >- input->open(facePath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >-#else >- input->open(facePath.c_str(), ios::in VTK_IOS_NOCREATE); > #endif >- binaryWriteFormat = true; >- } >- else >- { >- input->open(facePath.c_str(),ios::in); >- binaryWriteFormat = false; >- } > >- vtksys_ios::stringstream tokenizer; >- size_t pos; >- int numFacePoints; >- this->FacePoints->value.clear(); >+//----------------------------------------------------------------------------- >+// derive cell types and create the internal mesh >+vtkUnstructuredGrid * vtkOpenFOAMReader::MakeInternalMesh( >+ vtkIntArray *cellFacesList, vtkIntArray *cellFacesIndices, >+ const intVectorVector *facesPoints, vtkFloatArray *pointArray) >+{ >+ vtkDebugMacro(<<"Make internal mesh"); > >- //find end of header >- //while(temp.compare(0,4, "// *", 0, 4) != 0) >- while (strcmp(temp.substr(0,4).c_str(), "// *")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >+ // Create Mesh >+ vtkUnstructuredGrid* internalMesh = vtkUnstructuredGrid::New(); >+ internalMesh->Allocate(this->NumCells); > >- //find number of faces >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- while(temp.empty()) >+ if(this->DecomposePolyhedra) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- >- //read number of faces >- tokenizer << temp; >- tokenizer >> this->NumFaces; >- this->FacePoints->value.resize(this->NumFaces); >+ // for polyhedral decomposition >+ this->AdditionalCellIds = vtkIntArray::New(); >+ this->AdditionalCellPoints = new intArrayVector; > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//THROW OUT "(" >+ vtkIdTypeArray *additionalCells = vtkIdTypeArray::New(); >+ additionalCells->SetNumberOfComponents(5); // accommodates tetra or pyramid > >- //binary data >- if(binaryWriteFormat) >- { >- //char paren; >- int tempPoint; >- for(int i = 0; i < NumFaces; i++) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//THROW OUT blankline >+ this->InsertCellsToGrid(internalMesh, cellFacesList, cellFacesIndices, >+ facesPoints, pointArray, additionalCells, NULL); > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //grab point count >+ // for polyhedral decomposition >+ pointArray->Squeeze(); >+ this->AdditionalCellIds->Squeeze(); >+ additionalCells->Squeeze(); > >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> numFacePoints; >- this->FacePoints->value[i].resize(numFacePoints); >- //paren = input->get(); //grab ( >- input->get(); //grab ( >- for(int j = 0; j < numFacePoints; j++) >+ // insert decomposed cells into mesh >+ const int nComponents = additionalCells->GetNumberOfComponents(); >+ const int nAdditionalCells = additionalCells->GetNumberOfTuples(); >+ for(int i = 0; i < nAdditionalCells; i++) >+ { >+ if(additionalCells->GetComponent(i, 4) == -1) > { >- input->read((char *) &tempPoint, sizeof(int)); >- this->FacePoints->value[i][j] = tempPoint; >+ internalMesh->InsertNextCell(VTK_TETRA, 4, >+ additionalCells->GetPointer(i * nComponents)); > } >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //throw out ) and rest of line >- } >- } >- >- //ascii data >- else >- { >- //create vtkstd::vector of points in each face >- for(int i = 0; i < this->NumFaces; i++) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- pos = temp.find("("); >- vtksys_ios::stringstream ascTokenizer; >- ascTokenizer << temp.substr(0, pos); >- temp.erase(0, pos+1); >- ascTokenizer >> numFacePoints; >- this->FacePoints->value[i].resize(numFacePoints); >- for(int j = 0; j < numFacePoints; j++) >+ else > { >- pos = temp.find(" "); >- vtksys_ios::stringstream lineTokenizer; >- lineTokenizer << temp.substr(0, pos); >- temp.erase(0, pos+1); >- lineTokenizer >> this->FacePoints->value[i][j]; >+ internalMesh->InsertNextCell(VTK_PYRAMID, 5, >+ additionalCells->GetPointer(i * nComponents)); > } > } >- } >- >- input->close(); >- delete input; >- vtkDebugMacro(<<"Faces read"); >- return; >-} >- >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::ReadOwnerFile >-// >-// Purpose: >-// read the owner file into a vtkstd::vector >-// >-// **************************************************************************** >-void vtkOpenFOAMReader::ReadOwnerFile(const char * ownerPathIn) >-{ >- vtkstd::string ownerPath(ownerPathIn); >- vtkDebugMacro(<<"Read owner file: "<<ownerPath.c_str()); >- vtkstd::string temp; >- stdString* tempStringStruct; >- bool binaryWriteFormat; >- ifstream * input = new ifstream(ownerPath.c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >- { >- input->close(); >- delete input; >- return; >- } >- >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- input->close(); >- >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >- { >-#ifdef _WIN32 >- input->open(ownerPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >-#else >- input->open(ownerPath.c_str(), ios::in VTK_IOS_NOCREATE); >-#endif >- binaryWriteFormat = true; >+ internalMesh->Squeeze(); >+ additionalCells->Delete(); > } > else > { >- input->open(ownerPath.c_str(),ios::in); >- binaryWriteFormat = false; >+ this->InsertCellsToGrid(internalMesh, cellFacesList, cellFacesIndices, >+ facesPoints, pointArray, NULL, NULL); > } > >- vtkstd::string numFacesStr; >- int faceValue; >- >- this->FaceOwner = vtkIntArray::New(); >+ // set the internal mesh points >+ vtkPoints *points = vtkPoints::New(); >+ points->SetData(pointArray); >+ internalMesh->SetPoints(points); >+ points->Delete(); >+ this->SetDataObjectName(internalMesh, "Internal Mesh"); > >- vtksys_ios::stringstream tokenizer; >- tokenizer << this->NumFaces; >- tokenizer >> numFacesStr; >- //find end of header & number of faces >- //while(temp.compare(0,numFacesStr.size(),numFacesStr, >- //0,numFacesStr.size())!=0) >- while(strcmp(temp.substr(0,numFacesStr.size()).c_str(), numFacesStr.c_str())) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >+ vtkDebugMacro(<<"Internal mesh made"); >+ return internalMesh; >+} > >- this->FaceOwner->SetNumberOfValues(this->NumFaces); >+//----------------------------------------------------------------------------- >+// insert faces to grid >+void vtkOpenFOAMReader::InsertFacesToGrid(vtkUnstructuredGrid *boundaryMesh, >+ const intVectorVector *facesPoints, int startFace, int endFace, >+ vtkIntArray *boundaryPointMap, vtkIdList *facePointsVtkId, >+ vtkIntArray *labels, bool isLookupValue) >+{ >+ vtkUnstructuredGrid &bm = *boundaryMesh; > >- //binary data >- if(binaryWriteFormat) >+ for(int j = startFace; j < endFace; j++) > { >- input->get(); //parenthesis >- for(int i = 0; i < NumFaces; i++) >+ int faceId; >+ if(labels == NULL) > { >- input->read((char *) &faceValue, sizeof(int)); >- this->FaceOwner->SetValue(i, faceValue); >+ faceId = j; > } >- } >- >- //ascii data >- else >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- //read face owners into int array >- for(int i = 0; i < this->NumFaces; i++) >+ else > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> faceValue; >- this->FaceOwner->SetValue(i, faceValue); >+ faceId = labels->GetValue(j); >+ if(faceId >= this->FaceOwner->GetNumberOfTuples()) >+ { >+ vtkWarningMacro(<<"faceLabels id " << faceId >+ << " exceeds the number of faces " >+ << this->FaceOwner->GetNumberOfTuples()); >+ bm.InsertNextCell(VTK_EMPTY_CELL, 0, facePointsVtkId->GetPointer(0)); >+ continue; >+ } > } >- } >+ const int *facePoints = facesPoints->operator[](faceId); >+ size_t nFacePoints = facesPoints->size(faceId); > >- //find the number of cells >- double * range; >- range = this->FaceOwner->GetRange(); >- this->NumCells = (int)range[1]+1; >+ if(isLookupValue) >+ { >+ for(size_t k = 0; k < nFacePoints; k++) >+ { >+ facePointsVtkId->SetId(k, boundaryPointMap->LookupValue(facePoints[k])); >+ } >+ } >+ else >+ { >+ if(boundaryPointMap) >+ { >+ for(size_t k = 0; k < nFacePoints; k++) >+ { >+ facePointsVtkId->SetId(k, boundaryPointMap->GetValue(facePoints[k])); >+ } >+ } >+ else >+ { >+ for(size_t k = 0; k < nFacePoints; k++) >+ { >+ facePointsVtkId->SetId(k, facePoints[k]); >+ } >+ } >+ } > >- //add the face number to the correct cell >- //according to owner >- this->FacesOwnerCell->value.resize(this->NumCells); >- int tempCellId; >- for(int j = 0; j < this->NumFaces; j++) >- { >- tempCellId = this->FaceOwner->GetValue(j); >- if(tempCellId != -1) >+ // triangle >+ if(nFacePoints == 3) >+ { >+ bm.InsertNextCell(VTK_TRIANGLE, 3, facePointsVtkId->GetPointer(0)); >+ } >+ // quad >+ else if(nFacePoints == 4) >+ { >+ bm.InsertNextCell(VTK_QUAD, 4, facePointsVtkId->GetPointer(0)); >+ } >+ // polygon >+ else > { >- this->FacesOwnerCell->value[tempCellId].push_back(j); >+ bm.InsertNextCell(VTK_POLYGON, nFacePoints, >+ facePointsVtkId->GetPointer(0)); > } > } >- >- input->close(); >- delete input; >- vtkDebugMacro(<<"Owner file read"); >- return; > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::ReadNeighborFile >-// >-// Purpose: >-// read the neighbor file into a vtkstd::vector >-// >-// **************************************************************************** >-void vtkOpenFOAMReader::ReadNeighborFile(const char * neighborPathIn) >+//----------------------------------------------------------------------------- >+// returns requested boundary meshes >+unstructuredGridVector* vtkOpenFOAMReader::MakeBoundaryMesh( >+ vtkFoamBoundaryDict* boundaryDictPtr, const intVectorVector *facesPoints, >+ vtkFloatArray* pointArray) > { >- vtkstd::string neighborPath(neighborPathIn); >- vtkDebugMacro(<<"Read neighbor file: "<<neighborPath.c_str()); >- vtkstd::string temp; >- stdString* tempStringStruct; >- bool binaryWriteFormat; >- ifstream * input = new ifstream(neighborPath.c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >- { >- input->close(); >- delete input; >- return; >- } >- >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- input->close(); >+ vtkFoamBoundaryDict& boundaryDict = *boundaryDictPtr; >+ const int nBoundaries = boundaryDict.size(); >+ unstructuredGridVector *boundaryMesh = new unstructuredGridVector; > >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >- { >-#ifdef _WIN32 >- input->open(neighborPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >-#else >- input->open(neighborPath.c_str(), ios::in VTK_IOS_NOCREATE); >-#endif >- binaryWriteFormat = true; >- } >- else >+ if(this->CreateCellToPoint) > { >- input->open(neighborPath.c_str(),ios::in); >- binaryWriteFormat = false; >+ this->AllBoundaries = vtkUnstructuredGrid::New(); >+ this->AllBoundaries->Allocate(facesPoints->nElements() >+ - boundaryDict[0].startFace); > } >+ this->BoundaryPointMap = new intArrayVector; > >- vtkstd::string numFacesStr; >- int faceValue; >- vtkIntArray * faceNeighbor = vtkIntArray::New(); >+ vtkIntArray *nBoundaryPointsList = vtkIntArray::New(); >+ nBoundaryPointsList->SetNumberOfValues(nBoundaries); > >- vtksys_ios::stringstream tokenizer; >- tokenizer << this->NumFaces; >- tokenizer >> numFacesStr; >- //find end of header & number of faces >- //while(temp.compare(0,numFacesStr.size(),numFacesStr,0, >- //numFacesStr.size())!=0) >- while (strcmp(temp.substr(0,numFacesStr.size()).c_str(), numFacesStr.c_str())) >+ // count the max number of points per face and the number of points >+ // (with duplicates) in mesh >+ int maxNFacePoints = 0; >+ for(int boundaryI = 0; boundaryI < nBoundaries; boundaryI++) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ const int startFace = boundaryDict[boundaryI].startFace; >+ const int endFace = startFace + boundaryDict[boundaryI].nFaces; >+ int nPoints = 0; >+ for(int j = startFace; j < endFace; j++) >+ { >+ const int nFacePoints = facesPoints->size(j); >+ nPoints += nFacePoints; >+ if(nFacePoints > maxNFacePoints) >+ { >+ maxNFacePoints = nFacePoints; >+ } >+ } >+ nBoundaryPointsList->SetValue(boundaryI, nPoints); > } > >- //read face owners into int array >- faceNeighbor->SetNumberOfValues(this->NumFaces); >+ // aloocate array for converting int vector to vtkIdType List: >+ // workaround for 64bit machines >+ vtkIdList *facePointsVtkId = vtkIdList::New(); >+ facePointsVtkId->SetNumberOfIds(maxNFacePoints); > >- //binary data >- if(binaryWriteFormat) >+ // create initial internal point list: set all points to -1 >+ if(this->CreateCellToPoint) > { >- input->get(); //parenthesis >- for(int i = 0; i < this->NumFaces; i++) >+ this->InternalPoints = vtkIntArray::New(); >+ this->InternalPoints->SetNumberOfValues(this->NumPoints); >+ for(int pointI = 0; pointI < this->NumPoints; pointI++) > { >- input->read((char *) &faceValue, sizeof(int)); >- faceNeighbor->SetValue(i, faceValue); >+ this->InternalPoints->SetValue(pointI, -1); > } >- } > >- //ascii data >- else >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//throw away ( >- //read face owners into int array >- for(int i = 0; i < this->NumFaces; i++) >+ // mark boundary points as 0 >+ for(int boundaryI = 0; boundaryI < nBoundaries; boundaryI++) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ if(boundaryDict[boundaryI].isPhysicalBoundary) >+ { >+ const int startFace = boundaryDict[boundaryI].startFace; >+ const int endFace = startFace + boundaryDict[boundaryI].nFaces; > >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> faceValue; >- faceNeighbor->SetValue(i, faceValue); >+ for(int j = startFace; j < endFace; j++) >+ { >+ const int *facePoints = facesPoints->operator[](j); >+ const int nFacePoints = facesPoints->size(j); >+ for(int k = 0; k < nFacePoints; k++) >+ { >+ this->InternalPoints->SetValue(facePoints[k], 0); >+ } >+ } >+ } > } > } >- //No need to recalulate the Number of Cells >- this->FacesNeighborCell->value.resize(this->NumCells); > >- //add face number to correct cell >- int tempCellId; >- for(int j = 0; j < this->NumFaces; j++) >+ // create global to AllBounaries point map >+ int nAllBoundaryPoints = 0; >+ if(this->CreateCellToPoint) > { >- tempCellId = faceNeighbor->GetValue(j); >- if(tempCellId != -1) >+ for(int pointI = 0; pointI < this->NumPoints; pointI++) > { >- this->FacesNeighborCell->value[tempCellId].push_back(j); >+ if(this->InternalPoints->GetValue(pointI) == 0) >+ { >+ this->InternalPoints->SetValue(pointI, nAllBoundaryPoints); >+ nAllBoundaryPoints++; >+ } > } > } > >- faceNeighbor->Delete(); >- input->close(); >- delete input; >- vtkDebugMacro(<<"Neighbor file read"); >- return; >-} >+ for(int boundaryI = 0; boundaryI < nBoundaries; boundaryI++) >+ { >+ const int nFaces = boundaryDict[boundaryI].nFaces; >+ const int startFace = boundaryDict[boundaryI].startFace; >+ const int endFace = startFace + nFaces; > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::PopulatePolyMeshDirArrays >-// >-// Purpose: >-// create a Lookup Table containing the location of the points >-// and faces files for each time steps mesh >-// >-// **************************************************************************** >-void vtkOpenFOAMReader::PopulatePolyMeshDirArrays() >-{ >- vtkDebugMacro(<<"Create list of points/faces file directories"); >- vtksys_ios::stringstream path; >- vtksys_ios::stringstream timeStep; >- bool facesFound; >- bool pointsFound; >- bool polyMeshFound; >- >- //intialize size to number of timesteps >- this->PolyMeshPointsDir->value.resize(this->NumberOfTimeSteps); >- this->PolyMeshFacesDir->value.resize(this->NumberOfTimeSteps); >+ if(this->CreateCellToPoint && boundaryDict[boundaryI].isPhysicalBoundary) >+ { >+ // add faces to AllBoundaries >+ this->InsertFacesToGrid(this->AllBoundaries, facesPoints, startFace, >+ endFace, this->InternalPoints, facePointsVtkId, NULL, false); >+ } > >- //loop through each timestep >- for(int i = 0; i < this->NumberOfTimeSteps; i++) >- { >- polyMeshFound = false; >- facesFound = false; >- pointsFound = false; >+ // skip below if inactive >+ if(!boundaryDict[boundaryI].isActive) >+ { >+ continue; >+ } > >- //create the path to the timestep >- path.clear(); >- timeStep.clear(); >- timeStep << Steps[i]; >- path << this->PathPrefix->value <<timeStep.str() << "/"; >+ // create the mesh >+ boundaryMesh->push_back(vtkUnstructuredGrid::New()); >+ vtkUnstructuredGrid& bm = *boundaryMesh->back(); >+ bm.Allocate(nFaces); >+ const int nBoundaryPoints = nBoundaryPointsList->GetValue(boundaryI); > >- //get the number of files >- vtkDirectory * directory = vtkDirectory::New(); >- directory->Open(path.str().c_str()); >- int numFiles = directory->GetNumberOfFiles(); >- //Look for polyMesh Dir >- for(int j = 0; j < numFiles; j++) >+ // create global to boundary-local point map and boundary points >+ vtkIntArray *boundaryPointList = vtkIntArray::New(); >+ boundaryPointList->SetNumberOfValues(nBoundaryPoints); >+ int pointI = 0; >+ for(int j = startFace; j < endFace; j++) > { >- vtkstd::string tempFile(directory->GetFile(j)); >- if(tempFile.find("polyMesh") != vtkstd::string::npos) >+ const int *facePoints = facesPoints->operator[](j); >+ int nFacePoints = facesPoints->size(j); >+ for(int k = 0; k < nFacePoints; k++) > { >- polyMeshFound = true; >- >- path << "polyMesh/"; >- >- //get number of files in the polyMesh dir >- vtkDirectory * polyMeshDirectory = vtkDirectory::New(); >- polyMeshDirectory->Open(path.str().c_str()); >- int numPolyMeshFiles = polyMeshDirectory->GetNumberOfFiles(); >- //Look for points/faces files >- for(int k = 0; k < numPolyMeshFiles; k++) >- { >- vtkstd::string tempFile2 = vtkstd::string(polyMeshDirectory-> >- GetFile(k)); >- if(tempFile2.find("points") != vtkstd::string::npos) >- { >- this->PolyMeshPointsDir->value[i] = timeStep.str(); >- pointsFound = true; >- } >- else if(tempFile2.find("faces") != vtkstd::string::npos) >- { >- this->PolyMeshFacesDir->value[i] = timeStep.str(); >- facesFound = true; >- } >- } >- >- //if there is no points or faces found in this timestep >- //set it equal to previous time step if no previous >- //set it equal to "constant" dir >- if(!pointsFound) >- { >- if(i != 0) >- { >- this->PolyMeshPointsDir->value[i] = >- this->PolyMeshPointsDir->value[i-1]; >- } >- else >- { >- this->PolyMeshPointsDir->value[i] = vtkstd::string("constant"); >- } >- } >- if(!facesFound) >- { >- if(i != 0) >- { >- this->PolyMeshFacesDir->value[i] = >- this->PolyMeshFacesDir->value[i-1]; >- } >- else >- { >- this->PolyMeshFacesDir->value[i] = vtkstd::string("constant"); >- } >- } >- >- polyMeshDirectory->Delete(); >- break; //found - stop looking >+ boundaryPointList->SetValue(pointI, facePoints[k]); >+ pointI++; > } > } >- >- //if there is no polyMesh dir >- //set it equal to prev timestep >- //if no prev set to "constant" dir >- if(!polyMeshFound) >+ vtkSortDataArray::Sort(boundaryPointList); >+ this->BoundaryPointMap->push_back(vtkIntArray::New()); >+ vtkIntArray& bpMap = *this->BoundaryPointMap->back(); >+ vtkFloatArray *boundaryPointArray = vtkFloatArray::New(); >+ boundaryPointArray->SetNumberOfComponents(3); >+ int oldPointJ = -1; >+ for(int j = 0; j < nBoundaryPoints; j++) > { >- if(i != 0) >- { >- //set points/faces location to previous timesteps value >- this->PolyMeshPointsDir->value[i] = this->PolyMeshPointsDir->value[i-1]; >- this->PolyMeshFacesDir->value[i] = this->PolyMeshFacesDir->value[i-1]; >- } >- else >+ const int pointJ = boundaryPointList->GetValue(j); >+ if(pointJ != oldPointJ) > { >- //set points/faces to constant >- this->PolyMeshPointsDir->value[i] = vtkstd::string("constant"); >- this->PolyMeshFacesDir->value[i] = vtkstd::string("constant"); >+ oldPointJ = pointJ; >+ boundaryPointArray->InsertNextTuple(pointArray->GetPointer(3 * pointJ)); >+ bpMap.InsertNextValue(pointJ); > } > } >- directory->Delete(); >- } >+ boundaryPointArray->Squeeze(); >+ bpMap.Squeeze(); >+ boundaryPointList->Delete(); >+ vtkPoints *boundaryPoints = vtkPoints::New(); >+ boundaryPoints->SetData(boundaryPointArray); >+ boundaryPointArray->Delete(); > >- vtkDebugMacro(<<"Points/faces list created"); >- return; >-} >+ // set points for boundary >+ bm.SetPoints(boundaryPoints); >+ boundaryPoints->Delete(); > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GetDataType >-// >-// Purpose: >-// determines whether a variable is a volume scalar, vector or neither >-// for meta data >-// >-// **************************************************************************** >-const char * vtkOpenFOAMReader::GetDataType(const char * pathIn, >- const char * fileNameIn) >-{ >- vtkstd::string path(pathIn); >- vtkstd::string fileName(fileNameIn); >- vtkstd::string filePath = path+"/"+fileName; >- vtkDebugMacro(<<"Get data type of: "<<filePath.c_str()); >- stdString* tempStringStruct; >- ifstream * input = new ifstream(filePath.c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >- { >- input->close(); >- delete input; >- return "Null"; >- } >- >- vtkstd::string temp; >- vtkstd::string foamClass; >- vtksys_ios::stringstream tokenizer; >- int opened; >+ // set the name of boundary >+ this->SetDataObjectName(&bm, boundaryDict[boundaryI].boundaryName.c_str()); > >- //see if fileName is a file or directory >- vtkDirectory * directory = vtkDirectory::New(); >- opened = directory->Open(filePath.c_str()); >- directory->Delete(); >- if(opened) >- { >- input->close(); >- delete input; >- return "Directory"; >+ // insert faces to boundary mesh >+ this->InsertFacesToGrid(&bm, facesPoints, startFace, endFace, &bpMap, >+ facePointsVtkId, NULL, true); >+ bpMap.ClearLookup(); > } > >- //find class entry >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- while(temp.find("class") == vtkstd::string::npos && !input->eof()) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >+ nBoundaryPointsList->Delete(); >+ facePointsVtkId->Delete(); > >- //return type >- if(!input->eof()) >+ if(this->CreateCellToPoint) > { >- temp.erase(temp.begin()+temp.find(";")); >- //PARSE OUT CLASS TYPE >- tokenizer << temp; >- //while(tokenizer >> foamClass); >- while(!tokenizer.eof()) >- { >- tokenizer >> foamClass; >- } >- //return scalar, vector, or invalid >- if(foamClass =="volScalarField") >+ this->AllBoundariesPointMap = vtkIntArray::New(); >+ vtkIntArray &abpMap = *this->AllBoundariesPointMap; >+ abpMap.SetNumberOfValues(nAllBoundaryPoints); >+ >+ // create lists of internal points and AllBoundaries points >+ int nInternalPoints = 0; >+ for(int pointI = 0, allBoundaryPointI = 0; pointI < this->NumPoints; >+ pointI++) > { >- input->close(); >- delete input; >- return "Scalar"; >+ const int globalPointId = this->InternalPoints->GetValue(pointI); >+ if(globalPointId == -1) >+ { >+ this->InternalPoints->SetValue(nInternalPoints, pointI); >+ nInternalPoints++; >+ } >+ else >+ { >+ abpMap.SetValue(allBoundaryPointI, pointI); >+ allBoundaryPointI++; >+ } > } >- else if (foamClass =="volVectorField") >+ // shrink to the number of internal points >+ if(nInternalPoints > 0) > { >- input->close(); >- delete input; >- return "Vector"; >+ this->InternalPoints->Resize(nInternalPoints); > } > else > { >- input->close(); >- delete input; >- return "Invalid"; >+ this->InternalPoints->Delete(); >+ this->InternalPoints = NULL; > } >+ >+ // set dummy vtkPoints to tell the grid the number of points >+ // (otherwise GetPointCells will crash) >+ vtkPoints *allBoundaryPoints = vtkPoints::New(); >+ allBoundaryPoints->SetNumberOfPoints(abpMap.GetNumberOfTuples()); >+ this->AllBoundaries->SetPoints(allBoundaryPoints); >+ allBoundaryPoints->Delete(); > } > >- //if the file format is wrong return invalid >- else >+ vtkDebugMacro(<<"Boundary mesh created"); >+ return boundaryMesh; >+} >+ >+//----------------------------------------------------------------------------- >+// truncate face owner to have only boundary face info >+void vtkOpenFOAMReader::TruncateFaceOwner() >+{ >+ const int boundaryStartFace = this->BoundaryDict->operator[](0).startFace; >+ // all the boundary faces >+ const int nBoundaryFaces >+ = this->FaceOwner->GetNumberOfTuples() - boundaryStartFace; >+ memmove(this->FaceOwner->GetPointer(0), >+ this->FaceOwner->GetPointer(boundaryStartFace), >+ sizeof(int) * nBoundaryFaces); >+ this->FaceOwner->Resize(nBoundaryFaces); >+} >+ >+//----------------------------------------------------------------------------- >+// move polyhedral cell centroids >+vtkPoints * vtkOpenFOAMReader::MoveInternalMesh( >+ vtkUnstructuredGrid *internalMesh, vtkFloatArray *pointArray) >+{ >+ if(this->DecomposePolyhedra) > { >- input->close(); >- delete input; >- return "invalid"; >- } >+ const int nAdditionalCells = this->AdditionalCellPoints->size(); >+ pointArray->Resize(this->NumPoints + nAdditionalCells); >+ for(int i = 0; i < nAdditionalCells; i++) >+ { >+ vtkIntArray *polyCellPoints = this->AdditionalCellPoints->operator[](i); >+ float centroid[3]; >+ centroid[0] = centroid[1] = centroid[2] = 0.0F; >+ const int nCellPoints = polyCellPoints->GetDataSize(); >+ for(int j = 0; j < nCellPoints; j++) >+ { >+ float *pointK = pointArray->GetPointer(3 * polyCellPoints->GetValue(j)); >+ centroid[0] += pointK[0]; >+ centroid[1] += pointK[1]; >+ centroid[2] += pointK[2]; >+ } >+ float weight >+ = (nCellPoints ? 1.0F / static_cast<float>(nCellPoints) : 0.0F); >+ centroid[0] *= weight; >+ centroid[1] *= weight; >+ centroid[2] *= weight; >+ pointArray->InsertTuple(this->NumPoints + i, centroid); >+ } >+ } >+ // instantiate the points class >+ vtkPoints* points = vtkPoints::New(); >+ points->SetData(pointArray); >+ internalMesh->SetPoints(points); >+ return points; > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GetInternalVariableAtTimestep >-// >-// Purpose: >-// returns the values for a request variable for the internal mesh >-// >-// **************************************************************************** >-vtkDoubleArray * vtkOpenFOAMReader::GetInternalVariableAtTimestep >- (const char * varNameIn, int timeState) >+//----------------------------------------------------------------------------- >+// move boundary points >+void vtkOpenFOAMReader::MoveBoundaryMesh(unstructuredGridVector *boundaryMesh, >+ vtkFloatArray *pointArray) > { >- vtkstd::string varName(varNameIn); >- vtksys_ios::stringstream varPath; >- varPath << this->PathPrefix->value << this->Steps[timeState] << "/" << varName; >- vtkDebugMacro(<<"Get internal variable: "<<varPath.str().c_str()); >- vtkDoubleArray *data = vtkDoubleArray::New(); >+ const vtkFoamBoundaryDict& bDict = *this->BoundaryDict; > >- vtkstd::string temp; >- stdString* tempStringStruct; >- bool binaryWriteFormat; >- ifstream * input = new ifstream(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >+ for(size_t boundaryI = 0, activeBoundaryI = 0; >+ boundaryI < bDict.size(); boundaryI++) > { >- input->close(); >- delete input; >- return data; >+ if(bDict[boundaryI].isActive) >+ { >+ vtkUnstructuredGrid& bm >+ = *boundaryMesh->operator[](activeBoundaryI); >+ vtkIntArray& bpMap = *this->BoundaryPointMap->operator[](activeBoundaryI); >+ const int nBoundaryPoints = bpMap.GetNumberOfTuples(); >+ vtkFloatArray *boundaryPointArray = vtkFloatArray::New(); >+ boundaryPointArray->SetNumberOfComponents(3); >+ boundaryPointArray->SetNumberOfTuples(nBoundaryPoints); >+ for(int pointI = 0; pointI < nBoundaryPoints; pointI++) >+ { >+ boundaryPointArray->SetTuple(pointI, bpMap.GetValue(pointI), >+ pointArray); >+ } >+ vtkPoints *boundaryPoints = vtkPoints::New(); >+ boundaryPoints->SetData(boundaryPointArray); >+ boundaryPointArray->Delete(); >+ bm.SetPoints(boundaryPoints); >+ boundaryPoints->Delete(); >+ activeBoundaryI++; >+ } > } >+} > >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >+//----------------------------------------------------------------------------- >+// as of now the function does not do interpolation, but do just averaging. >+void vtkOpenFOAMReader:: InterpolateCellToPoint(vtkFloatArray *pData, >+ vtkFloatArray *iData, vtkUnstructuredGrid *mesh, vtkIntArray *pointList, >+ const int nPoints) >+{ >+ if(nPoints == 0) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ return; > } >- input->close(); > >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >- { >-#ifdef _WIN32 >- input->open(varPath.str().c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >-#else >- input->open(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE); >-#endif >- binaryWriteFormat = true; >+ // a dummy call to let GetPointCells() build the cell links >+ vtkIdList *pointCells = vtkIdList::New(); >+ mesh->GetPointCells(0, pointCells); >+ pointCells->Delete(); >+ >+ vtkCellLinks *cl = mesh->GetCellLinks(); >+ const int nComponents = iData->GetNumberOfComponents(); >+ >+ if(nComponents == 1) >+ { >+ // a special case with the innermost componentI loop unrolled >+ float *tuples = iData->GetPointer(0); >+ for(int pointI = 0; pointI < nPoints; pointI++) >+ { >+ const int pI = (pointList ? pointList->GetValue(pointI) : pointI); >+ const vtkCellLinks::Link &l = cl->GetLink(pI); >+ const int nCells = static_cast<int>(l.ncells); >+ const vtkIdType *cells = l.cells; >+ // use double intermediate variables for precision >+ double interpolatedValue = 0.0; >+ for(int cellI = 0; cellI < nCells; cellI++) >+ { >+ interpolatedValue += tuples[cells[cellI]]; >+ } >+ interpolatedValue >+ = (nCells ? interpolatedValue / static_cast<double>(nCells) : 0.0); >+ pData->SetValue(pI, interpolatedValue); >+ } >+ } >+ else if(nComponents == 3) >+ { >+ // a special case with the innermost componentI loop unrolled >+ float *pDataPtr = pData->GetPointer(0); >+ for(int pointI = 0; pointI < nPoints; pointI++) >+ { >+ const int pI = (pointList ? pointList->GetValue(pointI) : pointI); >+ const vtkCellLinks::Link &l = cl->GetLink(pI); >+ const int nCells = static_cast<int>(l.ncells); >+ const vtkIdType *cells = l.cells; >+ // use double intermediate variables for precision >+ const double weight = (nCells ? 1.0 / static_cast<double>(nCells) : 0.0); >+ double summedValue0 = 0.0, summedValue1 = 0.0, summedValue2 = 0.0; >+ >+ // hand unrolling >+ for(int cellI = 0; cellI < nCells; cellI++) >+ { >+ const float *tuple = iData->GetPointer(3 * cells[cellI]); >+ summedValue0 += tuple[0]; >+ summedValue1 += tuple[1]; >+ summedValue2 += tuple[2]; >+ } >+ >+ float *interpolatedValue = &pDataPtr[3 * pI]; >+ interpolatedValue[0] = weight * summedValue0; >+ interpolatedValue[1] = weight * summedValue1; >+ interpolatedValue[2] = weight * summedValue2; >+ } > } > else > { >- input->open(varPath.str().c_str(),ios::in); >- binaryWriteFormat = false; >+ float *pDataPtr = pData->GetPointer(0); >+ for(int pointI = 0; pointI < nPoints; pointI++) >+ { >+ const int pI = (pointList ? pointList->GetValue(pointI) : pointI); >+ const vtkCellLinks::Link &l = cl->GetLink(pI); >+ const int nCells = static_cast<int>(l.ncells); >+ const vtkIdType *cells = l.cells; >+ // use double intermediate variables for precision >+ const double weight = (nCells ? 1.0 / static_cast<double>(nCells) : 0.0); >+ float *interpolatedValue = &pDataPtr[nComponents * pI]; >+ // a bit strange loop order but this works fastest >+ for(int componentI = 0; componentI < nComponents; componentI++) >+ { >+ const float *tuple = iData->GetPointer(componentI); >+ double summedValue = 0.0; >+ for(int cellI = 0; cellI < nCells; cellI++) >+ { >+ summedValue += tuple[nComponents * cells[cellI]]; >+ } >+ interpolatedValue[componentI] = weight * summedValue; >+ } >+ } > } >+} > >- vtkstd::string foamClass; >- vtksys_ios::stringstream tokenizer; >- double value; >- >- //find class >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+//----------------------------------------------------------------------------- >+bool vtkOpenFOAMReader::ReadFieldFile(vtkFoamIOobject *ioPtr, >+ vtkFoamDict *dictPtr, const char *varNameIn, int timeState, >+ vtkDataArraySelection *selection) >+{ >+ vtkStdString varPath = *this->PathPrefix >+ + this->TimeNames->GetValue(timeState) + "/" + vtkStdString(varNameIn); >+ vtkDebugMacro(<<"Get variable: "<<varPath.c_str()); > >- while(temp.find("class") == vtkstd::string::npos) >+ // open the file >+ vtkFoamIOobject &io = *ioPtr; >+ if(!io.open(varPath)) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " >+ << io.error().c_str()); >+ return false; > } >- temp.erase(temp.begin()+temp.find(";")); >- tokenizer << temp; >- //while(tokenizer >> foamClass); >- while(!tokenizer.eof()) >+ >+ // if the variable is disabled on selection panel then skip it >+ if(selection->ArrayExists(io.objectName().c_str()) >+ && !selection->ArrayIsEnabled(io.objectName().c_str())) > { >- tokenizer >> foamClass; >+ return false; > } >- temp=""; >- //create scalar arrays >- if(foamClass =="volScalarField") >+ >+ // read the field file into dictionary >+ vtkFoamDict &dict = *dictPtr; >+ if(!dict.read(io)) > { >- while(temp.find("internalField") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- //nonuniform >- if(!(temp.find("nonuniform") == vtkstd::string::npos)) >- { >- //create an array >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ return false; >+ } > >- int scalarCount; >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> scalarCount; >- data->SetNumberOfValues(NumCells); >+ if(dict.type() != vtkFoamToken::DICTIONARY) >+ { >+ vtkErrorMacro(<<"File " << io.fileName().c_str() >+ << "is not valid as a field file"); >+ return false; >+ } >+ return true; >+} > >- //binary data >- if(binaryWriteFormat) >+//----------------------------------------------------------------------------- >+vtkFloatArray *vtkOpenFOAMReader::FillField(vtkFoamEntry *entryPtr, >+ int nElements, vtkFoamIOobject *ioPtr, const vtkStdString *fieldType) >+{ >+ vtkFloatArray *data; >+ vtkFoamEntry &entry = *entryPtr; >+ const vtkStdString &className = ioPtr->className(); >+ >+ // "uniformValue" keyword is for uniformFixedValue B.C. >+ if(entry.firstValue().isUniform() || entry.keyword() == "uniformValue") >+ { >+ if(entry.firstValue().type() == vtkFoamToken::SCALAR >+ || entry.firstValue().type() == vtkFoamToken::LABEL) >+ { >+ const float num = entry.toFloat(); >+ data = vtkFloatArray::New(); >+ data->SetNumberOfValues(nElements); >+ for(int i = 0; i < nElements; i++) > { >- //add values to array >- input->get(); //parenthesis >- for(int i = 0; i < scalarCount; i++) >+ data->SetValue(i, num); >+ } >+ } >+ else >+ { >+ float tupleBuffer[9], *tuple; >+ int nComponents; >+ // have to determine the type of vector >+ if(entry.firstValue().type() == vtkFoamToken::LABELLIST) >+ { >+ vtkIntArray &ll = entry.labelList(); >+ nComponents = ll.GetNumberOfTuples(); >+ for(int componentI = 0; componentI < nComponents; componentI++) > { >- input->read((char *) &value, sizeof(double)); >- data->SetValue(i, value); >+ tupleBuffer[componentI] = static_cast<float>(ll.GetValue(componentI)); > } >+ tuple = tupleBuffer; >+ } >+ else if(entry.firstValue().type() == vtkFoamToken::SCALARLIST) >+ { >+ vtkFloatArray& sl = entry.scalarList(); >+ nComponents = sl.GetSize(); >+ tuple = sl.GetPointer(0); > } >- >- //ascii data > else > { >- //add values to array >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //discard ( >+ vtkErrorMacro(<<"Wrong list type for uniform field"); >+ return NULL; >+ } > >- for(int i = 0; i < scalarCount; i++) >+ if((*fieldType == "SphericalTensorField" && nComponents == 1) >+ || (*fieldType == "VectorField" && nComponents == 3) >+ || (*fieldType == "SymmTensorField" && nComponents == 6) >+ || (*fieldType == "TensorField" && nComponents == 9)) >+ { >+ data = vtkFloatArray::New(); >+ data->SetNumberOfComponents(nComponents); >+ data->SetNumberOfTuples(nElements); >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+#if vtksys_DATE_STAMP_FULL >= 20080620 >+ // swap the components of symmTensor to match the component >+ // names in paraview >+ if(nComponents == 6) >+ { >+ const float symxy = tuple[1], symxz = tuple[2], symyy = tuple[3]; >+ const float symyz = tuple[4], symzz = tuple[5]; >+ tuple[1] = symyy; >+ tuple[2] = symzz; >+ tuple[3] = symxy; >+ tuple[4] = symyz; >+ tuple[5] = symxz; >+ } >+#endif >+#endif >+ for(int i = 0; i < nElements; i++) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> value; >- data->SetValue(i, value); >+ data->SetTuple(i, tuple); > } > } >+ else >+ { >+ vtkErrorMacro(<< "Number of components and field class doesn't match " >+ << "for " << ioPtr->objectName() << ". class = " << className >+ << ", nComponents = " << nComponents); >+ return NULL; >+ } > } >- >- //uniform >- else if(!(temp.find("uniform") == vtkstd::string::npos)) >+ } >+ else // nonuniform >+ { >+ if((*fieldType == "ScalarField" >+ && entry.firstValue().type() == vtkFoamToken::SCALARLIST) >+ || ((*fieldType == "VectorField" || *fieldType == "SphericalTensorField" >+ || *fieldType == "SymmTensorField" || *fieldType == "TensorField") >+ && entry.firstValue().type() == vtkFoamToken::VECTORLIST)) >+ { >+ const int nTuples = entry.scalarList().GetNumberOfTuples(); >+ if(nTuples != nElements) >+ { >+ vtkErrorMacro(<<"Number of cells/points in mesh and field don't match: " >+ << "mesh = " << nElements << ", field = " << nTuples); >+ return NULL; >+ } >+ data = static_cast<vtkFloatArray *>(entry.ptr()); >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+#if vtksys_DATE_STAMP_FULL >= 20080620 >+ // swap the components of symmTensor to match the component >+ // names in paraview >+ const int nComponents = data->GetNumberOfComponents(); >+ if(nComponents == 6) >+ { >+ for(int tupleI = 0; tupleI < nTuples; tupleI++) >+ { >+ float *tuple = data->GetPointer(nComponents * tupleI); >+ const float symxy = tuple[1], symxz = tuple[2], symyy = tuple[3]; >+ const float symyz = tuple[4], symzz = tuple[5]; >+ tuple[1] = symyy; >+ tuple[2] = symzz; >+ tuple[3] = symxy; >+ tuple[4] = symyz; >+ tuple[5] = symxz; >+ } >+ } >+#endif >+#endif >+ } >+ else if(entry.firstValue().type() == vtkFoamToken::EMPTYLIST && >+ nElements <= 0) > { >- //parse out the uniform value >- vtkstd::string token; >- temp.erase(temp.begin()+temp.find(";")); >- tokenizer.clear(); >- tokenizer << temp; >- //while(tokenizer>>token); >- while(!tokenizer.eof()) >+ data = vtkFloatArray::New(); >+ // set the number of components as appropriate if the list is empty >+ if(*fieldType == "ScalarField" || *fieldType == "SphericalTensorField") > { >- tokenizer >> token; >+ data->SetNumberOfComponents(1); > } >- tokenizer.clear(); >- tokenizer << token; >- tokenizer >> value; >- data->SetNumberOfValues(NumCells); >- >- //create array of uniform values >- for(int i = 0; i < NumCells; i++) >+ else if(*fieldType == "VectorField") >+ { >+ data->SetNumberOfComponents(3); >+ } >+ else if(*fieldType == "SymmTensorField") >+ { >+ data->SetNumberOfComponents(6); >+ } >+ else if(*fieldType == "TensorField") > { >- data->SetValue(i, value); >+ data->SetNumberOfComponents(9); > } > } >- >- //no data > else > { >- input->close(); >- delete input; >- return data; >+ vtkErrorMacro(<< ioPtr->objectName().c_str() << " is not a valid " >+ << ioPtr->className().c_str()); >+ return NULL; > } > } >+ return data; >+} > >- //create vector arrays >- else if(foamClass == "volVectorField") >+//----------------------------------------------------------------------------- >+// convert OpenFOAM's dimension array representation to string >+void vtkOpenFOAMReader::ConstructDimensions(vtkStdString *dimString, >+ vtkFoamDict *dictPtr) >+{ >+ if(!AddDimensionsToArrayNames) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- while(temp.find("internalField") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- if(!(temp.find("nonuniform") == vtkstd::string::npos)) >+ return; >+ } >+ vtkFoamEntry &dimEntry = dictPtr->lookup("dimensions"); >+ if(dimEntry.found() >+ && dimEntry.firstValue().type() == vtkFoamToken::LABELLIST) >+ { >+ vtkIntArray &dims = dimEntry.labelList(); >+ if(dims.GetNumberOfTuples() == 7) > { >- //create an array >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- int vectorCount; >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> vectorCount; >- data->SetNumberOfComponents(3); >- >- //binary data >- if(binaryWriteFormat) >+ int dimSet[7]; >+ for(int dimI = 0; dimI < 7; dimI++) >+ { >+ dimSet[dimI] = dims.GetValue(dimI); >+ } >+ static const char *units[7] = { "kg", "m", "s", "K", "mol", "A", "cd" }; >+ vtksys_ios::ostringstream posDim, negDim; >+ int posSpc = 0, negSpc = 0; >+ if(dimSet[0] == 1 && dimSet[1] == -1 && dimSet[2] == -2) >+ { >+ posDim << "Pa"; >+ dimSet[0] = dimSet[1] = dimSet[2] = 0; >+ posSpc = 1; >+ } >+ for(int dimI = 0; dimI < 7; dimI++) >+ { >+ const int dimDim = dimSet[dimI]; >+ if(dimDim > 0) >+ { >+ if(posSpc) >+ { >+ posDim << " "; >+ } >+ posDim << units[dimI]; >+ if(dimDim > 1) >+ { >+ posDim << dimDim; >+ } >+ posSpc++; >+ } >+ else if(dimDim < 0) >+ { >+ if(negSpc) >+ { >+ negDim << " "; >+ } >+ negDim << units[dimI]; >+ if(dimDim < -1) >+ { >+ negDim << -dimDim; >+ } >+ negSpc++; >+ } >+ } >+ *dimString += " [" + posDim.str(); >+ if(negSpc > 0) > { >- //add values to the array >- input->get(); //parenthesis >- for(int i = 0; i < vectorCount; i++) >+ if(posSpc == 0) >+ { >+ *dimString += "1"; >+ } >+ if(negSpc > 1) > { >- input->read((char *) &value, sizeof(double)); >- data->InsertComponent(i, 0, value); >- input->read((char *) &value, sizeof(double)); >- data->InsertComponent(i, 1, value); >- input->read((char *) &value, sizeof(double)); >- data->InsertComponent(i, 2, value); >+ *dimString += "/(" + negDim.str() + ")"; > } >- } >- >- //ascii data >- else >- { >- //add values to the array >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //discard ( >- for(int i = 0; i < vectorCount; i++) >+ else > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- //REMOVE BRACKETS >- temp.erase(temp.begin()+temp.find("(")); >- temp.erase(temp.begin()+temp.find(")")); >- >- //GRAB X,Y,&Z VALUES >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> value; >- data->InsertComponent(i, 0, value); >- tokenizer >> value; >- data->InsertComponent(i, 1, value); >- tokenizer >> value; >- data->InsertComponent(i, 2, value); >+ *dimString += "/" + negDim.str(); > } > } >- } >- else if(!(temp.find("uniform") == vtkstd::string::npos)) >- { >- //create an array of uniform values >- double value1, value2, value3; >- >- //parse out the uniform values >- temp.erase(temp.begin(), temp.begin()+temp.find("(")+1); >- temp.erase(temp.begin()+temp.find(")"), temp.end()); >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> value1; >- tokenizer >> value2; >- tokenizer >> value3; >- data->SetNumberOfComponents(3); >- for(int i = 0; i < NumCells; i++) >+ else if(posSpc == 0) > { >- data->InsertComponent(i, 0, value1); >- data->InsertComponent(i, 1, value2); >- data->InsertComponent(i, 2, value3); >+ *dimString += "-"; > } >- } >- >- //no data >- else >- { >- input->close(); >- delete input; >- return data; >+ *dimString += "]"; > } > } >- input->close(); >- delete input; >- vtkDebugMacro(<<"Internal variable data read"); >- return data; > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GetBoundaryVariableAtTimestep >-// >-// Purpose: >-// returns the values for a request variable for a bondary region >-// >-// **************************************************************************** >-vtkDoubleArray * vtkOpenFOAMReader::GetBoundaryVariableAtTimestep >- (int boundaryIndex, const char * varNameIn, int timeState, >- vtkUnstructuredGrid * internalMesh) >+//----------------------------------------------------------------------------- >+void vtkOpenFOAMReader::GetVolFieldAtTimestep( >+ vtkUnstructuredGrid* internalMesh, unstructuredGridVector* boundaryMesh, >+ vtkFoamBoundaryDict* boundaryDictPtr, const char* varNameIn, int timeState) > { >- vtkstd::string varName(varNameIn); >- vtksys_ios::stringstream varPath; >- varPath << this->PathPrefix->value << this->Steps[timeState] << "/" << varName; >- vtkDebugMacro(<<"Get boundary variable: "<<varPath.str().c_str()); >- vtkDoubleArray *data = vtkDoubleArray::New(); >- >- vtkstd::string temp; >- stdString* tempStringStruct; >- bool binaryWriteFormat; >- ifstream * input = new ifstream(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >+ vtkFoamIOobject io(*this->PathPrefix); >+ vtkFoamDict dict; >+ if(!this->ReadFieldFile(&io, &dict, varNameIn, timeState, >+ this->CellDataArraySelection)) > { >- input->close(); >- delete input; >- return data; >+ return; > } > >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >+ if(io.className().substr(0, 3) != "vol") > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ vtkErrorMacro(<< io.objectName().c_str() << " is not a volField"); >+ return; > } >- input->close(); > >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >+ vtkFoamEntry &iEntry = dict.lookup("internalField"); >+ if(!iEntry.found()) > { >-#ifdef _WIN32 >- input->open(varPath.str().c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >-#else >- input->open(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE); >-#endif >- binaryWriteFormat = true; >+ vtkErrorMacro(<<"internalField not found in " << io.fileName().c_str()); >+ return; > } >- else >+ >+ if(iEntry.firstValue().type() == vtkFoamToken::EMPTYLIST) > { >- input->open(varPath.str().c_str(),ios::in); >- binaryWriteFormat = false; >+ // if there's no cell there shouldn't be any boundary faces either >+ if(this->NumCells > 0) >+ { >+ vtkErrorMacro(<<"internalField of " << io.objectName().c_str() >+ << " is empty"); >+ } >+ return; > } > >- vtkstd::string foamClass; >- vtksys_ios::stringstream tokenizer; >- double value; >- >- //find class >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- while(temp.find("class") == vtkstd::string::npos) >+ vtkStdString fieldType = io.className().substr(3, vtkStdString::npos); >+ vtkFloatArray *iData = this->FillField(&iEntry, this->NumCells, &io, >+ &fieldType); >+ if(iData == NULL) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ return; > } >- temp.erase(temp.begin()+temp.find(";")); >- tokenizer << temp; >- //while(tokenizer >> foamClass); >- while(!tokenizer.eof()) >+ >+ vtkStdString dimString; >+ this->ConstructDimensions(&dimString, &dict); >+ >+ vtkFloatArray *acData = NULL, *ctpData = NULL; >+ >+ if(this->CreateCellToPoint) > { >- tokenizer >> foamClass; >+ acData = vtkFloatArray::New(); >+ acData->SetNumberOfComponents(iData->GetNumberOfComponents()); >+ acData->SetNumberOfTuples(this->FaceOwner->GetNumberOfTuples()); > } >- temp=""; >- //create scalar arrays >- if(foamClass =="volScalarField") >- { >- //find desired mesh >- while(temp.find(this->BoundaryNames->value[boundaryIndex]) == >- vtkstd::string::npos && !input->eof()) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- if(input->eof()) >- { >- input->close(); >- delete input; >- return data; >- } >- //find value entry >- while(temp.find("}") == vtkstd::string::npos && >- temp.find("value ") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //find value >- } > >- //nonuniform >- if(!(temp.find("nonuniform") == vtkstd::string::npos)) >+ if(iData->GetSize() > 0) >+ { >+ // Add field only if internal Mesh exists (skip if not selected). >+ // Note we still need to read internalField even if internal mesh is >+ // not selected, since boundaries without value entries may refer to >+ // the internalField. >+ if(internalMesh != NULL) > { >- >- //binary data >- if(binaryWriteFormat) >+ int nAdditionalCells = 0; >+ if(this->DecomposePolyhedra) > { >- //create an array >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- int scalarCount; >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> scalarCount; >- data->SetNumberOfValues(scalarCount); >- >- //assign values to the array >- input->get(); //parenthesis >- for(int i = 0; i < scalarCount; i++) >+ // add values for decomposed cells >+ nAdditionalCells = this->AdditionalCellIds->GetNumberOfTuples(); >+ iData->Resize(this->NumCells + nAdditionalCells); >+ for(int i = 0; i < nAdditionalCells; i++) > { >- input->read((char *) &value, sizeof(double)); >- data->SetValue(i, value); >+ iData->InsertTuple(this->NumCells + i, >+ static_cast<vtkIdType>(this->AdditionalCellIds->GetValue(i)), iData); > } > } > >- //ascii data >- else >+ // set data to internal mesh >+ this->AddArrayToFieldData(internalMesh->GetCellData(), iData, >+ io.objectName() + dimString); >+ >+ if(this->CreateCellToPoint) > { >- temp.erase(temp.begin(), temp.begin()+temp.find(">")+1); >- //ascii data with 10 or less values are on the same line >- //>10 >- if(temp == vtkstd::string(" ")) >+ // Create cell-to-point interpolated data >+ ctpData = vtkFloatArray::New(); >+ ctpData->SetNumberOfComponents(iData->GetNumberOfComponents()); >+ ctpData->SetNumberOfTuples( >+ internalMesh->GetPoints()->GetNumberOfPoints()); >+ if(this->InternalPoints != NULL) > { >- //create an array of data >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- int scalarCount; >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> scalarCount; >- data->SetNumberOfValues(scalarCount); >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //discard ( >- >- for(int i = 0; i < scalarCount; i++) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> value; >- data->SetValue(i, value); >- } >+ this->InterpolateCellToPoint(ctpData, iData, internalMesh, >+ this->InternalPoints, this->InternalPoints->GetNumberOfTuples()); > } >- //=<10 >- else >- { >- //create an array with data >- int scalarCount; >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> scalarCount; >- data->SetNumberOfValues(scalarCount); >- temp.erase(temp.begin(), temp.begin()+temp.find("(")+1); >- temp.erase(temp.begin()+temp.find(")"), temp.end()); > >- tokenizer.clear(); >- tokenizer << temp; >- for(int i = 0; i < scalarCount; i++) >+ if(this->DecomposePolyhedra) >+ { >+ // assign cell values to additional points >+ for(int cellI = 0, oldCellId = -1, pointI = this->NumPoints; >+ cellI < nAdditionalCells; cellI++) > { >- tokenizer >> value; >- data->SetValue(i, value); >+ const int cellId = this->AdditionalCellIds->GetValue(cellI); >+ if(cellId != oldCellId) >+ { >+ ctpData->SetTuple(pointI, cellId, iData); >+ pointI++; >+ oldCellId = cellId; >+ } > } > } > } > } >- >- //uniform >- else if(!(temp.find("uniform") == vtkstd::string::npos)) >- { >- //create an array of uniform values >- double value1 = 0; >- temp.erase(temp.begin(), temp.begin()+temp.find("uniform")+7); >- temp.erase(temp.begin()+temp.find(";"), temp.end()); >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> value1; >- data->SetNumberOfValues(this->SizeOfBoundary->value[boundaryIndex]); >- for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++) >- { >- data->SetValue(i, value1); >- } >- } >- >- //no data >- else >+ } >+ else >+ { >+ // determine as there's no cells >+ iData->Delete(); >+ if(acData != NULL) > { >- int cellId; >- vtkDataArray * internalData = internalMesh->GetCellData()-> >- GetArray(varName.c_str()); >- data->SetNumberOfValues(this->SizeOfBoundary->value[boundaryIndex]); >- for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++) >- { >- cellId = this->FaceOwner->GetValue(this->StartFace + i); >- data->SetValue(i, internalData->GetComponent(cellId, 0)); >- } >- input->close(); >- delete input; >- return data; >+ acData->Delete(); > } >+ return; > } >- //CREATE VECTOR ARRAYS >- else if(foamClass == "volVectorField") >+ >+ vtkFoamBoundaryDict &boundaryDict = *boundaryDictPtr; >+ >+ // set boundary values >+ vtkFoamEntry& bEntry = dict.lookup("boundaryField"); >+ if(!bEntry.found()) > { >- while(temp.find(this->BoundaryNames->value[boundaryIndex]) == >- vtkstd::string::npos && !input->eof()) >+ vtkErrorMacro(<< "boundaryField not found in object " << varNameIn >+ << " at time = " << this->TimeNames->GetValue(timeState).c_str()); >+ iData->Delete(); >+ if(acData != NULL) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ acData->Delete(); > } >- if(input->eof()) >+ if(ctpData != NULL) > { >- input->close(); >- delete input; >- return data; >+ ctpData->Delete(); > } >- while(temp.find("}") == vtkstd::string::npos && >- temp.find("value ") == vtkstd::string::npos) >+ return; >+ } >+ >+ vtkstd::vector<vtkFloatArray *> vDataVector; >+ for(size_t boundaryI = 0, activeBoundaryI = 0; >+ boundaryI < boundaryDict.size(); boundaryI++) >+ { >+ const vtkStdString &boundaryNameI = boundaryDict[boundaryI].boundaryName; >+ >+ vtkFoamEntry& bEntryI = bEntry.dictionary().lookup(boundaryNameI); >+ if(!bEntryI.found()) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //find value >+ vtkErrorMacro(<< "boundaryField " << boundaryNameI.c_str() >+ << " not found in object " << varNameIn << " at time = " >+ << this->TimeNames->GetValue(timeState).c_str()); >+ iData->Delete(); >+ if(acData != NULL) >+ { >+ acData->Delete(); >+ } >+ if(ctpData != NULL) >+ { >+ ctpData->Delete(); >+ } >+ return; > } >- //nonuniform >- if(!(temp.find("nonuniform") == vtkstd::string::npos)) >+ >+ if(bEntryI.firstValue().type() != vtkFoamToken::DICTIONARY) > { >- //create an array >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ vtkErrorMacro(<< "Type of boundaryField " << boundaryNameI.c_str() >+ << " is not a subdictionary in object " << varNameIn << " at time = " >+ << this->TimeNames->GetValue(timeState).c_str()); >+ iData->Delete(); >+ if(acData != NULL) >+ { >+ acData->Delete(); >+ } >+ if(ctpData != NULL) >+ { >+ ctpData->Delete(); >+ } >+ return; >+ } > >- int vectorCount; >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> vectorCount; >- data->SetNumberOfComponents(3); >+ const int nFaces = boundaryDict[boundaryI].nFaces; > >- //binary data >- if(binaryWriteFormat) >+ vtkFloatArray* vData = NULL; >+ bool valueFound = false; >+ vtkFoamEntry& vEntry = bEntryI.dictionary().lookup("value"); >+ if(vEntry.found()) // the boundary has a value entry >+ { >+ vData = this->FillField(&vEntry, nFaces, &io, &fieldType); >+ if(vData == NULL) > { >- //insert values into the array >- input->get(); //parenthesis >- for(int i = 0; i < vectorCount; i++) >+ iData->Delete(); >+ if(acData != NULL) > { >- input->read((char *) &value, sizeof(double)); >- data->InsertComponent(i, 0, value); >- input->read((char *) &value, sizeof(double)); >- data->InsertComponent(i, 1, value); >- input->read((char *) &value, sizeof(double)); >- data->InsertComponent(i, 2, value); >+ acData->Delete(); > } >+ if(ctpData != NULL) >+ { >+ ctpData->Delete(); >+ } >+ return; > } >- >- //ascii data >- else >+ valueFound = true; >+ } >+ else >+ { >+ // uniformFixedValue B.C. >+ vtkFoamEntry& ufvEntry = bEntryI.dictionary().lookup("type"); >+ if(ufvEntry.found()) >+ { >+ if(ufvEntry.toString() == "uniformFixedValue") > { >- //insert values into the array >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //discard ( >- for(int i = 0; i < vectorCount; i++) >+ // the boundary is of uniformFixedValue type >+ vtkFoamEntry& uvEntry = bEntryI.dictionary().lookup("uniformValue"); >+ if(uvEntry.found()) // and has a uniformValue entry > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- //REMOVE BRACKETS >- temp.erase(temp.begin()+temp.find("(")); >- temp.erase(temp.begin()+temp.find(")")); >- >- //GRAB X,Y,&Z VALUES >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> value; >- data->InsertComponent(i, 0, value); >- tokenizer >> value; >- data->InsertComponent(i, 1, value); >- tokenizer >> value; >- data->InsertComponent(i, 2, value); >+ vData = this->FillField(&uvEntry, nFaces, &io, &fieldType); >+ if(vData == NULL) >+ { >+ iData->Delete(); >+ if(acData != NULL) >+ { >+ acData->Delete(); >+ } >+ if(ctpData != NULL) >+ { >+ ctpData->Delete(); >+ } >+ return; >+ } >+ valueFound = true; > } > } > } >+ } > >- //uniform >- else if(!(temp.find("uniform") == vtkstd::string::npos)) >- { >- //create an array of uniform values >- double value1 = 0, value2 = 0, value3 = 0; >- temp.erase(temp.begin(), temp.begin()+temp.find("(")+1); >- temp.erase(temp.begin()+temp.find(")"), temp.end()); >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> value1; >- tokenizer >> value2; >- tokenizer >> value3; >+ const int boundaryStartFace >+ = boundaryDict[boundaryI].startFace - boundaryDict[0].startFace; > >- data->SetNumberOfComponents(3); >- for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++) >+ if(!valueFound) // doesn't have a value nor uniformValue entry >+ { >+ // use patch-internal values as boundary values >+ vData = vtkFloatArray::New(); >+ vData->SetNumberOfComponents(iData->GetNumberOfComponents()); >+ vData->SetNumberOfTuples(nFaces); >+ for(int j = 0; j < nFaces; j++) > { >- data->InsertComponent(i, 0, value1); >- data->InsertComponent(i, 1, value2); >- data->InsertComponent(i, 2, value3); >+ const int cellId = this->FaceOwner->GetValue(boundaryStartFace + j); >+ // in this case GetTuple should be thread-safe accoding to >+ // the FAQ on ParaView Wiki >+ vData->SetTuple(j, cellId, iData); > } > } > >- //no data >- else >+ if(this->CreateCellToPoint && boundaryDict[boundaryI].isPhysicalBoundary) > { >- int cellId; >- vtkDataArray * internalData = internalMesh->GetCellData()-> >- GetArray(varName.c_str()); >- data->SetNumberOfComponents(3); >- for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++) >+ // set the same value to AllBoundaries >+ for(int faceI = 0; faceI < nFaces; faceI++) > { >- cellId = this->FaceOwner->GetValue(this->StartFace + i); >- data->InsertComponent(i, 0, internalData->GetComponent(cellId, 0)); >- data->InsertComponent(i, 1, internalData->GetComponent(cellId, 1)); >- data->InsertComponent(i, 2, internalData->GetComponent(cellId, 2)); >+ const int startFace = boundaryDict[boundaryI].allBoundariesStartFace; >+ acData->SetTuple(faceI + startFace, faceI, vData); > } >- input->close(); >- delete input; >- return data; > } >- } >- input->close(); >- delete input; >- vtkDebugMacro(<<"Boundary data read"); >- return data; >-} > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GatherBlocks >-// >-// Purpose: >-// returns a vector of block names for a specified domain >-// >-// **************************************************************************** >-stringVector * vtkOpenFOAMReader::GatherBlocks(const char * typeIn, >- int timeState) >-{ >- vtkstd::string type(typeIn); >- vtkstd::string blockPath = this->PathPrefix->value + >- this->PolyMeshFacesDir->value[timeState] + >- "/polyMesh/"+type; >- vtkstd::vector< vtkstd::string > blocks; >- stringVector *returnValue = new stringVector; >- vtkDebugMacro(<<"Get blocks: "<<blockPath.c_str()); >- >- ifstream * input = new ifstream(blockPath.c_str(), ios::in VTK_IOS_NOCREATE); >- //if there is no file return a null vector >- if(input->fail()) >- { >- input->close(); >- delete input; >- returnValue->value = blocks; >- return returnValue; >- } >- >- vtkstd::string temp; >- stdString* tempStringStruct; >- vtkstd::string token; >- vtksys_ios::stringstream tokenizer; >- vtkstd::string tempName; >- >- //find end of header >- //while(temp.compare(0,4,"// *",0,4)!=0) >- while (strcmp(temp.substr(0,4).c_str(), "// *")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //throw out blank line >- >- //Number of blocks >- tokenizer << temp; >- tokenizer >> this->NumBlocks; >- blocks.resize(this->NumBlocks); >- >- //loop through each block >- for(int i = 0; i < this->NumBlocks; i++) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //throw out blank line >- >- //NAME >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; //name >- >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> tempName; >- blocks[i] = tempName; >- //while(temp.compare(0,1,"}",0,1) != 0) >- while (strcmp(temp.substr(0,1).c_str(), "}")) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- } >- returnValue->value = blocks; >- input->close(); >- delete input; >- return returnValue; >-} >+ if(boundaryDict[boundaryI].isActive) >+ { >+ this->AddArrayToFieldData(boundaryMesh->operator[](activeBoundaryI) >+ ->GetCellData(), vData, io.objectName() + dimString); > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GetBoundaryMesh >-// >-// Purpose: >-// returns a requested boundary mesh >-// >-// **************************************************************************** >-vtkUnstructuredGrid * vtkOpenFOAMReader::GetBoundaryMesh(int timeState, >- int boundaryIndex) >-{ >- vtkUnstructuredGrid * boundaryMesh = vtkUnstructuredGrid::New(); >- vtkstd::string boundaryPath = this->PathPrefix->value + >- this->PolyMeshFacesDir->value[timeState] + >- "/polyMesh/boundary"; >- vtkDebugMacro(<<"Create boundary mesh: "<<boundaryPath.c_str()); >+ if(this->CreateCellToPoint) >+ { >+ // construct cell-to-point interpolated boundary values. This >+ // is done independently from allBoundary interpolation so >+ // that the interpolated values are not affected by >+ // neighboring patches especially at patch edges and for >+ // baffle patches >+ vtkFloatArray *pData = vtkFloatArray::New(); >+ pData->SetNumberOfComponents(vData->GetNumberOfComponents()); >+ const int nPoints = boundaryMesh->operator[](activeBoundaryI)-> >+ GetPoints()->GetNumberOfPoints(); >+ pData->SetNumberOfTuples(nPoints); >+ this->InterpolateCellToPoint(pData, vData, >+ boundaryMesh->operator[](activeBoundaryI), NULL, nPoints); >+#if 0 >+ this->AddArrayToFieldData(boundaryMesh->operator[](activeBoundaryI) >+ ->GetPointData(), pData, >+ "CellToPoint[" + io.objectName() + "]" + dimString); >+#else >+ this->AddArrayToFieldData(boundaryMesh->operator[](activeBoundaryI) >+ ->GetPointData(), pData, io.objectName() + dimString); >+#endif >+ pData->Delete(); >+ } > >- int nFaces; >+ activeBoundaryI++; >+ } >+ vData->Delete(); >+ } >+ iData->Delete(); > >- ifstream * input = new ifstream(boundaryPath.c_str(), ios::in VTK_IOS_NOCREATE); >- //return a Null object >- if(input->fail()) >+ if(this->CreateCellToPoint) > { >- input->close(); >- delete input; >- return boundaryMesh; >- } >+ // Create cell-to-point interpolated data for all boundaries and >+ // override internal values >+ vtkFloatArray *bpData = vtkFloatArray::New(); >+ bpData->SetNumberOfComponents(acData->GetNumberOfComponents()); >+ const int nPoints = this->AllBoundariesPointMap->GetNumberOfTuples(); >+ bpData->SetNumberOfTuples(nPoints); >+ this->InterpolateCellToPoint(bpData, acData, this->AllBoundaries, NULL, >+ nPoints); >+ acData->Delete(); >+ >+ if(ctpData != NULL) >+ { >+ // set cell-to-pint data for internal mesh >+ for(int pointI = 0; pointI < nPoints; pointI++) >+ { >+ ctpData->SetTuple(this->AllBoundariesPointMap->GetValue(pointI), pointI, >+ bpData); >+ } >+#if 0 >+ this->AddArrayToFieldData(internalMesh->GetPointData(), ctpData, >+ "CellToPoint[" + io.objectName() + "]" + dimString); >+#else >+ this->AddArrayToFieldData(internalMesh->GetPointData(), ctpData, >+ io.objectName() + dimString); >+#endif >+ ctpData->Delete(); >+ } > >- vtkstd::string temp; >- stdString* tempStringStruct; >- vtkstd::string token; >- vtksys_ios::stringstream tokenizer; >+ bpData->Delete(); >+ } >+} > >- //find desired mesh entry >- while(temp.find(this->BoundaryNames->value[boundaryIndex]) == >- vtkstd::string::npos) >+//----------------------------------------------------------------------------- >+// read point field at a timestep >+void vtkOpenFOAMReader::GetPointFieldAtTimestep( >+ vtkUnstructuredGrid* internalMesh, unstructuredGridVector* boundaryMesh, >+ vtkFoamBoundaryDict* boundaryDictPtr, const char* varNameIn, int timeState) >+{ >+ vtkFoamIOobject io(*this->PathPrefix); >+ vtkFoamDict dict; >+ if(!this->ReadFieldFile(&io, &dict, varNameIn, timeState, >+ this->PointDataArraySelection)) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ return; > } > >- //get nFaces >- while(temp.find("nFaces") == vtkstd::string::npos) >+ if(io.className().substr(0, 5) != "point") > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ vtkErrorMacro(<< io.objectName().c_str() << " is not a pointField"); >+ return; > } >- temp.erase(temp.begin()+temp.find(";")); //remove ; >- tokenizer << temp; >- //while(tokenizer >> token); >- while(!tokenizer.eof()) >+ >+ vtkFoamEntry &iEntry = dict.lookup("internalField"); >+ if(!iEntry.found()) > { >- tokenizer >> token; >+ vtkErrorMacro(<<"internalField not found in " << io.fileName().c_str()); >+ return; > } >- tokenizer.clear(); >- tokenizer << token; >- tokenizer >> nFaces; >- >- //get startface >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; > >- //look for "startFaces" >- while(temp.find("startFace") == vtkstd::string::npos) >+ if(iEntry.firstValue().type() == vtkFoamToken::EMPTYLIST) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ // if there's no cell there shouldn't be any boundary faces either >+ if(this->NumPoints > 0) >+ { >+ vtkErrorMacro(<<"internalField of " << io.objectName().c_str() >+ << " is empty"); >+ } >+ return; > } >- temp.erase(temp.begin()+temp.find(";")); //remove ; >- tokenizer.clear(); >- tokenizer << temp; >- //while(tokenizer >> token); >- while(!tokenizer.eof()) >+ >+ vtkStdString fieldType = io.className().substr(5, vtkStdString::npos); >+ vtkFloatArray *iData = this->FillField(&iEntry, this->NumPoints, &io, >+ &fieldType); >+ if(iData == NULL) > { >- tokenizer >> token; >+ return; > } >- tokenizer.clear(); >- tokenizer << token; >- tokenizer >> this->StartFace; > >- //Create the mesh >- int j, k; >- vtkTriangle * triangle; >- vtkQuad * quad; >- vtkPolygon * polygon; >- int endFace = this->StartFace + nFaces; >- //loop through each face >- for(j = this->StartFace; j < endFace; j++) >- { >+ vtkStdString dimString; >+ this->ConstructDimensions(&dimString, &dict); > >- //triangle >- if(this->FacePoints->value[j].size() == 3) >- { >- triangle = vtkTriangle::New(); >- for(k = 0; k < 3; k++) >+ // AdditionalCellPoints is NULL if creation of InternalMesh had been skipped >+ if(this->AdditionalCellPoints != NULL) >+ { >+ // point-to-cell interpolation to additional cell centroidal points >+ // for decomposed cells >+ const int nAdditionalPoints = this->AdditionalCellPoints->size(); >+ const int nComponents = iData->GetNumberOfComponents(); >+ iData->Resize(this->NumPoints + nAdditionalPoints); >+ for(int i = 0; i < nAdditionalPoints; i++) >+ { >+ vtkIntArray *acp = this->AdditionalCellPoints->operator[](i); >+ int nPoints = acp->GetDataSize(); >+ float interpolatedValue[9]; >+ for(int k = 0; k < nComponents; k++) >+ { >+ interpolatedValue[k] = 0.0F; >+ } >+ for(int j = 0; j < nPoints; j++) >+ { >+ const float *tuple = iData->GetPointer(nComponents * acp->GetValue(j)); >+ for(int k = 0; k < nComponents; k++) >+ { >+ interpolatedValue[k] += tuple[k]; >+ } >+ } >+ const float weight = 1.0F / static_cast<float>(nPoints); >+ for(int k = 0; k < nComponents; k++) > { >- triangle->GetPointIds()->SetId(k, this->FacePoints->value[j][k]); >+ interpolatedValue[k] *= weight; > } >- boundaryMesh->InsertNextCell(triangle->GetCellType(), >- triangle->GetPointIds()); >- triangle->Delete(); >+ iData->InsertTuple(this->NumPoints + i, interpolatedValue); > } >+ } > >- //quad >- else if(this->FacePoints->value[j].size() == 4) >+ if(iData->GetSize() > 0) >+ { >+ // Add field only if internal Mesh exists (skip if not selected). >+ // Note we still need to read internalField even if internal mesh is >+ // not selected, since boundaries without value entries may refer to >+ // the internalField. >+ if(internalMesh != NULL) > { >- quad = vtkQuad::New(); >- for(k = 0; k < 4; k++) >- { >- quad->GetPointIds()->SetId(k, this->FacePoints->value[j][k]); >- } >- boundaryMesh->InsertNextCell(quad->GetCellType(), >- quad->GetPointIds()); >- quad->Delete(); >+ // set data to internal mesh >+ this->AddArrayToFieldData(internalMesh->GetPointData(), iData, >+ io.objectName() + dimString); > } >+ } >+ else >+ { >+ // determine as there's no points >+ iData->Delete(); >+ return; >+ } > >- //polygon >- else >+ // use patch-internal values as boundary values >+ vtkFoamBoundaryDict &boundaryDict = *boundaryDictPtr; >+ for(size_t boundaryI = 0, activeBoundaryI = 0; >+ boundaryI < boundaryDict.size(); boundaryI++) >+ { >+ if(boundaryDict[boundaryI].isActive) > { >- polygon = vtkPolygon::New(); >- for(k = 0; k < (int)this->FacePoints->value[j].size(); k++) >+ vtkFloatArray *vData = vtkFloatArray::New(); >+ vtkIntArray& bpMap = *this->BoundaryPointMap->operator[](activeBoundaryI); >+ const int nPoints = bpMap.GetNumberOfTuples(); >+ vData->SetNumberOfComponents(iData->GetNumberOfComponents()); >+ vData->SetNumberOfTuples(nPoints); >+ for(int j = 0; j < nPoints; j++) > { >- polygon->GetPointIds()->InsertId(k, this->FacePoints->value[j][k]); >+ vData->SetTuple(j, bpMap.GetValue(j), iData); > } >- boundaryMesh->InsertNextCell(polygon->GetCellType(), >- polygon->GetPointIds()); >- polygon->Delete(); >+ this->AddArrayToFieldData(boundaryMesh->operator[](activeBoundaryI) >+ ->GetPointData(), vData, io.objectName() + dimString); >+ vData->Delete(); >+ activeBoundaryI++; > } > } >- >- //set points for boundary >- boundaryMesh->SetPoints(this->Points); >- //add size of mesh >- this->SizeOfBoundary->value.push_back(boundaryMesh->GetNumberOfCells()); >- input->close(); >- delete input; >- vtkDebugMacro(<<"Boundary mesh created"); >- return boundaryMesh; >+ iData->Delete(); > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GetPointZoneMesh >-// >-// Purpose: >-// returns a requested point zone mesh >-// >-// **************************************************************************** >-vtkUnstructuredGrid * vtkOpenFOAMReader::GetPointZoneMesh(int timeState, >- int pointZoneIndex) >+//----------------------------------------------------------------------------- >+vtkPolyData* vtkOpenFOAMReader::MakeLagrangianMesh(int timeState, >+ const vtkStdString &lagrangianPath) > { >- vtkUnstructuredGrid * pointZoneMesh = vtkUnstructuredGrid::New(); >- vtkstd::string pointZonesPath = this->PathPrefix->value[timeState]+ >- "/polyMesh/pointZones"; >- vtkDebugMacro(<<"Create point zone mesh: "<<pointZonesPath.c_str()); >+ vtkStdString positionsPath = *this->PathPrefix >+ + this->TimeNames->GetValue(timeState) + "/" + lagrangianPath >+ + "/positions"; > >- vtkstd::string temp; >- stdString* tempStringStruct; >- bool binaryWriteFormat; >- ifstream * input = new ifstream(pointZonesPath.c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(!(io.open(positionsPath) || io.open(positionsPath + ".gz"))) > { >- input->close(); >- delete input; >- return pointZoneMesh; >+ // if positions doesn't exist we simply return without issuing an error >+ return NULL; > } > >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- input->close(); >+ // tell the IO object if the file is in OF 1.3 binary >+ // lagrangian/positions format >+ io.setIs13Positions(this->PositionsIsIn13Format != 0); > >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >+ vtkFoamDict dict; >+ if(!dict.read(io)) > { >-#ifdef _WIN32 >- input->open(pointZonesPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >-#else >- input->open(pointZonesPath.c_str(), ios::in VTK_IOS_NOCREATE); >-#endif >- binaryWriteFormat = true; >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ return NULL; > } >- else >+ if(dict.type() != vtkFoamToken::VECTORLIST) > { >- input->open(pointZonesPath.c_str(),ios::in); >- binaryWriteFormat = false; >+ vtkErrorMacro(<<"The file type of " << io.fileName().c_str() >+ << " is not a vectorList"); >+ return NULL; > } > >- vtkstd::string token; >- vtksys_ios::stringstream tokenizer; >- vtkVertex * pointCell; >- int tempElement; >- vtkstd::vector< vtkstd::vector < int > > tempElementZones; >- int numElement; >- >- //find desired mesh entry >- while(temp.find(this->PointZoneNames->value[pointZoneIndex]) == >- vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//throw out { >- >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//type >- >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//label >- >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//number of elements or { >- >- //number of elements >- if(temp.find("}") == vtkstd::string::npos) >- { >- tokenizer << temp; >- tokenizer >> numElement; >- if(numElement == 0) >- { >- input->close(); >- delete input; >- return NULL; >- } >+ vtkFloatArray *pointArray = reinterpret_cast<vtkFloatArray *>(dict.ptr()); >+ const int nParticles = pointArray->GetNumberOfTuples(); > >- //binary data >- if(binaryWriteFormat) >- { >- input->get(); //parenthesis >- for(int j = 0; j < numElement; j++) >- { >- input->read((char *) &tempElement, sizeof(int)); >- pointCell = vtkVertex::New(); >- pointCell->GetPointIds()->SetId(0,tempElement); >- pointZoneMesh->InsertNextCell(pointCell->GetCellType(), >- pointCell->GetPointIds()); >- pointCell->Delete(); >- } >- } >+ // instantiate the points class >+ vtkPoints *points = vtkPoints::New(); >+ points->SetData(pointArray); >+ pointArray->Delete(); >+ >+ // create lagrangian mesh >+ vtkPolyData* lagrangianMesh = vtkPolyData::New(); >+ lagrangianMesh->Allocate(nParticles); >+ for(vtkIdType i = 0; i < nParticles; i++) >+ { >+ lagrangianMesh->InsertNextCell(VTK_VERTEX, 1, &i); >+ } >+ lagrangianMesh->SetPoints(points); >+ points->Delete(); >+ this->SetDataObjectName(lagrangianMesh, lagrangianPath.c_str()); > >- //ascii data >- else >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//THROW OUT ( >+ return lagrangianMesh; >+} > >- //GET EACH ELEMENT & ADD TO VECTOR >- for(int j = 0; j < numElement; j++) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+//----------------------------------------------------------------------------- >+void vtkOpenFOAMReader::GetLagrangianFieldAtTimestep( >+ vtkPolyData* lagrangianMesh, const char* varNameIn, int timeState, >+ const vtkStdString &lagrangianPath) >+{ >+ vtkStdString varPath = *this->PathPrefix >+ + this->TimeNames->GetValue(timeState) + "/" + lagrangianPath + "/" >+ + vtkStdString(varNameIn); >+ >+ // open the file >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(!io.open(varPath)) >+ { >+ // if the field file doesn't exist we simply return without issuing an error >+ // as a simple way of supporting multi-region lagrangians >+#if 0 >+ vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " >+ << io.error().c_str()); >+#endif >+ return; >+ } > >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> tempElement; >- pointCell = vtkVertex::New(); >- pointCell->GetPointIds()->SetId(0,tempElement); >- pointZoneMesh->InsertNextCell(pointCell->GetCellType(), >- pointCell->GetPointIds()); >- pointCell->Delete(); >- } >- } >+ // if the variable is disabled on selection panel then skip it >+ vtkStdString selectionName = io.objectName(); >+ if(this->LagrangianDataArraySelection->ArrayExists(selectionName.c_str()) >+ && !this->LagrangianDataArraySelection >+ ->ArrayIsEnabled(selectionName.c_str())) >+ { >+ return; > } > >- //there is no entry >- else >+ // read the field file into dictionary >+ vtkFoamDict dict; >+ if(!dict.read(io)) > { >- input->close(); >- delete input; >- return NULL; >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ return; > } >- //set point zone points >- pointZoneMesh->SetPoints(Points); >- input->close(); >- delete input; >- vtkDebugMacro(<<"Point zone mesh created"); >- return pointZoneMesh; >+ >+ // set lagrangian values >+ if(dict.type() != vtkFoamToken::SCALARLIST >+ && dict.type() != vtkFoamToken::VECTORLIST) >+ { >+ vtkErrorMacro(<< io.fileName().c_str() >+ << ": Unsupported lagrangian field type " << io.className().c_str()); >+ return; >+ } >+ >+ vtkFloatArray* lData = reinterpret_cast<vtkFloatArray *>(dict.ptr()); >+ >+ // GetNumberOfTuples() works for both scalar and vector >+ const int nParticles = lData->GetNumberOfTuples(); >+ if(nParticles != lagrangianMesh->GetNumberOfCells()) >+ { >+ vtkErrorMacro(<< io.fileName().c_str() >+ <<": Sizes of lagrangian mesh and field don't match: mesh = " >+ << lagrangianMesh->GetNumberOfCells() << ", field = " << nParticles); >+ lData->Delete(); >+ return; >+ } >+ >+ this->AddArrayToFieldData(lagrangianMesh->GetCellData(), lData, >+ selectionName); >+ if(this->CreateCellToPoint) >+ { >+#if 0 >+ // have to use SetArray() since a vtkFloatArray can't be ShallowCopy()-ed >+ vtkFloatArray *lpData = vtkFloatArray::New(); >+ lpData->SetNumberOfComponents(lData->GetNumberOfComponents()); >+ lpData->SetArray(lData->GetPointer(0), lData->GetMaxId() + 1, 1); >+ this->AddArrayToFieldData(lagrangianMesh->GetPointData(), lpData, >+ "CellToPoint[" + selectionName + "]"); >+ lpData->Delete(); >+#else >+ this->AddArrayToFieldData(lagrangianMesh->GetPointData(), lData, >+ selectionName); >+#endif >+ } >+ lData->Delete(); >+ >+ return; > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GetFaceZoneMesh >-// >-// Purpose: >-// returns a requested face zone mesh >-// >-// **************************************************************************** >-vtkUnstructuredGrid * vtkOpenFOAMReader::GetFaceZoneMesh(int timeState, >- int faceZoneIndex) >+//----------------------------------------------------------------------------- >+// returns a dictionary of block names for a specified domain >+vtkOpenFOAMReader::vtkFoamDict* vtkOpenFOAMReader::GatherBlocks( >+ const char* typeIn, int timeState, bool mustRead) > { >- vtkUnstructuredGrid * faceZoneMesh = vtkUnstructuredGrid::New(); >- vtkstd::string faceZonesPath = this->PathPrefix->value + >- this->PolyMeshFacesDir->value[timeState] + >- "/polyMesh/faceZones"; >- vtkDebugMacro(<<"Create face zone mesh: "<<faceZonesPath.c_str()); >+ vtkStdString type(typeIn); >+ vtkStdString blockPath = *this->PathPrefix >+ + this->PolyMeshFacesDir->GetValue(timeState) + "/" + type; > >- vtkstd::string temp; >- stdString* tempStringStruct; >- bool binaryWriteFormat; >- ifstream * input = new ifstream(faceZonesPath.c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >+ vtkFoamIOobject io(*this->PathPrefix); >+ if(!(io.open(blockPath) || io.open(blockPath + ".gz"))) > { >- input->close(); >- delete input; >- return faceZoneMesh; >+ if(mustRead) >+ { >+ vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " >+ << io.error().c_str()); >+ } >+ return NULL; > } > >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ vtkFoamDict* dictPtr = new vtkFoamDict; >+ vtkFoamDict& dict = *dictPtr; >+ if(!dict.read(io)) >+ { >+ vtkErrorMacro(<<"Error reading line " << io.lineNumber() >+ << " of " << io.fileName().c_str() << ": " << io.error().c_str()); >+ delete dictPtr; >+ return NULL; > } >- input->close(); >- >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >+ if(dict.type() != vtkFoamToken::DICTIONARY) > { >-#ifdef _WIN32 >- input->open(faceZonesPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >-#else >- input->open(faceZonesPath.c_str(), ios::in); >-#endif >- binaryWriteFormat = true; >+ vtkErrorMacro(<<"The file type of " << io.fileName().c_str() >+ << " is not a dictionary"); >+ delete dictPtr; >+ return NULL; > } >- else >+ return dictPtr; >+} >+ >+//----------------------------------------------------------------------------- >+// returns a requested point zone mesh >+bool vtkOpenFOAMReader::GetPointZoneMesh(unstructuredGridVector* pointZoneMesh, >+ vtkPoints* points, int timeState) >+{ >+ vtkDebugMacro(<<"Create point zone mesh"); >+ >+ vtkFoamDict* pointZoneDictPtr >+ = this->GatherBlocks("polyMesh/pointZones", timeState, false); >+ >+ if(pointZoneDictPtr == NULL) > { >- input->open(faceZonesPath.c_str(),ios::in); >- binaryWriteFormat = false; >+ // not an error >+ return true; > } > >- vtkstd::string token; >- vtksys_ios::stringstream tokenizer; >- vtkstd::vector< int > faceZone; >- int tempElement; >- vtkstd::vector< vtkstd::vector < int > > tempElementZones; >- int numElement; >+ vtkFoamDict& pointZoneDict = *pointZoneDictPtr; >+ size_t nPointZones = pointZoneDict.size(); > >- //find desired mesh entry >- while(temp.find(this->FaceZoneNames->value[faceZoneIndex]) == >- vtkstd::string::npos) >+ for(size_t i = 0; i < nPointZones; i++) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ // look up point labels >+ vtkFoamDict& dict = pointZoneDict.entry(i).dictionary(); >+ vtkFoamEntry& pointLabelsEntry = dict.lookup("pointLabels"); >+ if(!pointLabelsEntry.found()) >+ { >+ delete pointZoneDictPtr; >+ vtkErrorMacro(<<"pointLabels not found in pointZones"); >+ return false; >+ } >+ >+ // allocate an empty mesh if the list is empty >+ if(pointLabelsEntry.firstValue().type() == vtkFoamToken::EMPTYLIST) >+ { >+ vtkUnstructuredGrid *pzm = vtkUnstructuredGrid::New(); >+ pointZoneMesh->push_back(pzm); >+ // set name >+ this->SetDataObjectName(pzm, pointZoneDict.entry(i).keyword()); >+ continue; >+ } >+ >+ if(pointLabelsEntry.firstValue().type() != vtkFoamToken::LABELLIST) >+ { >+ delete pointZoneDictPtr; >+ vtkErrorMacro(<<"pointLabels not of type labelList: type = " >+ << pointLabelsEntry.firstValue().type()); >+ return false; >+ } >+ >+ vtkIntArray &labels = pointLabelsEntry.labelList(); >+ >+ int nPoints = labels.GetNumberOfTuples(); >+ if(nPoints > this->NumPoints) >+ { >+ vtkErrorMacro(<<"The length of pointLabels " << nPoints >+ << " for pointZone " << pointZoneDict.entry(i).keyword().c_str() >+ << " exceeds the number of points " << this->NumPoints); >+ delete pointZoneDictPtr; >+ return false; >+ } >+ >+ // allocate new grid: we do not use resize() beforehand since it >+ // could lead to undefined pointer if we return by error >+ vtkUnstructuredGrid *pzm = vtkUnstructuredGrid::New(); >+ pointZoneMesh->push_back(pzm); >+ >+ // set pointZone size >+ pzm->Allocate(nPoints); >+ >+ // insert points >+ for(int j = 0; j < nPoints; j++) >+ { >+ vtkIdType pointLabel = labels.GetValue(j); // must be vtkIdType >+ if(pointLabel >= this->NumPoints) >+ { >+ vtkWarningMacro(<<"pointLabels id " << pointLabel >+ << " exceeds the number of points " << this->NumPoints); >+ pzm->InsertNextCell(VTK_EMPTY_CELL, 0, &pointLabel); >+ continue; >+ } >+ pzm->InsertNextCell(VTK_VERTEX, 1, &pointLabel); >+ } >+ pzm->SetPoints(points); >+ >+ // set name >+ this->SetDataObjectName(pzm, pointZoneDict.entry(i).keyword()); > } > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//throw out { >+ delete pointZoneDictPtr; >+ >+ vtkDebugMacro(<<"Point zone mesh created"); >+ return true; >+} >+ >+//----------------------------------------------------------------------------- >+// returns a requested face zone mesh >+bool vtkOpenFOAMReader::GetFaceZoneMesh( >+ unstructuredGridVector *faceZoneMesh, const intVectorVector *facesPoints, >+ vtkPoints* points, int timeState) >+{ >+ vtkDebugMacro(<<"Create face zone mesh"); > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//type >+ vtkFoamDict* faceZoneDictPtr >+ = this->GatherBlocks("polyMesh/faceZones", timeState, false); > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//label >+ if(faceZoneDictPtr == NULL) >+ { >+ // not an error >+ return true; >+ } > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//number of values or flipmap >+ vtkFoamDict& faceZoneDict = *faceZoneDictPtr; >+ size_t nFaceZones = faceZoneDict.size(); > >- if(temp.find("flipMap") == vtkstd::string::npos) >+ for(size_t i = 0; i < nFaceZones; i++) > { >- //number of elements >- tokenizer << temp; >- tokenizer >> numElement; >- if(numElement == 0) >+ // look up face labels >+ vtkFoamDict& dict = faceZoneDict.entry(i).dictionary(); >+ vtkFoamEntry& faceLabelsEntry = dict.lookup("faceLabels"); >+ if(!faceLabelsEntry.found()) > { >- input->close(); >- delete input; >- return NULL; >+ delete faceZoneDictPtr; >+ vtkErrorMacro(<<"faceLabels not found in faceZones"); >+ return false; > } > >- //binary >- if(binaryWriteFormat) >+ // allocate an empty mesh if the list is empty >+ if(faceLabelsEntry.firstValue().type() == vtkFoamToken::EMPTYLIST) > { >- input->get(); //parenthesis >- for(int j = 0; j < numElement; j++) >- { >- input->read((char *) &tempElement, sizeof(int)); >- faceZone.push_back(tempElement); >- } >+ vtkUnstructuredGrid *fzm = vtkUnstructuredGrid::New(); >+ faceZoneMesh->push_back(fzm); >+ // set name >+ this->SetDataObjectName(fzm, faceZoneDict.entry(i).keyword()); >+ continue; > } > >- //ascii >- else >+ if(faceLabelsEntry.firstValue().type() != vtkFoamToken::LABELLIST) > { >- //THROW OUT ( >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ delete faceZoneDictPtr; >+ vtkErrorMacro(<<"faceLabels not of type labelList"); >+ return false; >+ } > >- //get each element & add to vector >- for(int j = 0; j < numElement; j++) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ vtkIntArray &labels = faceLabelsEntry.labelList(); > >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> tempElement; >- faceZone.push_back(tempElement); >- } >+ int nFaces = labels.GetNumberOfTuples(); >+ if(nFaces > this->FaceOwner->GetNumberOfTuples()) >+ { >+ vtkErrorMacro(<<"The length of faceLabels " << nFaces >+ << " for faceZone " << faceZoneDict.entry(i).keyword().c_str() >+ << " exceeds the number of faces " >+ << this->FaceOwner->GetNumberOfTuples()); >+ delete faceZoneDictPtr; >+ return false; > } >- } > >- //Create the mesh >- int k; >- vtkTriangle * triangle; >- vtkQuad * quad; >- vtkPolygon * polygon; >+ // allocate new grid: we do not use resize() beforehand since it >+ // could lead to undefined pointer if we return by error >+ faceZoneMesh->push_back(vtkUnstructuredGrid::New()); >+ vtkUnstructuredGrid *fzm = faceZoneMesh->back(); > >- //LOOP THROUGH EACH FACE >- for(int j = 0; j < (int)faceZone.size(); j++) >- { >+ // set faceZone size >+ fzm->Allocate(nFaces); > >- //Triangular Face >- if(this->FacePoints->value[faceZone[j]].size() == 3) >+ // aloocate array for converting int vector to vtkIdType vector: >+ // workaround for 64bit machines >+ int maxNFacePoints = 0; >+ for(int j = 0; j < nFaces; j++) > { >- triangle = vtkTriangle::New(); >- for(k = 0; k < 3; k++) >+ const int nFacePoints = facesPoints->size(labels.GetValue(j)); >+ if(nFacePoints > maxNFacePoints) > { >- triangle->GetPointIds()->SetId(k, this->FacePoints->value[ >- faceZone[j]][k]); >+ maxNFacePoints = nFacePoints; > } >- faceZoneMesh->InsertNextCell(triangle->GetCellType(), >- triangle->GetPointIds()); >- triangle->Delete(); > } >+ vtkIdList* facePointsVtkId = vtkIdList::New(); >+ facePointsVtkId->SetNumberOfIds(maxNFacePoints); > >- //Quadraic Face >- else if(this->FacePoints->value[faceZone[j]].size() == 4) >- { >- quad = vtkQuad::New(); >- for(k = 0; k < 4; k++) >- { >- quad->GetPointIds()->SetId(k, >- this->FacePoints->value[faceZone[j]][k]); >- } >- faceZoneMesh->InsertNextCell(quad->GetCellType(), >- quad->GetPointIds()); >- quad->Delete(); >- } >+ // insert faces >+ this->InsertFacesToGrid(fzm, facesPoints, 0, nFaces, NULL, facePointsVtkId, >+ &labels, false); > >- //Polygonal Face >- else >- { >- polygon = vtkPolygon::New(); >- for(k = 0; k < (int)this->FacePoints->value[faceZone[j]].size(); k++) >- { >- polygon->GetPointIds()->InsertId(k, this->FacePoints->value[ >- faceZone[j]][k]); >- } >- faceZoneMesh->InsertNextCell(polygon->GetCellType(), >- polygon->GetPointIds()); >- polygon->Delete(); >- } >+ facePointsVtkId->Delete(); >+ fzm->SetPoints(points); >+ >+ // set name >+ this->SetDataObjectName(fzm, faceZoneDict.entry(i).keyword()); > } > >- //set the face zone points >- faceZoneMesh->SetPoints(this->Points); >- input->close(); >- delete input; >+ delete faceZoneDictPtr; >+ > vtkDebugMacro(<<"Face zone mesh created"); >- return faceZoneMesh; >+ return true; > } > >-// **************************************************************************** >-// Method: vtkOpenFOAMReader::GetCellZoneMesh >-// >-// Purpose: >-// returns a requested cell zone mesh >-// >-// **************************************************************************** >-vtkUnstructuredGrid * vtkOpenFOAMReader::GetCellZoneMesh(int timeState, >- int cellZoneIndex) >+//----------------------------------------------------------------------------- >+// returns a requested cell zone mesh >+bool vtkOpenFOAMReader::GetCellZoneMesh(unstructuredGridVector* cellZoneMesh, >+ vtkIntArray *cellFacesList, vtkIntArray *cellFacesIndices, >+ const intVectorVector *facesPoints, vtkPoints *points, int timeState) > { >- vtkUnstructuredGrid * cellZoneMesh = vtkUnstructuredGrid::New(); >- vtkstd::string cellZonesPath = this->PathPrefix->value + >- this->PolyMeshFacesDir->value[timeState] + >- "/polyMesh/cellZones"; >- vtkDebugMacro(<<"Create cell zone mesh: "<<cellZonesPath.c_str()); >- vtkstd::string temp; >- stdString* tempStringStruct; >- bool binaryWriteFormat; >- ifstream * input = new ifstream(cellZonesPath.c_str(), ios::in VTK_IOS_NOCREATE); >- //make sure file exists >- if(input->fail()) >+ vtkDebugMacro(<<"Create cell zone mesh"); >+ >+ vtkFoamDict* cellZoneDictPtr >+ = this->GatherBlocks("polyMesh/cellZones", timeState, false); >+ >+ if(cellZoneDictPtr == NULL) > { >- input->close(); >- delete input; >- return cellZoneMesh; >+ // not an error >+ return true; > } > >- //determine if file is binary or ascii >- while(temp.find("format") == vtkstd::string::npos) >+ vtkFoamDict& cellZoneDict = *cellZoneDictPtr; >+ size_t nCellZones = cellZoneDict.size(); >+ >+ for(size_t i = 0; i < nCellZones; i++) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ // look up cell labels >+ vtkFoamDict& dict = cellZoneDict.entry(i).dictionary(); >+ vtkFoamEntry& cellLabelsEntry = dict.lookup("cellLabels"); >+ if(!cellLabelsEntry.found()) >+ { >+ delete cellZoneDictPtr; >+ vtkErrorMacro(<<"cellLabels not found in cellZones"); >+ return false; >+ } >+ >+ // allocate an empty mesh if the list is empty >+ if(cellLabelsEntry.firstValue().type() == vtkFoamToken::EMPTYLIST) >+ { >+ vtkUnstructuredGrid *czm = vtkUnstructuredGrid::New(); >+ cellZoneMesh->push_back(czm); >+ // set name >+ this->SetDataObjectName(czm, cellZoneDict.entry(i).keyword()); >+ continue; >+ } >+ >+ if(cellLabelsEntry.firstValue().type() != vtkFoamToken::LABELLIST) >+ { >+ delete cellZoneDictPtr; >+ vtkErrorMacro(<<"cellLabels not of type labelList"); >+ return false; >+ } >+ >+ vtkIntArray &labels = cellLabelsEntry.labelList(); >+ >+ int nCells = labels.GetNumberOfTuples(); >+ if(nCells > this->NumCells) >+ { >+ vtkErrorMacro(<<"The length of cellLabels " << nCells >+ << " for cellZone " << cellZoneDict.entry(i).keyword().c_str() >+ << " exceeds the number of cells " << this->NumCells); >+ delete cellZoneDictPtr; >+ return false; >+ } >+ >+ // allocate new grid: we do not use resize() beforehand since it >+ // could lead to undefined pointers if we return by error >+ cellZoneMesh->push_back(vtkUnstructuredGrid::New()); >+ vtkUnstructuredGrid* czm = cellZoneMesh->back(); >+ >+ // set cellZone size >+ czm->Allocate(nCells); >+ >+ // insert cells >+ this->InsertCellsToGrid(czm, cellFacesList, cellFacesIndices, facesPoints, >+ NULL, NULL, &labels); >+ >+ // set cell zone points >+ czm->SetPoints(points); >+ >+ // set name >+ this->SetDataObjectName(czm, cellZoneDict.entry(i).keyword()); > } >- input->close(); > >- //reopen file in correct format >- if(temp.find("binary") != vtkstd::string::npos) >+ delete cellZoneDictPtr; >+ vtkDebugMacro(<<"Cell zone mesh created"); >+ return true; >+} >+ >+//----------------------------------------------------------------------------- >+void vtkOpenFOAMReader::AddArrayToFieldData(vtkDataSetAttributes *fieldData, >+ vtkDataArray *array, const vtkStdString &arrayName) >+{ >+ // exclude dimensional unit string if any >+ const vtkStdString arrayNameString(arrayName.substr(0, arrayName.find(' '))); >+ array->SetName(arrayName.c_str()); >+ >+ if(array->GetNumberOfComponents() == 1 >+#if 0 >+ && (fieldData->IsA("vtkPointData") && arrayNameString == "CellToPoint[p]" >+ || fieldData->IsA("vtkCellData") && arrayNameString == "p") >+#else >+ && arrayNameString == "p" >+#endif >+ ) > { >-#ifdef _WIN32 >- input->open(cellZonesPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); >+ fieldData->SetScalars(array); >+ } >+ else if(array->GetNumberOfComponents() == 3 >+#if 0 >+ && (fieldData->IsA("vtkPointData") && arrayNameString == "CellToPoint[U]" >+ || fieldData->IsA("vtkCellData") && arrayNameString == "U") > #else >- input->open(cellZonesPath.c_str(), ios::in VTK_IOS_NOCREATE); >+ && arrayNameString == "U" > #endif >- binaryWriteFormat = true; >+ ) >+ { >+ fieldData->SetVectors(array); > } > else > { >- input->open(cellZonesPath.c_str(),ios::in); >- binaryWriteFormat = false; >+ fieldData->AddArray(array); > } >+} > >- vtkstd::string token; >- vtksys_ios::stringstream tokenizer; >- vtkstd::vector< int > cellZone; >- int tempElement; >- vtkstd::vector< vtkstd::vector < int > > tempElementZones; >- int numElement; >+//----------------------------------------------------------------------------- >+// return 0 if there's any error, 1 if success >+int vtkOpenFOAMReader::CreateDataSet(vtkMultiBlockDataSet *output, >+ int timeState) >+{ >+ const bool recreateInternalMesh = (!this->CacheMesh) >+ || this->TimeStepOld == -1 >+ || this->PolyMeshFacesDir->GetValue(timeState) >+ != this->PolyMeshFacesDir->GetValue(this->TimeStepOld) >+ || this->FaceOwner == NULL >+ || (this->PatchSelectionStatus & 0x02) >+ != (this->PatchSelectionOldStatus & 0x02) >+ || this->DecomposePolyhedra != this->DecomposePolyhedraOld >+ || this->ReadZones != this->ReadZonesOld >+ || this->KeepPatches != this->KeepPatchesOld >+ || this->ListTimeStepsByControlDict != this->ListTimeStepsByControlDictOld; > >- //find desired mesh entry >- while(temp.find(this->CellZoneNames->value[cellZoneIndex]) == >- vtkstd::string::npos) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >- } >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//throw out { >+ const bool recreateBoundaryMesh = recreateInternalMesh >+ || this->PatchSelectionStatus != this->PatchSelectionOldStatus >+ || this->CreateCellToPoint != this->CreateCellToPointOld; > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//type >+ const bool updateVariables = recreateBoundaryMesh >+ || timeState != this->TimeStepOld >+ || this->CellSelectionStatus != this->CellSelectionOldStatus >+ || this->PointSelectionStatus != this->PointSelectionOldStatus >+ || this->LagrangianSelectionStatus != this->LagrangianSelectionOldStatus >+ || this->PositionsIsIn13Format != this->PositionsIsIn13FormatOld >+ || this->AddDimensionsToArrayNames != this->AddDimensionsToArrayNamesOld; > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ const bool pointsMoved = this->TimeStepOld == -1 >+ || this->PolyMeshPointsDir->GetValue(timeState) >+ != this->PolyMeshPointsDir->GetValue(this->TimeStepOld); > >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ const bool moveInternalPoints = !recreateInternalMesh && pointsMoved; >+ const bool moveBoundaryPoints = !recreateBoundaryMesh && pointsMoved; > >- //number of elements >- tokenizer << temp; >- tokenizer >> numElement; >+ // determine if we need to reconstruct meshes >+ if(recreateInternalMesh) >+ { >+ this->ClearInternalMeshes(); >+ } >+ if(recreateBoundaryMesh) >+ { >+ this->ClearBoundaryMeshes(); >+ } > >- //binary >- if(binaryWriteFormat) >+ intVectorVector *facePoints = NULL; >+ vtkStdString meshDir; >+ if(recreateInternalMesh || recreateBoundaryMesh) > { >- input->get(); //parenthesis >- for(int j = 0; j < numElement; j++) >+ meshDir = *this->PathPrefix >+ + this->PolyMeshFacesDir->GetValue(timeState) + "/polyMesh/"; >+ >+ // create paths to polyMesh files >+ vtkStdString facesPath = meshDir + "faces"; >+ // create the faces vector >+ facePoints = this->ReadFacesFile(facesPath.c_str()); >+ if(facePoints == NULL) > { >- input->read((char *) &tempElement, sizeof(int)); >- cellZone.push_back(tempElement); >+ return 0; > } >+ this->UpdateProgress(0.2); > } > >- //ascii >- else >+ vtkIntArray *cellFacesList = NULL; >+ vtkIntArray *cellFacesIndices = NULL; >+ if(recreateInternalMesh) > { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct;//throw out ( >+ vtkStdString ownerPath = meshDir + "owner"; >+ vtkStdString neighborPath = meshDir + "neighbour"; > >- //get each element & add to vector >- for(int j = 0; j < numElement; j++) >- { >- tempStringStruct = this->GetLine(input); >- temp = tempStringStruct->value; >- delete tempStringStruct; >+ // read owner/neighbor and create the faces owner/facesOfCell vector >+ cellFacesList = vtkIntArray::New(); >+ cellFacesIndices = vtkIntArray::New(); > >- tokenizer.clear(); >- tokenizer << temp; >- tokenizer >> tempElement; >- cellZone.push_back(tempElement); >+ if(!this->ReadOwnerNeighborFiles(cellFacesList, cellFacesIndices, >+ ownerPath.c_str(), neighborPath.c_str())) >+ { >+ delete facePoints; >+ cellFacesList->Delete(); >+ cellFacesIndices->Delete(); >+ return 0; > } >+ if(static_cast<vtkIdType>(facePoints->nElements()) >+ != this->FaceOwner->GetNumberOfTuples()) >+ { >+ vtkErrorMacro(<< "The numbers of faces in faces and owners don't match: " >+ << "faces = " << facePoints->nElements() << ", owners = " >+ << this->FaceOwner->GetNumberOfTuples()); >+ delete facePoints; >+ cellFacesList->Delete(); >+ cellFacesIndices->Delete(); >+ return 0; >+ } >+ this->UpdateProgress(0.3); > } > >- //Create the mesh >- bool foundDup = false; >- vtkstd::vector< int > cellPoints; >- vtkstd::vector< int > tempFaces[2]; >- vtkstd::vector< int > firstFace; >- int pivotPoint = 0; >- int i, j, k, l, pCount; >- int faceCount = 0; >- >- //Create Mesh >- for(i = 0; i < (int)cellZone.size(); i++) //each cell >+ vtkFloatArray *pointArray = NULL; >+ if(recreateInternalMesh || (recreateBoundaryMesh && !recreateInternalMesh >+ && this->InternalMesh == NULL) || moveInternalPoints || moveBoundaryPoints) > { >- //calculate total points for all faces of a cell >- //used to determine cell type >- int totalPointCount = 0; >- for(j = 0; j < (int)this->FacesOfCell->value[ >- cellZone[i]].size(); j++) //each face >+ // get the points >+ pointArray = this->ReadPointsFile(timeState); >+ if(pointArray == NULL && recreateInternalMesh) > { >- totalPointCount += (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][j].faceIndex].size(); >+ delete facePoints; >+ cellFacesList->Delete(); >+ cellFacesIndices->Delete(); >+ return 0; > } >+ this->UpdateProgress(0.4); >+ } > >- // using cell type - order points, create cell, add to mesh >- >- //OFhex | vtkHexahedron >- if (totalPointCount == 24) >+ // make internal mesh >+ // Create Internal Mesh only if required for display >+ if(recreateInternalMesh) >+ { >+ if(this->GetPatchArrayStatus(GetPatchArrayName(0))) > { >- faceCount = 0; >- >- //get first face >- for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][0].faceIndex].size(); j++) >- { >- firstFace.push_back(this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][0].faceIndex][j]); >- } >- >- //-if it is a neighbor face flip it >- if(FacesOfCell->value[i][0].neighborFace) >+ this->InternalMesh = this->MakeInternalMesh(cellFacesList, >+ cellFacesIndices, facePoints, pointArray); >+ } >+ // read and construct zones >+ if(this->ReadZones) >+ { >+ vtkPoints *points; >+ if(this->InternalMesh != NULL) > { >- int tempPop; >- for(k = 0; k < (int)firstFace.size() - 1; k++) >- { >- tempPop = firstFace[firstFace.size()-1]; >- firstFace.pop_back(); >- firstFace.insert(firstFace.begin()+1+k, tempPop); >- } >+ points = this->InternalMesh->GetPoints(); > } >- >- //add first face to cell points >- for(j =0; j < (int)firstFace.size(); j++) >+ else > { >- cellPoints.push_back(firstFace[j]); >+ points = vtkPoints::New(); >+ points->SetData(pointArray); > } > >- for(int pointCount = 0;pointCount < (int)firstFace.size();pointCount++) >+ this->PointZoneMesh = new unstructuredGridVector; >+ if(!this->GetPointZoneMesh(this->PointZoneMesh, points, timeState)) > { >- //find the 2 other faces containing each point - start with face 1 >- for(j = 1; j < (int)this->FacesOfCell->value[ >- cellZone[i]].size(); j++) //each face >+ delete this->PointZoneMesh; >+ this->PointZoneMesh = NULL; >+ delete facePoints; >+ cellFacesList->Delete(); >+ cellFacesIndices->Delete(); >+ if(this->InternalMesh == NULL) > { >- for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell-> >- value[cellZone[i]][j].faceIndex].size(); k++) >- { >- if(firstFace[pointCount] == this->FacePoints-> >- value[this->FacesOfCell->value[cellZone[i]][j].faceIndex][k]) >- { >- //another face with the point >- for(l = 0; l < (int)this->FacePoints->value[this->FacesOfCell-> >- value[cellZone[i]][j].faceIndex].size(); l++) >- { >- tempFaces[faceCount].push_back(this->FacePoints->value[ >- this->FacesOfCell->value[cellZone[i]][j].faceIndex] >- [l]); >- } >- faceCount++; >- } >- } >- } >- >- //locate the pivot point contained in faces 0 & 1 >- for(j = 0; j < (int)tempFaces[0].size(); j++) >- { >- for(k = 0; k < (int)tempFaces[1].size(); k++) >- { >- if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] != >- firstFace[pointCount]) >- { >- pivotPoint = tempFaces[0][j]; >- break; >- } >- } >+ points->Delete(); > } >- cellPoints.push_back(pivotPoint); >- tempFaces[0].clear(); >- tempFaces[1].clear(); >- faceCount=0; >+ pointArray->Delete(); >+ return 0; > } >- >- //create the hex cell and insert it into the mesh >- vtkHexahedron * hexahedron = vtkHexahedron::New(); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >- { >- hexahedron->GetPointIds()->SetId(pCount, cellPoints[pCount]); >- } >- cellZoneMesh->InsertNextCell(hexahedron->GetCellType(), >- hexahedron->GetPointIds()); >- hexahedron->Delete(); >- cellPoints.clear(); >- firstFace.clear(); >+ if(this->PointZoneMesh->size() == 0) >+ { >+ delete this->PointZoneMesh; >+ this->PointZoneMesh = NULL; > } > >- //OFprism | vtkWedge >- else if (totalPointCount == 18) >- { >- faceCount = 0; >- int index = 0; >- >- //find first triangular face >- for(j = 0; j < (int)this->FacesOfCell->value[ >- cellZone[i]].size(); j++) //each face >+ this->FaceZoneMesh = new unstructuredGridVector; >+ if(!this->GetFaceZoneMesh(this->FaceZoneMesh, facePoints, points, >+ timeState)) > { >- if((int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][j].faceIndex].size() == 3) >+ delete this->FaceZoneMesh; >+ this->FaceZoneMesh = NULL; >+ delete this->PointZoneMesh; >+ this->PointZoneMesh = NULL; >+ delete facePoints; >+ cellFacesList->Delete(); >+ cellFacesIndices->Delete(); >+ if(this->InternalMesh == NULL) > { >- for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][j].faceIndex].size(); k++) >- { >- firstFace.push_back(this->FacePoints->value[this->FacesOfCell-> >- value[cellZone[i]][j].faceIndex][k]); >- index = j; >- } >- break; >+ points->Delete(); > } >+ pointArray->Delete(); >+ return 0; > } >- >- //-if it is a neighbor face flip it >- if(this->FacesOfCell->value[i][0].neighborFace) >+ if(this->FaceZoneMesh->size() == 0) > { >- int tempPop; >- for(k = 0; k < (int)firstFace.size() - 1; k++) >+ delete this->FaceZoneMesh; >+ this->FaceZoneMesh = NULL; >+ } >+ >+ this->CellZoneMesh = new unstructuredGridVector; >+ if(!this->GetCellZoneMesh(this->CellZoneMesh, cellFacesList, >+ cellFacesIndices, facePoints, points, timeState)) >+ { >+ delete this->CellZoneMesh; >+ this->CellZoneMesh = NULL; >+ delete this->FaceZoneMesh; >+ this->FaceZoneMesh = NULL; >+ delete this->PointZoneMesh; >+ this->PointZoneMesh = NULL; >+ delete facePoints; >+ cellFacesList->Delete(); >+ cellFacesIndices->Delete(); >+ if(this->InternalMesh == NULL) > { >- tempPop = firstFace[firstFace.size()-1]; >- firstFace.pop_back(); >- firstFace.insert(firstFace.begin()+1+k, tempPop); >+ points->Delete(); > } >+ pointArray->Delete(); >+ return 0; > } >- >- //add first face to cell points >- for(j =0; j < (int)firstFace.size(); j++) >+ if(this->CellZoneMesh->size() == 0) > { >- cellPoints.push_back(firstFace[j]); >+ delete this->CellZoneMesh; >+ this->CellZoneMesh = NULL; > } >- >- for(int pointCount = 0;pointCount < (int)firstFace.size();pointCount++) >+ if(this->InternalMesh == NULL) > { >- //find the 2 other faces containing each point >- for(j = 0; j < (int)this->FacesOfCell->value[ >- cellZone[i]].size(); j++) //each face >- { >- for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][j].faceIndex].size(); k++) //each point >- { >- if(firstFace[pointCount] == this->FacePoints-> >- value[this->FacesOfCell->value[cellZone[i]][j].faceIndex][k] && >- j != index) >- { >- //another face with point >- for(l = 0; l < (int)this->FacePoints->value[this-> >- FacesOfCell->value[cellZone[i]][j].faceIndex].size(); l++) >- { >- tempFaces[faceCount].push_back(this->FacePoints->value[ >- this->FacesOfCell->value[cellZone[i]][j].faceIndex] >- [l]); >- } >- faceCount++; >- } >- } >- } >- >- //locate the pivot point contained in faces 0 & 1 >- for(j = 0; j < (int)tempFaces[0].size(); j++) >- { >- for(k = 0; k < (int)tempFaces[1].size(); k++) >- { >- if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] != >- firstFace[pointCount]) >- { >- pivotPoint = tempFaces[0][j]; >- break; >- } >- } >- } >- cellPoints.push_back(pivotPoint); >- tempFaces[0].clear(); >- tempFaces[1].clear(); >- faceCount=0; >+ points->Delete(); > } >+ } >+ cellFacesList->Delete(); >+ cellFacesIndices->Delete(); >+ this->TruncateFaceOwner(); >+ } > >- //create the wedge cell and insert it into the mesh >- vtkWedge * wedge = vtkWedge::New(); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >+ if(recreateBoundaryMesh) >+ { >+ vtkFloatArray *boundaryPointArray; >+ if(pointArray != NULL) >+ { >+ boundaryPointArray = pointArray; >+ } >+ else >+ { >+ boundaryPointArray = static_cast<vtkFloatArray *>( >+ this->InternalMesh->GetPoints()->GetData()); >+ } >+ // create boundary mesh >+ this->BoundaryMesh = this->MakeBoundaryMesh(this->BoundaryDict, facePoints, >+ boundaryPointArray); >+ if(this->BoundaryMesh == NULL) >+ { >+ delete facePoints; >+ if(pointArray != NULL) > { >- wedge->GetPointIds()->SetId(pCount, cellPoints[pCount]); >+ pointArray->Delete(); > } >- cellZoneMesh->InsertNextCell(wedge->GetCellType(), >- wedge->GetPointIds()); >- cellPoints.clear(); >- wedge->Delete(); >- firstFace.clear(); >+ return 0; > } >+ } > >- //OFpyramid | vtkPyramid >- else if (totalPointCount == 16) >+ delete facePoints; >+ >+ // if only point coordinates change refresh point vector >+ if(moveInternalPoints) >+ { >+ // refresh the points in each mesh >+ vtkPoints *points; >+ // Check if Internal Mesh exists first.... >+ if(this->InternalMesh != NULL) >+ { >+ points = this->MoveInternalMesh(this->InternalMesh, pointArray); >+ } >+ else > { >- foundDup = false; >+ points = vtkPoints::New(); >+ points->SetData(pointArray); >+ } > >- //find quad >- for(j = 0; j < (int)this->FacesOfCell->value[ >- cellZone[i]].size(); j++) //each face >+ if(this->PointZoneMesh != NULL) >+ { >+ for(size_t i = 0; i < this->PointZoneMesh->size(); i++) > { >- if((int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][j].faceIndex].size() == 4) >- { >- for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][j].faceIndex].size(); k++) >- { >- cellPoints.push_back(this->FacePoints->value[this->FacesOfCell-> >- value[cellZone[i]][j].faceIndex][k]); >- } >- break; >- } >+ this->PointZoneMesh->operator[](i)->SetPoints(points); > } >- >- //compare first face points to second faces >- for(j = 0; j < (int)cellPoints.size(); j++) //each point >+ } >+ if(this->FaceZoneMesh != NULL) >+ { >+ for(size_t i = 0; i < this->FaceZoneMesh->size(); i++) > { >- for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][1].faceIndex].size(); k++) >- { >- if(cellPoints[j] == this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][1].faceIndex][k]) >- { >- foundDup = true; >- } >- } >- if(!foundDup) >- { >- cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][j].faceIndex][k]); >- break; >- } >+ this->FaceZoneMesh->operator[](i)->SetPoints(points); > } >- >- //create the pyramid cell and insert it into the mesh >- vtkPyramid * pyramid = vtkPyramid::New(); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >+ } >+ if(this->CellZoneMesh != NULL) >+ { >+ for(size_t i = 0; i < this->CellZoneMesh->size(); i++) > { >- pyramid->GetPointIds()->SetId(pCount, cellPoints[pCount]); >+ this->CellZoneMesh->operator[](i)->SetPoints(points); > } >- cellZoneMesh->InsertNextCell(pyramid->GetCellType(), >- pyramid->GetPointIds()); >- cellPoints.clear(); >- pyramid->Delete(); > } >+ points->Delete(); >+ } > >- //OFtet | vtkTetrahedron >- else if (totalPointCount == 12) >+ if(moveBoundaryPoints) >+ { >+ // Check if Boundary Mesh exists first.... >+ if(this->BoundaryMesh != NULL) > { >- foundDup = false; >+ this->MoveBoundaryMesh(this->BoundaryMesh, pointArray); >+ } >+ } >+ >+ if(pointArray != NULL) >+ { >+ pointArray->Delete(); >+ } >+ this->UpdateProgress(0.5); > >- //grab first face >- for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][0].faceIndex].size(); j++) >+ polyDataVector *lagrangianMesh = new polyDataVector; >+ if(updateVariables) >+ { >+ if(!recreateInternalMesh && this->InternalMesh != NULL) >+ { >+ // clean up arrays of the previous timestep >+ // Check if Internal Mesh Exists first... >+ this->InternalMesh->GetCellData()->Initialize(); >+ this->InternalMesh->GetPointData()->Initialize(); >+ } >+ // Check if Boundary Mesh Exists first... >+ if(!recreateBoundaryMesh && this->BoundaryMesh != NULL) >+ { >+ for(size_t i = 0; i < this->BoundaryMesh->size(); i++) > { >- cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][0].faceIndex][j]); >+ this->BoundaryMesh->operator[](i)->GetCellData()->Initialize(); >+ this->BoundaryMesh->operator[](i)->GetPointData()->Initialize(); > } >+ } >+ // read field data variables into Internal/Boundary meshes >+ for(int i = 0; i < (int)this->VolFieldFiles->GetNumberOfValues(); i++) >+ { >+ this->GetVolFieldAtTimestep(this->InternalMesh, this->BoundaryMesh, >+ this->BoundaryDict, this->VolFieldFiles->GetValue(i).c_str(), >+ timeState); >+ this->UpdateProgress(0.5 + 0.25 * ((float)(i + 1) >+ / ((float)this->VolFieldFiles->GetNumberOfValues() + 0.0001))); >+ } >+ for(int i = 0; i < (int)this->PointFieldFiles->GetNumberOfValues(); i++) >+ { >+ this->GetPointFieldAtTimestep(this->InternalMesh, this->BoundaryMesh, >+ this->BoundaryDict, this->PointFieldFiles->GetValue(i).c_str(), >+ timeState); >+ this->UpdateProgress(0.75 + 0.125 * ((float)(i + 1) >+ / ((float)this->PointFieldFiles->GetNumberOfValues() + 0.0001))); >+ } > >- //compare first face points to second faces >- for(j = 0; j < (int)cellPoints.size(); j++) //each point >+ // read lagrangian mesh and fields >+ for(int cloudI = 0; cloudI < this->LagrangianPaths->GetNumberOfTuples(); >+ cloudI++) >+ { >+ const vtkStdString& pathI = this->LagrangianPaths->GetValue(cloudI); >+ if(this->GetPatchArrayStatus(pathI.c_str())) > { >- for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][1].faceIndex].size(); k++) >+ // construct lagrangian mesh >+ vtkPolyData *meshI = this->MakeLagrangianMesh(timeState, pathI); >+ if(meshI == NULL) >+ { >+ // if mesh doesn't exist we create an empty mesh to keep >+ // node/leaf structure of the multi-block consistent >+ meshI = vtkPolyData::New(); >+ this->SetDataObjectName(meshI, pathI.c_str()); >+ } >+ else > { >- if(cellPoints[j] == this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][1].faceIndex][k]) >+ // read lagrangian variables >+ for(int i = 0; i < this->LagrangianFieldFiles->GetNumberOfValues(); >+ i++) > { >- foundDup = true; >+ this->GetLagrangianFieldAtTimestep(meshI, >+ this->LagrangianFieldFiles->GetValue(i).c_str(), timeState, >+ pathI); > } > } >- if(!foundDup) >- { >- cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][j].faceIndex][k]); >- break; >- } >- } >- >- //create the wedge cell and insert it into the mesh >- vtkTetra * tetra = vtkTetra::New(); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >- { >- tetra->GetPointIds()->SetId(pCount, cellPoints[pCount]); >+ lagrangianMesh->push_back(meshI); > } >- cellZoneMesh->InsertNextCell(tetra->GetCellType(), >- tetra->GetPointIds()); >- cellPoints.clear(); >- tetra->Delete(); > } >+ } >+ >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ // do nothing >+#else >+ // assign group to each of data and point/face/cell-Zones >+ int nGroups = 1 >+ + ((lagrangianMesh->size() != 0 >+ || this->GetPatchArrayStatus("Lagrangian Particles")) ? 1 : 0) >+ + (this->PointZoneMesh != NULL ? 1 : 0) >+ + (this->FaceZoneMesh != NULL ? 1 : 0) >+ + (this->CellZoneMesh != NULL ? 1 : 0); >+ output->SetNumberOfGroups(nGroups); >+#endif >+ >+ // set internal mesh/data as output >+ >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ vtkMultiBlockDataSet *eulerians = vtkMultiBlockDataSet::New(); >+#endif >+ >+ // Add Internal Mesh to final output only if selected for display >+ if(this->InternalMesh != NULL) >+ { >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ eulerians->SetBlock(0, this->InternalMesh); >+ this->SetBlockName(eulerians, 0, this->InternalMesh); >+#else >+ output->SetDataSet(0, output->GetNumberOfDataSets(0), this->InternalMesh); >+#endif >+ } > >- //erronous cells >- else if(totalPointCount == 0) >+ // set boundary meshes/data as output >+ for(size_t j = 0; j < this->BoundaryMesh->size(); j++) >+ { >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ const unsigned int dataSetI = eulerians->GetNumberOfBlocks(); >+ eulerians->SetBlock(dataSetI, this->BoundaryMesh->operator[](j)); >+ this->SetBlockName(eulerians, dataSetI, this->BoundaryMesh->operator[](j)); >+#else >+ output->SetDataSet(0, output->GetNumberOfDataSets(0), >+ this->BoundaryMesh->operator[](j)); >+#endif >+ } >+ >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ output->SetBlock(0, eulerians); >+ output->GetMetaData(static_cast<unsigned int>(0)) >+ ->Set(vtkCompositeDataSet::NAME(), "Vol/Point Data"); >+ eulerians->Delete(); >+#else >+ int groupI = 1; >+#endif >+ >+ // set lagrangian mesh as output >+ if(lagrangianMesh->size() > 0) >+ { >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ vtkMultiBlockDataSet *lagrangians = vtkMultiBlockDataSet::New(); >+#endif >+ for(size_t meshI = 0; meshI < lagrangianMesh->size(); meshI++) > { >- vtkWarningMacro("Warning: No points in cell."); >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ lagrangians->SetBlock(meshI, lagrangianMesh->operator[](meshI)); >+ this->SetBlockName(lagrangians, meshI, lagrangianMesh->operator[](meshI)); >+#else >+ output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI), >+ lagrangianMesh->operator[](meshI)); >+#endif > } >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ const unsigned int groupTypeI = output->GetNumberOfBlocks(); >+ output->SetBlock(groupTypeI, lagrangians); >+ output->GetMetaData(groupTypeI) >+ ->Set(vtkCompositeDataSet::NAME(), "Lagrangian Particles"); >+ lagrangians->Delete(); >+#else >+ groupI++; >+#endif >+ } >+ delete lagrangianMesh; > >- //OFpolyhedron || vtkConvexPointSet >- else >+ if(this->ReadZones) >+ { >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ vtkMultiBlockDataSet *zones = NULL; >+#endif >+ // set Zone Meshes as output >+ if(this->PointZoneMesh != NULL) > { >- vtkWarningMacro("Warning: Polyhedral Data is very Slow!"); >- foundDup = false; >- >- //grab face 0 >- for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[ >- cellZone[i]][0].faceIndex].size(); j++) >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ if(zones == NULL) >+ { >+ zones = vtkMultiBlockDataSet::New(); >+ } >+ vtkMultiBlockDataSet *pointZone = vtkMultiBlockDataSet::New(); >+#endif >+ for(size_t i = 0; i < this->PointZoneMesh->size(); i++) > { >- firstFace.push_back(this->FacePoints->value[ >- this->FacesOfCell->value[i][0].faceIndex][j]); >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ const unsigned int zoneI = pointZone->GetNumberOfBlocks(); >+ vtkDataObject *zoneMeshI = this->PointZoneMesh->operator[](i); >+ pointZone->SetBlock(zoneI, zoneMeshI); >+ this->SetBlockName(pointZone, zoneI, zoneMeshI); >+#else >+ output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI), >+ this->PointZoneMesh->operator[](i)); >+#endif > } >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ const unsigned int zoneTypeI = zones->GetNumberOfBlocks(); >+ zones->SetBlock(zoneTypeI, pointZone); >+ this->SetBlockName(zones, zoneTypeI, "pointZones"); >+ pointZone->Delete(); >+#else >+ groupI++; >+#endif >+ } > >- //ADD FIRST FACE TO CELL POINTS >- for(j =0; j < (int)firstFace.size(); j++) >- { >- cellPoints.push_back(firstFace[j]); >- } >- //j = 1 skip firstFace >- for(j = 1; j < (int) this->FacesOfCell->value[ >- cellZone[i]].size(); j++) >- { >- //remove duplicate points from faces >- for(k = 0; k < (int)this->FacePoints->value[ >- this->FacesOfCell->value[i][j].faceIndex].size(); k++) >- { >- for(l = 0; l < (int)cellPoints.size(); l++); >- { >- if(cellPoints[l] == this->FacePoints->value[this->FacesOfCell-> >- value[cellZone[i]][j].faceIndex][k]) >- { >- foundDup = true; >- } >- } >- if(!foundDup) >- { >- cellPoints.push_back(this->FacePoints->value[this->FacesOfCell-> >- value[cellZone[i]][j].faceIndex][k]); >- foundDup = false; >- } >- } >+ if(this->FaceZoneMesh != NULL) >+ { >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ if(zones == NULL) >+ { >+ zones = vtkMultiBlockDataSet::New(); >+ } >+ vtkMultiBlockDataSet *faceZone = vtkMultiBlockDataSet::New(); >+#endif >+ for(size_t i = 0; i < this->FaceZoneMesh->size(); i++) >+ { >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ const unsigned int zoneI = faceZone->GetNumberOfBlocks(); >+ vtkDataObject *zoneMeshI = this->FaceZoneMesh->operator[](i); >+ faceZone->SetBlock(zoneI, zoneMeshI); >+ this->SetBlockName(faceZone, zoneI, zoneMeshI); >+#else >+ output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI), >+ this->FaceZoneMesh->operator[](i)); >+#endif > } >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ const unsigned int zoneTypeI = zones->GetNumberOfBlocks(); >+ zones->SetBlock(zoneTypeI, faceZone); >+ this->SetBlockName(zones, zoneTypeI, "faceZones"); >+ faceZone->Delete(); >+#else >+ groupI++; >+#endif >+ } > >- //create the poly cell and insert it into the mesh >- vtkConvexPointSet * poly = vtkConvexPointSet::New(); >- poly->GetPointIds()->SetNumberOfIds(cellPoints.size()); >- for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) >- { >- poly->GetPointIds()->SetId(pCount, cellPoints[pCount]); >- } >- cellZoneMesh->InsertNextCell(poly->GetCellType(), >- poly->GetPointIds()); >- cellPoints.clear(); >- firstFace.clear(); >- poly->Delete(); >+ if(this->CellZoneMesh != NULL) >+ { >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ if(zones == NULL) >+ { >+ zones = vtkMultiBlockDataSet::New(); >+ } >+ vtkMultiBlockDataSet *cellZone = vtkMultiBlockDataSet::New(); >+#endif >+ for(size_t i = 0; i < this->CellZoneMesh->size(); i++) >+ { >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ const unsigned int zoneI = cellZone->GetNumberOfBlocks(); >+ vtkDataObject *zoneMeshI = this->CellZoneMesh->operator[](i); >+ cellZone->SetBlock(zoneI, zoneMeshI); >+ this->SetBlockName(cellZone, zoneI, zoneMeshI); >+#else >+ output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI), >+ this->CellZoneMesh->operator[](i)); >+#endif >+ } >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ const unsigned int zoneTypeI = zones->GetNumberOfBlocks(); >+ zones->SetBlock(zoneTypeI, cellZone); >+ this->SetBlockName(zones, zoneTypeI, "cellZones"); >+ cellZone->Delete(); >+#endif >+ } >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ if(zones != NULL) >+ { >+ const unsigned int groupTypeI = output->GetNumberOfBlocks(); >+ output->SetBlock(groupTypeI, zones); >+ this->SetBlockName(output, groupTypeI, "Zones"); > } >+#endif > } >- //set cell zone points >- cellZoneMesh->SetPoints(Points); >- input->close(); >- delete input; >- vtkDebugMacro(<<"Cell zone mesh created"); >- return cellZoneMesh; >-} > >-void vtkOpenFOAMReader::CreateDataSet(vtkMultiBlockDataSet *output) >-{ >- int timeState = this->TimeStep; >- //create paths to polyMesh files >- vtkstd::string boundaryPath = this->PathPrefix->value + >- this->PolyMeshFacesDir->value[timeState] + >- "/polyMesh/boundary"; >- vtkstd::string facePath = this->PathPrefix->value + >- this->PolyMeshFacesDir->value[timeState] + >- "/polyMesh/faces"; >- vtkstd::string ownerPath = this->PathPrefix->value + >- this->PolyMeshFacesDir->value[timeState] + >- "/polyMesh/owner"; >- vtkstd::string neighborPath = this->PathPrefix->value + >- this->PolyMeshFacesDir->value[timeState] + >- "/polyMesh/neighbour"; >- //create the faces vector >- this->ReadFacesFile(facePath.c_str()); >- >- //create the faces owner vector >- this->ReadOwnerFile(ownerPath.c_str()); >- >- //create the faces neighbor vector >- this->ReadNeighborFile(neighborPath.c_str()); >- >- //create a vector containing a faces of each cell >- this->CombineOwnerNeigbor(); >- >- this->GetPoints(timeState); //get the points >- >- //get the names of the regions >- //this->BoundaryNames->value = >- // this->GatherBlocks("boundary", timeState)->value; >- //this->PointZoneNames->value = >- // this->GatherBlocks("pointZones", timeState)->value; >- //this->FaceZoneNames->value = >- // this->GatherBlocks("faceZones", timeState)->value; >- //this->CellZoneNames->value = >- // this->GatherBlocks("cellZones", timeState)->value; >- >- //get the names of the regions >- this->BoundaryNames = >- this->GatherBlocks("boundary", timeState); >- this->PointZoneNames = >- this->GatherBlocks("pointZones", timeState); >- this->FaceZoneNames = >- this->GatherBlocks("faceZones", timeState); >- this->CellZoneNames = >- this->GatherBlocks("cellZones", timeState); >- >- int numBoundaries = static_cast<int>(this->BoundaryNames->value.size()); >- int numPointZones = static_cast<int>(this->PointZoneNames->value.size()); >- int numFaceZones = static_cast<int>(this->FaceZoneNames->value.size()); >- int numCellZones = static_cast<int>(this->CellZoneNames->value.size()); >- >- //Internal Mesh >- vtkUnstructuredGrid * internalMesh = this->MakeInternalMesh(); >- for(int i = 0; i < (int)this->TimeStepData->value.size(); i++) >- { >- vtkDoubleArray * data = >- this->GetInternalVariableAtTimestep(this->TimeStepData->value[i].c_str(), >- timeState); >- if(data->GetSize() > 0) >- { >- data->SetName(this->TimeStepData->value[i].c_str()); >- internalMesh->GetCellData()->AddArray(data); >- } >- data->Delete(); >- } >- output->SetBlock(output->GetNumberOfBlocks(), internalMesh); >- >- //Boundary Meshes >- for(int i = 0; i < (int)numBoundaries; i++) >- { >- vtkUnstructuredGrid * boundaryMesh = this->GetBoundaryMesh(timeState, i); >- for(int j = 0; j < (int)this->TimeStepData->value.size(); j++) >- { >- vtkDoubleArray * data = >- this->GetBoundaryVariableAtTimestep(i, TimeStepData->value[j].c_str(), >- timeState, internalMesh); >- if(data->GetSize() > 0) >- { >- data->SetName(this->TimeStepData->value[j].c_str()); >- boundaryMesh->GetCellData()->AddArray(data); >- } >- data->Delete(); >- } >- output->SetBlock(output->GetNumberOfBlocks(), boundaryMesh); >- boundaryMesh->Delete(); >- } >- >- internalMesh->Delete(); >- this->FaceOwner->Delete(); >- //Zone Meshes >- for(int i = 0; i < (int)numPointZones; i++) >- { >- vtkUnstructuredGrid * pointMesh = this->GetPointZoneMesh(timeState, i); >- output->SetBlock(output->GetNumberOfBlocks(), pointMesh); >- pointMesh->Delete(); >- } >- for(int i = 0; i < (int)numFaceZones; i++) >- { >- vtkUnstructuredGrid * faceMesh = this->GetFaceZoneMesh(timeState, i); >- output->SetBlock(output->GetNumberOfBlocks(), faceMesh); >- faceMesh->Delete(); >- } >- for(int i = 0; i < (int)numCellZones; i++) >- { >- vtkUnstructuredGrid * cellMesh = this->GetCellZoneMesh(timeState, i); >- output->SetBlock(output->GetNumberOfBlocks(), cellMesh); >- cellMesh->Delete(); >+ if(this->CacheMesh) >+ { >+ this->TimeStepOld = timeState; > } >- return; >-} >-stdString * vtkOpenFOAMReader::GetLine(ifstream * file) >-{ >- char tempChar; >- stdString * buffer = new stdString; >- while(file->peek() != '\n') >+ else > { >- file->get(tempChar); >- buffer->value += tempChar; >+ this->ClearMeshes(); >+ this->TimeStepOld = -1; > } >- file->get(tempChar); //throw out \n >- return buffer; >+ >+ this->UpdateProgress(1.0); >+ return 1; > } >--- ParaView3-src/VTK/IO/vtkOpenFOAMReader.h 2007-01-18 16:56:52.000000000 +0100 >+++ ParaView3-20080728/VTK/IO/vtkOpenFOAMReader.h 2008-07-26 06:57:00.000000000 +0200 >@@ -23,30 +23,36 @@ > // .SECTION Thanks > // Thanks to Terry Jordan of SAIC at the National Energy > // Technology Laboratory who developed this class. >-// Please address all comments to Terry Jordan (terry.jordan@sa.netl.doe.gov) >+// Please address all comments to Terry Jordan (terry.jordan@sa.netl.doe.gov). >+// Gzipped file, lagrangian field, new UI support and >+// performance/compatibility enhancements by Takuya Oshima >+// (oshima@eng.niigata-u.ac.jp) and Philippose Rajan (sarith@rocketmail.com). >+ >+// version 2008-07-24 > > #ifndef __vtkOpenFOAMReader_h > #define __vtkOpenFOAMReader_h > > #include "vtkMultiBlockDataSetAlgorithm.h" >+#include "vtkPVConfig.h" // for PARAVIEW_VERSION_MAJOR, PARAVIEW_VERSION_MINOR > >-typedef struct >-{ >- int faceIndex; >- bool neighborFace; >-} face; >- >-class vtkUnstructuredGrid; >-class vtkPoints; >-class vtkIntArray; >-class vtkFloatArray; >-class vtkDoubleArray; >+class vtkCallbackCommand; > class vtkDataArraySelection; >-struct stdString; >-struct stringVector; >-struct intVector; >-struct intVectorVector; >-struct faceVectorVector; >+class vtkDataObject; >+class vtkDataSetAttributes; >+class vtkFloatArray; >+class vtkIdList; >+class vtkIdTypeArray; >+class vtkIntArray; >+class vtkPoints; >+class vtkPolyData; >+class vtkStdString; >+class vtkStringArray; >+class vtkUnstructuredGrid; >+//BTX >+class intArrayVector; >+class unstructuredGridVector; >+//ETX > > class VTK_IO_EXPORT vtkOpenFOAMReader : public vtkMultiBlockDataSetAlgorithm > { >@@ -56,6 +62,10 @@ > void PrintSelf(ostream& os, vtkIndent indent); > > // Description: >+ // Determine if the file can be readed with this reader. >+ int CanReadFile(const char* fname); >+ >+ // Description: > // Set/Get the filename. > vtkSetStringMacro(FileName); > vtkGetStringMacro(FileName); >@@ -80,85 +90,349 @@ > // Description: > // Get/Set whether the cell array with the given name is to > // be read. >- int GetCellArrayStatus(const char* name); >- void SetCellArrayStatus(const char* name, int status); >+ int GetCellArrayStatus(const char *name); >+ void SetCellArrayStatus(const char *name, int status); > > // Description: > // Get the name of the cell array with the given index in > // the input. >- const char* GetCellArrayName(int index); >+ const char *GetCellArrayName(int index); > > // Description: > // Turn on/off all cell arrays. > void DisableAllCellArrays(); > void EnableAllCellArrays(); > >+ // Description: >+ // Get the number of point arrays available in the input. >+ int GetNumberOfPointArrays(void); >+ >+ // Description: >+ // Get/Set whether the point array with the given name is to >+ // be read. >+ int GetPointArrayStatus(const char *name); >+ void SetPointArrayStatus(const char *name, int status); >+ >+ // Description: >+ // Get the name of the point array with the given index in >+ // the input. >+ const char* GetPointArrayName(int index); >+ >+ // Description: >+ // Turn on/off all point arrays. >+ void DisableAllPointArrays(); >+ void EnableAllPointArrays(); >+ >+ // Description: >+ // Get the number of point arrays available in the input. >+ int GetNumberOfLagrangianArrays(void); >+ >+ // Description: >+ // Get/Set whether the point array with the given name is to >+ // be read. >+ int GetLagrangianArrayStatus(const char *name); >+ void SetLagrangianArrayStatus(const char *name, int status); >+ >+ // Description: >+ // Get the name of the point array with the given index in >+ // the input. >+ const char* GetLagrangianArrayName(int index); >+ >+ // Description: >+ // Turn on/off all point arrays. >+ void DisableAllLagrangianArrays(); >+ void EnableAllLagrangianArrays(); >+ >+ // Description: >+ // Get the number of Patches (inlcuding Internal Mesh) available in the input. >+ int GetNumberOfPatchArrays(void); >+ >+ // Description: >+ // Get/Set whether the Patch with the given name is to >+ // be read. >+ int GetPatchArrayStatus(const char *name); >+ void SetPatchArrayStatus(const char *name, int status); >+ >+ // Description: >+ // Get the name of the Patch with the given index in >+ // the input. >+ const char *GetPatchArrayName(int index); >+ >+ // Description: >+ // Turn on/off all Patches including the Internal Mesh. >+ void DisableAllPatchArrays(); >+ void EnableAllPatchArrays(); >+ >+ // Selection observer callback functions >+ static void SelectionModifiedCallback >+ ( >+ vtkObject *caller, >+ unsigned long eid, >+ void *clientdata, >+ void *calldata >+ ); >+ >+ void SelectionModified(const bool); >+ >+ // Description: >+ // Set/Get whether to create cell-to-point translated data for cell-type data >+ vtkSetMacro(CreateCellToPoint,int); >+ vtkGetMacro(CreateCellToPoint,int); >+ vtkBooleanMacro(CreateCellToPoint, int); >+ >+ // Description: >+ // Set/Get whether mesh is to be cached. >+ vtkSetMacro(CacheMesh, int); >+ vtkGetMacro(CacheMesh, int); >+ vtkBooleanMacro(CacheMesh, int); >+ >+ // Description: >+ // Set/Get whether polyhedra are to be decomposed. >+ vtkSetMacro(DecomposePolyhedra, int); >+ vtkGetMacro(DecomposePolyhedra, int); >+ vtkBooleanMacro(DecomposePolyhedra, int); >+ >+ // Option to accumulate patches and fields across time steps >+ // Description: >+ // Set/Get whether the patches are listed even if size = 0 >+ vtkSetMacro(KeepPatches, int); >+ vtkGetMacro(KeepPatches, int); >+ vtkBooleanMacro(KeepPatches, int); >+ >+ // Option for reading old binary lagrangian/positions format >+ // Description: >+ // Set/Get whether the lagrangian/positions is in OF 1.3 format >+ vtkSetMacro(PositionsIsIn13Format, int); >+ vtkGetMacro(PositionsIsIn13Format, int); >+ vtkBooleanMacro(PositionsIsIn13Format, int); >+ >+ // Description: >+ // Determine if time directories are to be listed according to controlDict >+ vtkSetMacro(ListTimeStepsByControlDict, int); >+ vtkGetMacro(ListTimeStepsByControlDict, int); >+ vtkBooleanMacro(ListTimeStepsByControlDict, int); >+ >+ // Description: >+ // Add dimensions to array names >+ vtkSetMacro(AddDimensionsToArrayNames, int); >+ vtkGetMacro(AddDimensionsToArrayNames, int); >+ vtkBooleanMacro(AddDimensionsToArrayNames, int); >+ >+ // Description: >+ // Set/Get whether zones will be read. >+ vtkSetMacro(ReadZones, int); >+ vtkGetMacro(ReadZones, int); >+ vtkBooleanMacro(ReadZones, int); > > protected: >+ // for creating cell-to-point translated data >+ int CreateCellToPoint; >+ >+ // for caching mesh >+ int CacheMesh; >+ >+ // for decomposing polyhedra on-the-fly >+ int DecomposePolyhedra; >+ >+ // for accumulating patches across time steps >+ int KeepPatches; >+ >+ // for reading old binary lagrangian/positions format >+ int PositionsIsIn13Format; >+ >+ // for reading point/face/cell-Zones >+ int ReadZones; >+ >+ // determine if time directories are listed according to controlDict >+ int ListTimeStepsByControlDict; >+ >+ // add dimensions to array names >+ int AddDimensionsToArrayNames; >+ > vtkOpenFOAMReader(); > ~vtkOpenFOAMReader(); >- int RequestData(vtkInformation *, >- vtkInformationVector **, vtkInformationVector *); >- int RequestInformation(vtkInformation *, >- vtkInformationVector **, vtkInformationVector *); >+ int RequestData(vtkInformation *, vtkInformationVector **, >+ vtkInformationVector *); >+ int RequestInformation(vtkInformation *, vtkInformationVector **, >+ vtkInformationVector *); > > private: >+ struct vtkFoamError; >+ struct vtkFoamToken; >+ struct vtkFoamFileStack; >+ struct vtkFoamFile; >+ struct vtkFoamIOobject; >+ struct vtkFoamEntryValue; >+ struct vtkFoamEntry; >+ struct vtkFoamDict; >+ struct vtkFoamBoundaryDict; >+ >+ // declared inside the vtkOpenFOAMReader class for workarounding a >+ // bug in MSVC++ >+ struct intVectorVector; >+ > vtkOpenFOAMReader(const vtkOpenFOAMReader&); // Not implemented. > void operator=(const vtkOpenFOAMReader&); // Not implemented. > > vtkSetVector2Macro(TimeStepRange, int); > >- char * FileName; >+ char *FileName; > int NumberOfTimeSteps; > int TimeStep; > int TimeStepRange[2]; >- double * Steps; >- bool RequestInformationFlag; >- int StartFace; >- >- stdString * Path; >- stdString * PathPrefix; >- stringVector * TimeStepData; >- vtkDataArraySelection * CellDataArraySelection; >- intVectorVector * FacePoints; >- intVectorVector * FacesOwnerCell; >- intVectorVector * FacesNeighborCell; >- faceVectorVector * FacesOfCell; >- vtkPoints * Points; >+ double *Steps; >+ int ListTimeStepsByControlDictOld; >+ >+ // Selection Observer for translating GUI Changes to Mesh Updates >+ vtkCallbackCommand *SelectionObserver; >+ >+ // DataArraySelection for Patch / Region Data >+ vtkDataArraySelection *PatchDataArraySelection; >+ vtkDataArraySelection *CellDataArraySelection; >+ vtkDataArraySelection *PointDataArraySelection; >+ vtkDataArraySelection *LagrangianDataArraySelection; >+ >+ // Previous and Current Status of each of the selection arrays (in >+ // Bitwise form). Maximum 31 patches or fields support as of now >+ // (since we use LSB for overflow handling) >+ unsigned long CellSelectionOldStatus; >+ unsigned long PointSelectionOldStatus; >+ unsigned long LagrangianSelectionOldStatus; >+ unsigned long PatchSelectionOldStatus; >+ unsigned long CellSelectionStatus; >+ unsigned long PointSelectionStatus; >+ unsigned long LagrangianSelectionStatus; >+ unsigned long PatchSelectionStatus; >+ int ReadZonesOld; >+ >+ // filenames / directories >+ vtkStdString *OldFileName; >+ vtkStdString *PathPrefix; >+ vtkStringArray *TimeNames; >+ vtkStringArray *VolFieldFiles; >+ vtkStringArray *PointFieldFiles; >+ vtkStringArray *LagrangianPaths; >+ vtkStringArray *LagrangianFieldFiles; >+ vtkStringArray *PolyMeshPointsDir; >+ vtkStringArray *PolyMeshFacesDir; >+ >+ // for mesh construction > vtkIdType NumCells; >- vtkIdType NumFaces; >- vtkIntArray * FaceOwner; >- //vtkIntArray * FaceNeighbor; >- stringVector * PolyMeshPointsDir; >- stringVector * PolyMeshFacesDir; > vtkIdType NumPoints; >- intVector * SizeOfBoundary; >- stringVector * BoundaryNames; >- stringVector * PointZoneNames; >- stringVector * FaceZoneNames; >- stringVector * CellZoneNames; >- int NumBlocks; >- >- void CombineOwnerNeigbor(); >- vtkUnstructuredGrid * MakeInternalMesh(); >- double ControlDictDataParser(const char *); >- void ReadControlDict (); >- void GetPoints (int); >- void ReadFacesFile (const char *); >- void ReadOwnerFile(const char *); >- void ReadNeighborFile(const char *); >+ vtkIntArray *FaceOwner; >+ >+ // for cell-to-point interpolation >+ vtkUnstructuredGrid *AllBoundaries; >+ vtkIntArray *AllBoundariesPointMap; >+ vtkIntArray *InternalPoints; >+ int CreateCellToPointOld; >+ >+ // for caching mesh >+ vtkUnstructuredGrid *InternalMesh; >+ unstructuredGridVector *BoundaryMesh; >+ intArrayVector *BoundaryPointMap; >+ vtkFoamBoundaryDict *BoundaryDict; >+ unstructuredGridVector *PointZoneMesh; >+ unstructuredGridVector *FaceZoneMesh; >+ unstructuredGridVector *CellZoneMesh; >+ int TimeStepOld; >+ >+ // for polyhedra handling >+ vtkIntArray *AdditionalCellIds; >+ intArrayVector *AdditionalCellPoints; >+ int DecomposePolyhedraOld; >+ >+ // for accumulating patches across time steps >+ int KeepPatchesOld; >+ >+ // for reading old binary lagrangian/positions format >+ int PositionsIsIn13FormatOld; >+ >+ // for addiing dimensions to array names >+ int AddDimensionsToArrayNamesOld; >+ >+ // member functions >+ void ClearInternalMeshes(); >+ void ClearBoundaryMeshes(); >+ void ClearMeshes(); >+ >+ // Calculate selection status variables >+ unsigned long CreateSelectionStatus(vtkDataArraySelection *, unsigned long); >+ >+ // search time directories for mesh >+ void AppendMeshDirToArray(vtkStringArray *, const char *, const int); > void PopulatePolyMeshDirArrays(); >- const char * GetDataType(const char *, const char *); >- vtkDoubleArray * GetInternalVariableAtTimestep(const char *, int); >- vtkDoubleArray * GetBoundaryVariableAtTimestep(int, const char *, int, >- vtkUnstructuredGrid *); >- stringVector *GatherBlocks(const char *, int); >- vtkUnstructuredGrid * GetBoundaryMesh(int, int); >- vtkUnstructuredGrid * GetPointZoneMesh(int, int); >- vtkUnstructuredGrid * GetFaceZoneMesh(int, int); >- vtkUnstructuredGrid * GetCellZoneMesh(int, int); >- void CreateDataSet(vtkMultiBlockDataSet *); >- stdString * GetLine(ifstream *); >+ >+ // search a time directory for field objects >+ void GetFieldNames(const char *, const bool, vtkStringArray *, >+ vtkStringArray *); >+ void LocateLagrangianClouds(vtkStringArray *, const vtkStdString &); >+ int MakeTimeStepData(const bool); >+ >+ // read controlDict >+ bool ListTimeDirectoriesByControlDict(vtkFoamDict *dict); >+ bool ListTimeDirectoriesByInstances(); >+ bool ReadControlDict(const char *); >+ >+ // read mesh files >+ vtkFloatArray* ReadPointsFile(int); >+ intVectorVector* ReadFacesFile (const char *); >+ bool ReadOwnerNeighborFiles(vtkIntArray *, vtkIntArray *, const char *, >+ const char *); >+ >+ // create mesh >+ void InsertCellsToGrid(vtkUnstructuredGrid *, vtkIntArray *, vtkIntArray *, >+ const intVectorVector *, vtkFloatArray *, vtkIdTypeArray *, >+ vtkIntArray *); >+ vtkUnstructuredGrid *MakeInternalMesh(vtkIntArray *, vtkIntArray *, >+ const intVectorVector *, vtkFloatArray *); >+ void InsertFacesToGrid(vtkUnstructuredGrid *, const intVectorVector *, >+ int, int, vtkIntArray *, vtkIdList *, vtkIntArray *, const bool); >+ unstructuredGridVector* MakeBoundaryMesh(vtkFoamBoundaryDict *, >+ const intVectorVector *, vtkFloatArray *); >+ void SetDataObjectName(vtkDataObject *, const char *); >+#if PARAVIEW_VERSION_MAJOR >= 3 && PARAVIEW_VERSION_MINOR >= 3 >+ void SetBlockName(vtkMultiBlockDataSet *, unsigned int, const char *); >+ void SetBlockName(vtkMultiBlockDataSet *, unsigned int, vtkDataObject *); >+#endif >+ void TruncateFaceOwner(); >+ >+ // move additional points for decomposed cells >+ vtkPoints *MoveInternalMesh(vtkUnstructuredGrid *, vtkFloatArray *); >+ void MoveBoundaryMesh(unstructuredGridVector *, vtkFloatArray *); >+ >+ // cell-to-point interpolator >+ void InterpolateCellToPoint(vtkFloatArray *, vtkFloatArray *, >+ vtkUnstructuredGrid *, vtkIntArray *, const int); >+ >+ // read and create cell/point fields >+ void ConstructDimensions(vtkStdString *, vtkFoamDict *); >+ bool ReadFieldFile(vtkFoamIOobject *, vtkFoamDict *, const char *, int, >+ vtkDataArraySelection *); >+ vtkFloatArray *FillField(vtkFoamEntry *, int, vtkFoamIOobject *, >+ const vtkStdString *); >+ void GetVolFieldAtTimestep(vtkUnstructuredGrid *, unstructuredGridVector *, >+ vtkFoamBoundaryDict *, const char *, int); >+ void GetPointFieldAtTimestep(vtkUnstructuredGrid *, unstructuredGridVector *, >+ vtkFoamBoundaryDict *, const char *, int); >+ void AddArrayToFieldData(vtkDataSetAttributes *, vtkDataArray *, >+ const vtkStdString &); >+ >+ // create lagrangian mesh/fields >+ vtkPolyData *MakeLagrangianMesh(int, const vtkStdString &); >+ void GetLagrangianFieldAtTimestep(vtkPolyData *, const char *, int, >+ const vtkStdString &); >+ >+ // create point/face/cell zones >+ vtkFoamDict *GatherBlocks(const char *, int, bool); >+ bool GetPointZoneMesh(unstructuredGridVector *, vtkPoints *, int); >+ bool GetFaceZoneMesh(unstructuredGridVector *, const intVectorVector *, >+ vtkPoints *, int); >+ bool GetCellZoneMesh(unstructuredGridVector *, vtkIntArray *, vtkIntArray *, >+ const intVectorVector *, vtkPoints *, int); >+ >+ // read mesh/fields and create dataset >+ int CreateDataSet(vtkMultiBlockDataSet *, int); > }; > > #endif >--- ParaView3/Servers/ServerManager/Resources/readers.xml.orig 2008-07-28 19:23:24.000000000 +0900 >+++ ParaView3/Servers/ServerManager/Resources/readers.xml 2008-07-28 19:56:24.000000000 +0900 >@@ -3806,65 +3806,203 @@ > </SourceProxy> > > <!-- Beginning of FOAM Reader --> >- <SourceProxy name="OpenFOAMReader" >- class="vtkOpenFOAMReader"> >- <StringVectorProperty name="FileName" >- command="SetFileName" >- animateable="0" >- number_of_elements="1"> >- <FileListDomain name="files"/> >- <Documentation> >- Set the file name for the OpenFOAM reader. >- </Documentation> >- </StringVectorProperty> >- <StringVectorProperty name="CellArrayInfo" >- information_only="1"> >- <ArraySelectionInformationHelper attribute_name="Cell"/> >- </StringVectorProperty> >- <StringVectorProperty name="CellArrayStatus" >- command="SetCellArrayStatus" >- number_of_elements="0" >- repeat_command="1" >- number_of_elements_per_command="2" >- element_types="2 0" >- information_property="CellArrayInfo" >- label="Cell Arrays"> >- <ArraySelectionDomain name="array_list"> >- <RequiredProperties> >- <Property name="CellArrayInfo" function="ArrayList"/> >- </RequiredProperties> >- </ArraySelectionDomain> >- <Documentation> >- Select which cell-centered arrays to read. >- </Documentation> >- </StringVectorProperty> >- <IntVectorProperty name="TimeStepRangeInfo" >- command="GetTimeStepRange" >- information_only="1"> >- <SimpleIntInformationHelper/> >- </IntVectorProperty> >- <IntVectorProperty name="TimeStep" >- command="SetTimeStep" >+ <SourceProxy >+ >+ name="OpenFOAMReader" >+ class="vtkOpenFOAMReader" >+ output="vtkDataSet"> >+ >+ <StringVectorProperty >+ name="FileName" >+ command="SetFileName" >+ number_of_elements="1"> >+ <FileListDomain name="files"/> >+ </StringVectorProperty> >+ >+ <IntVectorProperty >+ name="CreateCellToPoint" >+ command="SetCreateCellToPoint" >+ number_of_elements="1" >+ default_values="1" >+ label="Create cell-to-point filtered data"> >+ <BooleanDomain name="bool"/> >+ <Documentation> >+ Create cell-to-point filtered data. >+ </Documentation> >+ </IntVectorProperty> >+ >+ <IntVectorProperty name="AddDimensionsToArrayNames" >+ command="SetAddDimensionsToArrayNames" > number_of_elements="1" >- animateable="1" >- default_values="0"> >- <IntRangeDomain name="range"> >- <RequiredProperties> >- <Property name="TimeStepRangeInfo" function="Range"/> >- </RequiredProperties> >- </IntRangeDomain> >- <Documentation> >- Set the current timestep. >- </Documentation> >- </IntVectorProperty> >- <DoubleVectorProperty >- name="TimestepValues" >- repeatable="1" >- information_only="1"> >- <TimeStepsInformationHelper/> >- </DoubleVectorProperty> >+ default_values="0" >+ label="Add dimensional units to array names"> >+ <BooleanDomain name="bool"/> >+ <Documentation> >+ Read dimensional units from field data and add them to array names as human-understandable string. >+ </Documentation> >+ </IntVectorProperty> >+ >+ <DoubleVectorProperty >+ name="TimestepValues" >+ repeatable="1" >+ information_only="1"> >+ <TimeStepsInformationHelper/> >+ </DoubleVectorProperty> >+ >+ <StringVectorProperty >+ name="PatchArrayInfo" >+ information_only="1"> >+ <ArraySelectionInformationHelper attribute_name="Patch"/> >+ </StringVectorProperty> >+ <StringVectorProperty >+ name="MeshRegions" >+ command="SetPatchArrayStatus" >+ number_of_elements="0" >+ repeat_command="1" >+ number_of_elements_per_command="2" >+ element_types="2 0" >+ information_property="PatchArrayInfo"> >+ <ArraySelectionDomain name="array_list"> >+ <RequiredProperties> >+ <Property name="PatchArrayInfo" >+ function="ArrayList"/> >+ </RequiredProperties> >+ </ArraySelectionDomain> >+ </StringVectorProperty> >+ >+ <StringVectorProperty >+ name="CellArrayInfo" >+ information_only="1"> >+ <ArraySelectionInformationHelper attribute_name="Cell"/> >+ </StringVectorProperty> >+ <StringVectorProperty >+ name="CellArrays" >+ command="SetCellArrayStatus" >+ number_of_elements="0" >+ repeat_command="1" >+ number_of_elements_per_command="2" >+ element_types="2 0" >+ information_property="CellArrayInfo"> >+ <ArraySelectionDomain name="array_list"> >+ <RequiredProperties> >+ <Property name="CellArrayInfo" >+ function="ArrayList"/> >+ </RequiredProperties> >+ </ArraySelectionDomain> >+ </StringVectorProperty> >+ >+ <StringVectorProperty >+ name="PointArrayInfo" >+ information_only="1"> >+ <ArraySelectionInformationHelper attribute_name="Point"/> >+ </StringVectorProperty> >+ <StringVectorProperty >+ name="PointArrays" >+ command="SetPointArrayStatus" >+ number_of_elements="0" >+ repeat_command="1" >+ number_of_elements_per_command="2" >+ element_types="2 0" >+ information_property="PointArrayInfo"> >+ <ArraySelectionDomain name="array_list"> >+ <RequiredProperties> >+ <Property name="PointArrayInfo" >+ function="ArrayList"/> >+ </RequiredProperties> >+ </ArraySelectionDomain> >+ </StringVectorProperty> >+ >+ <StringVectorProperty >+ name="LagrangianArrayInfo" >+ information_only="1"> >+ <ArraySelectionInformationHelper attribute_name="Lagrangian"/> >+ </StringVectorProperty> >+ <StringVectorProperty >+ name="LagrangianArrays" >+ command="SetLagrangianArrayStatus" >+ number_of_elements="0" >+ repeat_command="1" >+ number_of_elements_per_command="2" >+ element_types="2 0" >+ information_property="LagrangianArrayInfo"> >+ <ArraySelectionDomain name="array_list"> >+ <RequiredProperties> >+ <Property name="LagrangianArrayInfo" >+ function="ArrayList"/> >+ </RequiredProperties> >+ </ArraySelectionDomain> >+ </StringVectorProperty> >+ >+ <IntVectorProperty >+ name="CacheMesh" >+ command="SetCacheMesh" >+ number_of_elements="1" >+ default_values="1" >+ label="Cache mesh"> >+ <BooleanDomain name="bool"/> >+ <Documentation> >+ Cache the OpenFOAM mesh between GUI selection changes. >+ </Documentation> >+ </IntVectorProperty> >+ >+ <IntVectorProperty >+ name="DecomposePolyhedra" >+ command="SetDecomposePolyhedra" >+ number_of_elements="1" >+ default_values="1" >+ label="Decompose polyhedra"> >+ <BooleanDomain name="bool"/> >+ <Documentation> >+ Decompose polyhedra into tetrahedra and pyramids. >+ </Documentation> >+ </IntVectorProperty> >+ >+ <IntVectorProperty name="ListTimeStepsByControlDict" >+ command="SetListTimeStepsByControlDict" >+ number_of_elements="1" >+ default_values="0" >+ label="List timesteps according to controlDict"> >+ <BooleanDomain name="bool"/> >+ <Documentation> >+ Determine if time directories are to be listed according to the description in controlDict. >+ </Documentation> >+ </IntVectorProperty> >+ >+ <IntVectorProperty name="AccumulatePatches" >+ command="SetKeepPatches" >+ number_of_elements="1" >+ default_values="1" >+ label="Accumulate patches to selection list"> >+ <BooleanDomain name="bool"/> >+ <Documentation> >+ Accumulate patches into selection list across time-steps even if they stop existing. >+ </Documentation> >+ </IntVectorProperty> >+ >+ <IntVectorProperty name="PositionsIsIn13Format" >+ command="SetPositionsIsIn13Format" >+ number_of_elements="1" >+ default_values="0" >+ label="Lagrangian positions are in OF 1.3 binary format"> >+ <BooleanDomain name="bool"/> >+ <Documentation> >+ Set if Lagrangian positions files are in OpenFOAM 1.3 binary format. >+ </Documentation> >+ </IntVectorProperty> >+ >+ <IntVectorProperty name="ReadZones" >+ command="SetReadZones" >+ number_of_elements="1" >+ default_values="0" >+ label="Read zones"> >+ <BooleanDomain name="bool"/> >+ <Documentation> >+ Read point/face/cell-Zones? >+ </Documentation> >+ </IntVectorProperty> >+ > </SourceProxy> >- <!-- End of foam Reader --> >+ <!-- End of FOAM Reader --> > > <!-- Beginning of MFIX Reader --> > <SourceProxy name="MFIXReader" class="vtkMFIXReader">
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 233191
: 161581