|
|
</SourceProxy> | </SourceProxy> |
| |
<!-- Beginning of FOAM Reader --> | <!-- Beginning of FOAM Reader --> |
<SourceProxy name="OpenFOAMReader" |
<SourceProxy |
class="vtkOpenFOAMReader"> |
|
<StringVectorProperty name="FileName" |
name="OpenFOAMReader" |
command="SetFileName" |
class="vtkOpenFOAMReader" |
animateable="0" |
output="vtkDataSet"> |
number_of_elements="1"> |
|
<FileListDomain name="files"/> |
<StringVectorProperty |
<Documentation> |
name="FileName" |
Set the file name for the OpenFOAM reader. |
command="SetFileName" |
</Documentation> |
number_of_elements="1"> |
</StringVectorProperty> |
<FileListDomain name="files"/> |
<StringVectorProperty name="CellArrayInfo" |
</StringVectorProperty> |
information_only="1"> |
|
<ArraySelectionInformationHelper attribute_name="Cell"/> |
<IntVectorProperty |
</StringVectorProperty> |
name="CacheMesh" |
<StringVectorProperty name="CellArrayStatus" |
command="SetCacheMesh" |
command="SetCellArrayStatus" |
number_of_elements="1" |
number_of_elements="0" |
default_values="1"> |
repeat_command="1" |
<BooleanDomain name="bool"/> |
number_of_elements_per_command="2" |
<Documentation> |
element_types="2 0" |
Cache the OpenFOAM mesh between GUI selection changes. |
information_property="CellArrayInfo" |
</Documentation> |
label="Cell Arrays"> |
</IntVectorProperty> |
<ArraySelectionDomain name="array_list"> |
|
<RequiredProperties> |
<IntVectorProperty name="ReadZones" |
<Property name="CellArrayInfo" function="ArrayList"/> |
command="SetReadZones" |
</RequiredProperties> |
number_of_elements="1" |
</ArraySelectionDomain> |
default_values="0" |
<Documentation> |
label="Read Zones"> |
Select which cell-centered arrays to read. |
<BooleanDomain name="bool"/> |
</Documentation> |
<Documentation> |
</StringVectorProperty> |
Read point/face/cell-Zones? |
<IntVectorProperty name="TimeStepRangeInfo" |
</Documentation> |
command="GetTimeStepRange" |
</IntVectorProperty> |
information_only="1"> |
|
<SimpleIntInformationHelper/> |
<IntVectorProperty name="AccumulatePatches" |
</IntVectorProperty> |
command="SetKeepPatches" |
<IntVectorProperty name="TimeStep" |
number_of_elements="1" |
command="SetTimeStep" |
default_values="1" |
number_of_elements="1" |
label="Accumulate Patches to Selection List"> |
animateable="1" |
<BooleanDomain name="bool"/> |
default_values="0"> |
<Documentation> |
<IntRangeDomain name="range"> |
Accumulate patches into selection list across time-steps even if they stop existing |
<RequiredProperties> |
</Documentation> |
<Property name="TimeStepRangeInfo" function="Range"/> |
</IntVectorProperty> |
</RequiredProperties> |
|
</IntRangeDomain> |
<DoubleVectorProperty |
<Documentation> |
name="TimestepValues" |
Set the current timestep. |
repeatable="1" |
</Documentation> |
information_only="1"> |
</IntVectorProperty> |
<TimeStepsInformationHelper/> |
<DoubleVectorProperty |
</DoubleVectorProperty> |
name="TimestepValues" |
|
repeatable="1" |
<StringVectorProperty |
information_only="1"> |
name="PatchArrayInfo" |
<TimeStepsInformationHelper/> |
information_only="1"> |
</DoubleVectorProperty> |
<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> |
|
|
</SourceProxy> | </SourceProxy> |
<!-- End of foam Reader --> | <!-- End of foam Reader --> |
| |
|
|
// Technology Laboratory who developed this class. | // 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) |
// | // |
|
// 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) |
|
|
#include "vtkOpenFOAMReader.h" | #include "vtkOpenFOAMReader.h" |
| |
|
#include <vtksys/ios/sstream> |
#include <vtkstd/string> | #include <vtkstd/string> |
#include <vtkstd/vector> | #include <vtkstd/vector> |
#include <vtksys/ios/sstream> |
#include <vtk_zlib.h> |
| |
#include "vtkInformation.h" | #include "vtkInformation.h" |
#include "vtkInformationVector.h" | #include "vtkInformationVector.h" |
|
|
#include "vtkDataArraySelection.h" | #include "vtkDataArraySelection.h" |
#include "vtkStreamingDemandDrivenPipeline.h" | #include "vtkStreamingDemandDrivenPipeline.h" |
#include "vtkCellArray.h" | #include "vtkCellArray.h" |
|
#include "vtkCallbackCommand.h" |
#include "vtkDataArraySelection.h" | #include "vtkDataArraySelection.h" |
#include "vtkIntArray.h" | #include "vtkIntArray.h" |
#include "vtkFloatArray.h" |
|
#include "vtkDoubleArray.h" | #include "vtkDoubleArray.h" |
|
#include "vtkStringArray.h" |
|
#include "vtkSortDataArray.h" |
#include "vtkPoints.h" | #include "vtkPoints.h" |
#include "vtkCellData.h" | #include "vtkCellData.h" |
#include "vtkHexahedron.h" | #include "vtkHexahedron.h" |
|
|
#include "vtkUnstructuredGridAlgorithm.h" | #include "vtkUnstructuredGridAlgorithm.h" |
#include "vtkObjectFactory.h" | #include "vtkObjectFactory.h" |
#include "vtkDirectory.h" | #include "vtkDirectory.h" |
|
#include "vtkPolyData.h" |
|
#include "vtkPointData.h" |
|
#include "vtkPVConfig.h" // for PARAVIEW_VERSION_MAJOR |
| |
#include <ctype.h> | #include <ctype.h> |
#include <sys/stat.h> | #include <sys/stat.h> |
| |
|
#if 0 |
#ifdef VTK_USE_ANSI_STDLIB | #ifdef VTK_USE_ANSI_STDLIB |
#define VTK_IOS_NOCREATE | #define VTK_IOS_NOCREATE |
#else | #else |
#define VTK_IOS_NOCREATE | ios::nocreate | #define VTK_IOS_NOCREATE | ios::nocreate |
#endif | #endif |
|
#endif |
|
|
|
// The input buffer size in bytes. The purpose of the buffering is to |
|
// reduce the number of costly gzread() calls so the buffer size |
|
// doesn't have to be large. |
|
#define VTK_FOAMFILE_BUFSIZE (2048) |
|
|
|
// If the macro is set to 1 fast (but inaccurate) string to floating |
|
// point number conversion routine is used instead of the system |
|
// strtod(). This affects about 15% in performance for ascii cases. |
|
#define VTK_FOAMFILE_FAST_STRTOD 1 |
| |
vtkCxxRevisionMacro(vtkOpenFOAMReader, "$Revision: 1.10 $"); |
vtkCxxRevisionMacro(vtkOpenFOAMReader, "$Revision: 1.7.2.2 $"); |
vtkStandardNewMacro(vtkOpenFOAMReader); | vtkStandardNewMacro(vtkOpenFOAMReader); |
| |
struct stdString |
struct stringVector |
{ | { |
vtkstd::string value; |
vtkstd::vector< vtkStdString > value; |
}; | }; |
| |
struct stringVector |
struct intVector |
|
{ |
|
vtkstd::vector< int > value; |
|
}; |
|
|
|
struct doubleVector |
|
{ |
|
vtkstd::vector<double> value; |
|
}; |
|
|
|
struct intVectorVector |
|
{ |
|
vtkstd::vector< vtkstd::vector< int > > value; |
|
}; |
|
|
|
struct faceVectorVector |
|
{ |
|
vtkstd::vector< vtkstd::vector< face > > value; |
|
}; |
|
|
|
struct unstructuredGridVector |
|
{ |
|
vtkstd::vector<vtkUnstructuredGrid*> value; |
|
}; |
|
|
|
struct vtkOpenFOAMReader::vtkFoamError |
|
{ |
|
private: |
|
vtkStdString str_; |
|
public: |
|
vtkFoamError(): str_() {} |
|
vtkFoamError(vtkFoamError& e): str_(e.str()) {} |
|
const vtkStdString str() const { return str_; } |
|
// a super-easy way to make use of operator<<()'s defined in |
|
// vtkstd::ostringstream class |
|
template <class T> vtkFoamError& operator<<(const T& t) |
|
{ vtkstd::ostringstream os; os << t; str_ += os.str(); return *this; } |
|
}; |
|
|
|
// token class |
|
// based on src/OpenFOAM/db/IOstreams/token/{token|tokenI}.H |
|
// a word token is treated as a string token. |
|
struct vtkOpenFOAMReader::vtkFoamToken |
{ | { |
vtkstd::vector< vtkstd::string > value; |
public: |
|
enum tokenType { UNDEFINED, PUNCTUATION, STRING, LABEL, SCALAR, ERROR }; |
|
private: |
|
tokenType type_; |
|
|
|
vtkFoamToken(const vtkFoamToken&); |
|
void clear() { if(type_ == STRING) delete stringTokenPtr_; } |
|
|
|
public: |
|
union |
|
{ |
|
char punctuationToken_; vtkStdString* stringTokenPtr_; int labelToken_; |
|
double scalarToken_; |
|
}; |
|
|
|
vtkFoamToken(): type_(UNDEFINED) {} |
|
~vtkFoamToken() { clear(); } |
|
void setBad() { clear(); type_ = ERROR; } |
|
tokenType type() const { return type_; } |
|
bool isNumber() const { return type_ == LABEL || type_ == SCALAR; } |
|
|
|
char punctuationToken() const { return punctuationToken_; } |
|
int labelToken() const { return labelToken_; } |
|
double number() const |
|
{ if(type_ == LABEL) return labelToken_; else return scalarToken_; } |
|
const vtkStdString& stringToken() const |
|
{ return *stringTokenPtr_; } |
|
|
|
void operator=(const char c) |
|
{ clear(); type_ = PUNCTUATION; punctuationToken_ = c; } |
|
void operator=(const char *s) |
|
{ clear(); type_ = STRING; stringTokenPtr_ = new vtkStdString(s); } |
|
void operator=(const vtkStdString& s) |
|
{ clear(); type_ = STRING; stringTokenPtr_ = new vtkStdString(s); } |
|
void operator=(const int l) |
|
{ clear(); type_ = LABEL; labelToken_ = l; } |
|
void operator=(const double d) |
|
{ clear(); type_ = SCALAR; scalarToken_ = d; } |
|
bool operator==(const char c) const |
|
{ return type_ == PUNCTUATION && punctuationToken_ == c; } |
|
bool operator==(const int i) const |
|
{ return type_ == LABEL && labelToken_ == i; } |
|
bool operator==(const vtkStdString& str) const |
|
{ return type_ == STRING && *stringTokenPtr_ == str; } |
|
bool operator!=(const vtkStdString& str) const |
|
{ return type_ != STRING || *stringTokenPtr_ != str; } |
|
bool operator!=(const char c) const { return !operator==(c); } |
|
|
|
friend vtkstd::ostringstream& operator<<(vtkstd::ostringstream& str, |
|
const vtkFoamToken& t) |
|
{ |
|
if(t.type() == PUNCTUATION) |
|
{ |
|
str << t.punctuationToken_; |
|
} |
|
else if(t.type() == STRING) |
|
{ |
|
str << *t.stringTokenPtr_; |
|
} |
|
else if(t.type() == LABEL) |
|
{ |
|
str << t.labelToken_; |
|
} |
|
else if(t.type() == SCALAR) |
|
{ |
|
str << t.scalarToken_; |
|
} |
|
else if(t.type() == ERROR) |
|
{ |
|
str << "badToken (an unexpected EOF?)"; |
|
} |
|
return str; |
|
} |
}; | }; |
| |
struct intVector |
// read and tokenize the input |
|
// line number counting is based on |
|
// src/OpenFOAM/db/IOstreams/Sstreams/ISstreamI.H |
|
struct vtkOpenFOAMReader::vtkFoamFile |
|
{ |
|
private: |
|
gzFile file_; |
|
bool putBack_; |
|
int putBackC_; |
|
int lineNumber_; |
|
|
|
// buffer pointers. using raw pointers for performance reason. |
|
unsigned char *buf_; |
|
unsigned char *bufPtr_; |
|
unsigned char *bufEndPtr_; |
|
|
|
// declare and define as private |
|
void putBack(const int c) |
|
{ |
|
if(putBack_) |
|
{ |
|
throw vtkFoamError() << "Attempted duplicated putBack()"; |
|
} |
|
else |
|
{ |
|
if(c == '\n') |
|
{ |
|
lineNumber_--; |
|
} |
|
*--bufPtr_ = c; |
|
putBack_ = true; |
|
} |
|
} |
|
|
|
// get a character |
|
int getc() |
|
{ |
|
putBack_ = false; |
|
if(bufPtr_ == bufEndPtr_) |
|
{ |
|
bufPtr_ = buf_ + 1; // reserve the first byte for getback char |
|
const int readSize = gzread(file_, bufPtr_, VTK_FOAMFILE_BUFSIZE - 1); |
|
if(readSize <= 0) // 0 byte read or EOF |
|
{ |
|
// set the current location to the end of the buffer so that |
|
// getc() returns EOF again when called next time |
|
bufPtr_ = bufEndPtr_; |
|
return EOF; |
|
} |
|
bufEndPtr_ = bufPtr_ + readSize; |
|
} |
|
const int c = *bufPtr_++; |
|
if(c == '\n') |
|
{ |
|
lineNumber_++; |
|
} |
|
return c; |
|
} |
|
|
|
// get next semantically valid character |
|
// based on src/OpenFOAM/db/IOstreams/Sstream/ISnextValid.C |
|
int nextValid() |
|
{ |
|
int c; |
|
for(;;) |
|
{ |
|
if((c = getc()) != EOF && isspace(c)) |
|
{ |
|
while((c = getc()) != EOF && isspace(c)); |
|
} |
|
if(c == '/') |
|
{ |
|
if((c = getc()) == EOF) |
|
{ |
|
return '/'; |
|
} |
|
if(c == '/') // one-line comment |
|
{ |
|
while(EOF != (c = getc()) && c != '\n' && c != '\r'); |
|
} |
|
else if(c == '*') // multi-line comment |
|
{ |
|
for(;;) |
|
{ |
|
if((c = getc()) == '*') |
|
{ |
|
if((c = getc()) == '/') |
|
{ |
|
break; |
|
} |
|
else if(c == EOF) |
|
{ |
|
return EOF; |
|
} |
|
else |
|
{ |
|
putBack(c); |
|
} |
|
} |
|
else if(c == EOF) |
|
{ |
|
return EOF; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
putBack(c); |
|
return '/'; |
|
} |
|
} |
|
else // a valid character or an EOF |
|
{ |
|
return c; |
|
} |
|
} |
|
} |
|
|
|
// valid as a character that constitutes a word or not |
|
// based on src/OpenFOAM/primitives/strings/word/wordI.H |
|
bool valid(const int c) const |
|
{ |
|
return (!isspace(c) && c != '"' && c != '/' && c != ';' && c != '{' |
|
&& c != '}'); |
|
} |
|
|
|
public: |
|
vtkFoamFile(): file_(NULL), putBack_(false), putBackC_(0), lineNumber_(0), |
|
buf_(NULL) {} |
|
~vtkFoamFile() { close(); } |
|
|
|
void open(const vtkStdString& path) |
|
{ |
|
lineNumber_ = 0; |
|
|
|
buf_ = new unsigned char[VTK_FOAMFILE_BUFSIZE]; |
|
bufPtr_ = buf_; |
|
bufEndPtr_ = buf_; |
|
|
|
if(file_ != NULL) |
|
{ |
|
throw vtkFoamError() << "File already opened"; |
|
} |
|
if((file_ = gzopen(path.c_str(), "rb")) == NULL) |
|
{ |
|
throw vtkFoamError() << "Can't open"; |
|
} |
|
|
|
lineNumber_ = 1; |
|
} |
|
|
|
void close() |
|
{ |
|
if(buf_ != NULL) |
|
{ |
|
delete [] buf_; |
|
buf_ = NULL; |
|
} |
|
putBack_ = false; |
|
putBackC_ = 0; |
|
if(file_ != NULL) |
|
{ |
|
gzclose(file_); |
|
file_ = NULL; |
|
} |
|
// don't reset the line number so that the last line number is |
|
// retained after close |
|
// lineNumber_ = 0; |
|
} |
|
|
|
int lineNumber() const { return lineNumber_; } |
|
|
|
// gzread with buffering handling |
|
int read(char *buf, const int len) |
|
{ |
|
int readlen; |
|
const int buflen = bufEndPtr_ - bufPtr_; |
|
if(len > buflen) |
|
{ |
|
memcpy(buf, bufPtr_, buflen); |
|
readlen = gzread(file_, 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; |
|
} |
|
|
|
// the tokenizer |
|
// based on src/OpenFOAM/db/IOstreams/Sstreams/{ISreadToken|ISread}.C |
|
// returns true if success, false if encountered EOF |
|
bool read(vtkFoamToken& token) |
|
{ |
|
int c = nextValid(); |
|
if(c == EOF) |
|
{ |
|
token.setBad(); |
|
return false; |
|
} |
|
switch(c) |
|
{ |
|
case ';': case '(': case ')': case '{': case '}': case '[': case ']': |
|
case ':': case ',': case '=': case '+': case '*': case '/': |
|
// punctuation token |
|
token = (char)c; |
|
return true; |
|
case '-': case '.': case '0': case '1': case '2': case '3': case '4': |
|
case '5': case '6': case '7': case '8': case '9': |
|
// number token |
|
{ |
|
const int MAX_NUM = 100; |
|
static char numberBuffer[MAX_NUM]; |
|
bool isScalar = false; |
|
if(c == '.') |
|
{ |
|
isScalar = true; |
|
} |
|
int i = 0, isDigit; |
|
numberBuffer[i++] = c; |
|
while(EOF != (c = getc()) && i < MAX_NUM && ((isDigit = isdigit(c)) |
|
|| c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-')) |
|
{ |
|
numberBuffer[i++] = c; |
|
if(!isDigit) |
|
{ |
|
isScalar = true; |
|
} |
|
} |
|
if(i == MAX_NUM) |
|
{ |
|
if(c != EOF) |
|
{ |
|
putBack(c); |
|
} |
|
numberBuffer[MAX_NUM - 1] = '\0'; |
|
token.setBad(); |
|
throw vtkFoamError() << "Reached the maximum allowed number length"; |
|
} |
|
numberBuffer[i] = '\0'; |
|
if(c != EOF) |
|
{ |
|
putBack(c); |
|
if(i == 1 && numberBuffer[0] == '-') |
|
{ |
|
token = '-'; |
|
} |
|
else if(isScalar) |
|
{ |
|
token = strtod(numberBuffer, NULL); |
|
} |
|
else |
|
{ |
|
token = static_cast<int>(strtol(numberBuffer, NULL, 10)); |
|
} |
|
return true; |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Encountered EOF while tokenizing a number"; |
|
} |
|
} |
|
case '"': |
|
// string token |
|
{ |
|
const int MAX_STR = 1024; |
|
static char stringBuffer[MAX_STR]; |
|
int i = 0; |
|
bool escape = false; |
|
while((c = getc()) != EOF) |
|
{ |
|
if(c == '"' && !escape) |
|
{ |
|
stringBuffer[i] = '\0'; |
|
token = stringBuffer; |
|
return true; |
|
} |
|
if((c == '\n' || c == '\r') && !escape) |
|
{ |
|
stringBuffer[i] = '\0'; |
|
token = stringBuffer; |
|
throw vtkFoamError() << "Found a newline while reading string \"" |
|
<< stringBuffer << "\""; |
|
} |
|
if(c == '\\') |
|
{ |
|
escape = true; |
|
} |
|
else |
|
{ |
|
escape = false; |
|
stringBuffer[i] = c; |
|
if(++i == MAX_STR) |
|
{ |
|
stringBuffer[MAX_STR - 1] = '\0'; |
|
token = stringBuffer; |
|
throw vtkFoamError() |
|
<< "Reached the maximum allowed string length"; |
|
} |
|
} |
|
} |
|
stringBuffer[i] = '\0'; |
|
token = stringBuffer; |
|
throw vtkFoamError() << "Encountered EOF while reading string"; |
|
} |
|
default: |
|
// parses as a word token, but gives the STRING type for simplicity |
|
{ |
|
putBack(c); |
|
const int MAX_WORD = 1024; |
|
static char wordBuffer[MAX_WORD]; |
|
int i = 0; |
|
int bc = 0; |
|
while((EOF != (c = getc())) && valid(c)) |
|
{ |
|
if(i >= MAX_WORD) |
|
{ |
|
wordBuffer[MAX_WORD - 1] = '\0'; |
|
token = wordBuffer; |
|
throw vtkFoamError() << "Reached the maximum allowed word length."; |
|
} |
|
if(c == '(') |
|
{ |
|
bc++; |
|
} |
|
else if(c == ')') |
|
{ |
|
bc--; |
|
if(bc == -1) |
|
{ |
|
break; |
|
} |
|
} |
|
wordBuffer[i++] = c; |
|
} |
|
if(i == 0) |
|
{ |
|
token.setBad(); |
|
throw vtkFoamError() << "Invalid first character as a token"; |
|
} |
|
wordBuffer[i] = '\0'; |
|
token = wordBuffer; |
|
if(c != EOF) |
|
{ |
|
putBack(c); |
|
} |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
void readExpecting(const char c) |
|
{ |
|
vtkFoamToken t; |
|
if(!read(t)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
if(t != c) |
|
{ |
|
throw vtkFoamError() << "Expected punctuation token " << c << ", found " |
|
<< t; |
|
} |
|
} |
|
|
|
void readExpecting(const char* str) |
|
{ |
|
vtkFoamToken t; |
|
if(!read(t)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
if(t != str) |
|
{ |
|
throw vtkFoamError() << "Expected string \"" << str << "\", found " << t; |
|
} |
|
} |
|
|
|
// specialized for reading an integer value. |
|
// not using the standard strtol() for speed reason. |
|
int readLabel() |
|
{ |
|
int c = nextValid(); |
|
|
|
bool negative = false; |
|
if(c == '-') |
|
{ |
|
negative = true; |
|
c = getc(); |
|
} |
|
|
|
if(!isdigit(c)) |
|
{ |
|
throw vtkFoamError() |
|
<< "Expected an integer, found a non-digit character" << (char)c; |
|
} |
|
|
|
int num = c - '0'; |
|
while(EOF != (c = getc()) && isdigit(c)) |
|
{ |
|
num = 10 * num + c - '0'; |
|
} |
|
|
|
if(c == EOF) |
|
{ |
|
throw vtkFoamError() << "Encountered EOF while reading integer"; |
|
} |
|
putBack(c); |
|
|
|
return negative ? -num : num; |
|
} |
|
|
|
#if VTK_FOAMFILE_FAST_STRTOD |
|
// extreamely simplified high-performing string to floating point |
|
// conversion code based on |
|
// ParaView3/VTK/Utilities/vtksqlite/vtk_sqlite3.c |
|
double readNumber() |
|
{ |
|
int c = nextValid(); |
|
|
|
// determine sign |
|
bool negative = false; |
|
if(c == '-') |
|
{ |
|
negative = true; |
|
c = getc(); |
|
} |
|
|
|
if(c == EOF || (!isdigit(c) && c != '.' && c != 'e' && c != 'E')) |
|
{ |
|
throw vtkFoamError() |
|
<< "Expected a number, found a non-digit character" << (char)c; |
|
} |
|
|
|
// read integer part |
|
long double num = 0.0; |
|
while(c != EOF && isdigit(c)) |
|
{ |
|
num = num * 10.0 + (c - '0'); |
|
c = getc(); |
|
} |
|
|
|
// read decimal part |
|
if(c == '.') |
|
{ |
|
long double divisor = 1.0; |
|
|
|
c = getc(); |
|
while(c != EOF && isdigit(c)) |
|
{ |
|
num = num * 10.0 + (c - '0'); |
|
divisor *= 10.0; |
|
c = getc(); |
|
} |
|
num /= divisor; |
|
} |
|
|
|
// read exponent part |
|
if(c == 'e' || c == 'E') |
|
{ |
|
int esign = 1; |
|
int eval = 0; |
|
long double scale = 1.0; |
|
|
|
c = getc(); |
|
if(c == '-') |
|
{ |
|
esign = -1; |
|
c = getc(); |
|
} |
|
else if(c == '+') |
|
{ |
|
c = getc(); |
|
} |
|
|
|
while(c != EOF && isdigit(c)) |
|
{ |
|
eval = eval * 10 + c - '0'; |
|
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) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
putBack(c); |
|
|
|
return static_cast<double>(negative ? -num : num); |
|
} |
|
#else |
|
// specialized for reading a scalar value |
|
double readNumber() |
|
{ |
|
int c = nextValid(); |
|
if(c == EOF || (!isdigit(c) && c != '-' && c != '.')) |
|
{ |
|
if(c == EOF) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected a number, found " << (char)c; |
|
} |
|
} |
|
|
|
const int MAX_NUM = 100; |
|
static char numberBuffer[MAX_NUM]; |
|
int i = 0; |
|
numberBuffer[i++] = c; |
|
if(EOF != (c = getc()) && i < MAX_NUM && (isdigit(c) |
|
|| c == '.' || c == 'e' || c == 'E')) // signs do not come as a 2nd char |
|
{ |
|
numberBuffer[i++] = c; |
|
while(EOF != (c = getc()) && i < MAX_NUM && (isdigit(c) |
|
|| c == '.' || c == 'e' || c == 'E' || c == '+' || c == '-')) |
|
{ |
|
numberBuffer[i++] = c; |
|
} |
|
} |
|
if(i == MAX_NUM) |
|
{ |
|
throw vtkFoamError() << "Reached the maximum allowed number length"; |
|
} |
|
numberBuffer[i] = '\0'; |
|
if(c == EOF) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
else |
|
{ |
|
putBack(c); |
|
if(i == 1 && numberBuffer[0] == '-') |
|
{ |
|
throw vtkFoamError() << "Expected a number, found a minus sign"; |
|
} |
|
} |
|
return strtod(numberBuffer, NULL); |
|
} |
|
#endif |
|
}; |
|
|
|
// IOobject class |
|
// 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: |
|
vtkStdString fileName_; |
|
fileFormat format_; |
|
vtkStdString objectName_; |
|
vtkStdString headerClassName_; |
|
vtkFoamError* e_; |
|
|
|
void readHeader(); // defined later |
|
public: |
|
vtkFoamIOobject(): vtkFoamFile(), format_(UNDEFINED), e_(NULL) {} |
|
~vtkFoamIOobject() { close(); } |
|
|
|
bool open(const vtkStdString& file) |
|
{ |
|
fileName_ = file; |
|
try |
|
{ |
|
vtkFoamFile::open(file); |
|
} |
|
catch(vtkFoamError& e) |
|
{ |
|
e_ = new vtkFoamError(e); |
|
return false; |
|
} |
|
|
|
try |
|
{ |
|
readHeader(); |
|
} |
|
catch(vtkFoamError& e) |
|
{ |
|
vtkFoamFile::close(); |
|
e_ = new vtkFoamError(e); |
|
return false; |
|
} |
|
e_ = NULL; |
|
return true; |
|
} |
|
|
|
void close() |
|
{ |
|
vtkFoamFile::close(); |
|
format_ = UNDEFINED; |
|
objectName_.erase(); |
|
headerClassName_.erase(); |
|
if(e_ != NULL) |
|
{ |
|
delete e_; |
|
} |
|
} |
|
const vtkStdString& fileName() { return fileName_; } |
|
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(vtkFoamError& e) |
|
{ if(e_ != NULL) delete e_; e_ = new vtkFoamError(e); } |
|
}; |
|
|
|
// 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: |
|
enum entryValueType |
|
{ |
|
UNDEFINED, PUNCTUATION, STRING, LABEL, SCALAR, STRINGLIST, LABELLIST, |
|
LABELLISTLIST, SCALARLIST, VECTORLIST, ENTRYVALUELIST, EMPTYLIST, |
|
DICTIONARY, ERROR |
|
}; |
|
|
|
private: |
|
entryValueType type_; |
|
bool isUniform_; |
|
bool managed_; |
|
|
|
// don't pack them into a union |
|
vtkFoamToken t_; |
|
vtkstd::vector<vtkFoamEntryValue*> entryValuePtrs_; |
|
|
|
union |
|
{ |
|
intVector *labelListPtr_; vtkDoubleArray *scalarListPtr_, *vectorListPtr_; |
|
stringVector *stringListPtr_; intVectorVector *labelListListPtr_; |
|
vtkFoamDict *dictPtr_; |
|
}; |
|
|
|
void clear(); |
|
void readList(vtkFoamIOobject& io); |
|
|
|
public: |
|
vtkFoamEntryValue(): type_(UNDEFINED), isUniform_(false), managed_(true), |
|
labelListPtr_(NULL) {} |
|
~vtkFoamEntryValue() { clear(); } |
|
|
|
entryValueType type() const { return type_; } |
|
void setEmptyList() { clear(); isUniform_ = false; type_ = EMPTYLIST; } |
|
bool isUniform() const { return isUniform_; } |
|
void read(vtkFoamIOobject& io); |
|
void readDictionary(vtkFoamIOobject& io, |
|
const vtkStdString& firstKeyword = ""); |
|
const vtkFoamToken& token() const { return t_; } |
|
vtkFoamToken& token() { return t_; } |
|
const vtkstd::vector<int>& labelList() const |
|
{ return labelListPtr_->value; } |
|
const vtkstd::vector<vtkstd::vector<int> >& labelListList() const |
|
{ return labelListListPtr_->value; } |
|
vtkDoubleArray& scalarList() |
|
{ return *scalarListPtr_; } |
|
vtkDoubleArray& vectorList() |
|
{ return *vectorListPtr_; } |
|
vtkFoamDict& dictionary() |
|
{ return *dictPtr_; } |
|
bool operator==(const char c) const |
|
{ return type_ == PUNCTUATION && t_ == c; } |
|
bool operator!=(const char c) const |
|
{ return type_ != PUNCTUATION || t_ != c; } |
|
bool operator==(const int i) const |
|
{ return type_ == LABEL && t_ == i; } |
|
|
|
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 |
|
} |
|
|
|
// 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_ = new intVector; |
|
type_ = LABELLIST; |
|
vtkstd::vector<int>& ll = labelListPtr_->value; |
|
ll.resize(size); |
|
for(int i = 0; i < size; i++) |
|
{ |
|
ll[i] = labelValue; |
|
} |
|
} |
|
void makeScalarList(const double scalarValue, const int size) |
|
{ |
|
scalarListPtr_ = vtkDoubleArray::New(); |
|
type_ = SCALARLIST; |
|
vtkDoubleArray& sl = *scalarListPtr_; |
|
sl.SetNumberOfValues(size); |
|
for(vtkIdType i = 0; i < size; i++) |
|
{ |
|
sl.SetValue(i, scalarValue); |
|
} |
|
} |
|
|
|
// read a labelList |
|
void readLabelList(vtkFoamIOobject& io) |
|
{ |
|
vtkFoamToken currToken; |
|
if(!io.read(currToken)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
labelListPtr_ = new intVector; |
|
type_ = LABELLIST; |
|
if(currToken.type() == vtkFoamToken::LABEL) |
|
{ |
|
const int size = currToken.labelToken(); |
|
labelListPtr_->value.resize(size); |
|
if(!io.read(currToken)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
vtkstd::vector<int>& ll = labelListPtr_->value; |
|
// some objects have lists with only one element enclosed by {} |
|
// e. g. simpleFoam/pitzDaily3Blocks/constant/polyMesh/faceZones |
|
if(currToken == '{') |
|
{ |
|
int labelValue = io.readLabel(); |
|
for(int i = 0; i < size; i++) |
|
{ |
|
ll[i] = labelValue; |
|
} |
|
io.readExpecting('}'); |
|
return; |
|
} |
|
if(currToken != '(') |
|
{ |
|
throw vtkFoamError() << "Expected (, found " << currToken; |
|
} |
|
if(io.format() == vtkFoamIOobject::ASCII) |
|
{ |
|
for(int i = 0; i < size; i++) |
|
{ |
|
ll[i] = io.readLabel(); |
|
} |
|
} |
|
else |
|
{ |
|
if(size > 0) // avoid invalid access to ll.at(0) |
|
{ |
|
io.read(reinterpret_cast<char*>(&ll.at(0)), size * sizeof(int)); |
|
} |
|
} |
|
io.readExpecting(')'); |
|
} |
|
else if(currToken == '(') |
|
{ |
|
while(io.read(currToken) && currToken != ')') |
|
{ |
|
if(currToken.type() != vtkFoamToken::LABEL) |
|
{ |
|
throw vtkFoamError() << "Expected an integer or a (, found " |
|
<< currToken; |
|
} |
|
labelListPtr_->value.push_back(currToken.labelToken()); |
|
} |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected integer or (, found " << currToken; |
|
} |
|
} |
|
|
|
// reads a list of labelLists. requires size prefix of the listList |
|
// to be present. size of the list must 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) |
|
{ |
|
labelListListPtr_ = new intVectorVector; |
|
type_ = LABELLISTLIST; |
|
|
|
const int sizeI = currToken.labelToken(); |
|
labelListListPtr_->value.resize(sizeI); |
|
io.readExpecting('('); |
|
for(int i = 0; i < sizeI; i++) |
|
{ |
|
if(!io.read(currToken)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
if(currToken.type() == vtkFoamToken::LABEL) |
|
{ |
|
const int sizeJ = currToken.labelToken(); |
|
labelListListPtr_->value[i].resize(sizeJ); |
|
io.readExpecting('('); |
|
vtkstd::vector<int>& labelListI = labelListListPtr_->value[i]; |
|
if(io.format() == vtkFoamIOobject::ASCII) |
|
{ |
|
for(int j = 0; j < sizeJ; j++) |
|
{ |
|
labelListI[j] = io.readLabel(); |
|
} |
|
} |
|
else |
|
{ |
|
if(sizeJ > 0) // avoid invalid reference to labelListI.at(0) |
|
{ |
|
io.read(reinterpret_cast<char*>(&labelListI.at(0)), |
|
sizeJ * sizeof(int)); |
|
} |
|
} |
|
io.readExpecting(')'); |
|
} |
|
else if(currToken == '(') |
|
{ |
|
while(io.read(currToken) && currToken != ')') |
|
{ |
|
if(currToken.type() != vtkFoamToken::LABEL) |
|
{ |
|
throw vtkFoamError() << "Expected an integer, found " |
|
<< currToken; |
|
} |
|
labelListListPtr_->value[i].push_back(currToken.labelToken()); |
|
} |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected integer or (, found " << currToken; |
|
} |
|
} |
|
io.readExpecting(')'); |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected integer, found " << currToken; |
|
} |
|
} |
|
|
|
// reads a scalarList. requires size prefix of the list to be |
|
// present in the stream if the format is binary. |
|
void readScalarList(vtkFoamIOobject& io) |
|
{ |
|
vtkFoamToken currToken; |
|
if(!io.read(currToken)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
scalarListPtr_ = vtkDoubleArray::New(); |
|
type_ = SCALARLIST; |
|
if(currToken.type() == vtkFoamToken::LABEL) |
|
{ |
|
const vtkIdType size = currToken.labelToken(); |
|
scalarListPtr_->SetNumberOfValues(size); |
|
if(!io.read(currToken)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
vtkDoubleArray& sl = *scalarListPtr_; |
|
// some objects have lists with only one element enclosed by {} |
|
// to represent a field with an uniform value |
|
if(currToken == '{') |
|
{ |
|
double scalarValue = io.readNumber(); |
|
for(vtkIdType i = 0; i < size; i++) |
|
{ |
|
sl.SetValue(i, scalarValue); |
|
} |
|
io.readExpecting('}'); |
|
return; |
|
} |
|
if(currToken != '(') |
|
{ |
|
throw vtkFoamError() << "Expected (, found " << currToken; |
|
} |
|
if(io.format() == vtkFoamIOobject::ASCII) |
|
{ |
|
for(vtkIdType i = 0; i < size; i++) |
|
{ |
|
sl.SetValue(i, io.readNumber()); |
|
} |
|
} |
|
else |
|
{ |
|
if(size > 0) // avoid invalid access to GetPointer(0) |
|
{ |
|
io.read(reinterpret_cast<char*>(sl.GetPointer(0)), |
|
size * sizeof(double)); |
|
} |
|
} |
|
io.readExpecting(')'); |
|
} |
|
else if(currToken == '(') |
|
{ |
|
while(io.read(currToken) && currToken != ')') |
|
{ |
|
if(!io.read(currToken) || !currToken.isNumber()) |
|
{ |
|
throw vtkFoamError() << "Expected an integer or a (, found " |
|
<< currToken; |
|
} |
|
scalarListPtr_->InsertNextValue(currToken.number()); |
|
} |
|
scalarListPtr_->Squeeze(); |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected integer or (, found " << currToken; |
|
} |
|
} |
|
|
|
// reads a vectorList. requires size prefix of the list to be |
|
// present in the stream if the format is binary. |
|
// if isPositions is true read Cloud type of data as particle positions |
|
// based on src/lagrangian/basic/particle/particleIO.C |
|
void readVectorList(vtkFoamIOobject& io, const bool isPositions) |
|
{ |
|
vtkFoamToken currToken; |
|
if(!io.read(currToken)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
vectorListPtr_ = vtkDoubleArray::New(); |
|
vectorListPtr_->SetNumberOfComponents(3); |
|
type_ = VECTORLIST; |
|
if(currToken.type() == vtkFoamToken::LABEL) |
|
{ |
|
const int size = currToken.labelToken(); |
|
vectorListPtr_->SetNumberOfTuples(size); |
|
if(!io.read(currToken)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
// some objects may have a vector list with one element enclosed by {} |
|
if(currToken == '{') |
|
{ |
|
io.readExpecting('('); |
|
double vectorValue[3]; |
|
vectorValue[0] = io.readNumber(); |
|
vectorValue[1] = io.readNumber(); |
|
vectorValue[2] = io.readNumber(); |
|
for(int i = 0; i < size; i++) |
|
{ |
|
vectorListPtr_->SetTuple(i, vectorValue); |
|
} |
|
io.readExpecting(')'); |
|
if(isPositions) |
|
{ |
|
// skip label celli |
|
io.readLabel(); |
|
} |
|
io.readExpecting('}'); |
|
return; |
|
} |
|
|
|
if(currToken != '(') |
|
{ |
|
throw vtkFoamError() << "Expected (, found " << currToken; |
|
} |
|
if(io.format() == vtkFoamIOobject::ASCII) |
|
{ |
|
if(size > 0) // avoid invalid access to GetPointer(0) |
|
{ |
|
double* vectorComponentI = vectorListPtr_->GetPointer(0); |
|
for(int i = 0; i < size; i++) |
|
{ |
|
io.readExpecting('('); |
|
*vectorComponentI++ = io.readNumber(); |
|
*vectorComponentI++ = io.readNumber(); |
|
*vectorComponentI++ = io.readNumber(); |
|
io.readExpecting(')'); |
|
if(isPositions) |
|
{ |
|
// skip label celli |
|
io.readLabel(); |
|
} |
|
} |
|
} |
|
} |
|
else // binary |
|
{ |
|
if(isPositions) // lagrangian/positions (class Cloud) |
|
{ |
|
if(size > 0) // avoid invalid access to GetPointer() |
|
{ |
|
for(int i = 0, index = 0; i < size; i++, index += 3) |
|
{ |
|
io.readExpecting('('); |
|
io.read(reinterpret_cast<char*>(vectorListPtr_ |
|
->GetPointer(index)), sizeof(double) * 3); |
|
|
|
// skip label celli, label facei and scalar stepFraction |
|
const int dummySize = 2 * sizeof(int) + sizeof(double); |
|
char dummyBuf[dummySize]; |
|
io.read(dummyBuf, dummySize); |
|
io.readExpecting(')'); |
|
} |
|
} |
|
} |
|
else // regular vectorField |
|
{ |
|
if(size > 0) // avoid invalid access to GetPointer() |
|
{ |
|
io.read(reinterpret_cast<char*>(vectorListPtr_->GetPointer(0)), |
|
size * sizeof(double) * 3); |
|
} |
|
} |
|
} |
|
io.readExpecting(')'); |
|
} |
|
else if(currToken == '(') |
|
{ |
|
while(io.read(currToken) && currToken != ')') |
|
{ |
|
if(currToken != '(') |
|
{ |
|
throw vtkFoamError() << "Expected (, found " << currToken; |
|
} |
|
double v[3]; |
|
v[0] = io.readNumber(); |
|
v[1] = io.readNumber(); |
|
v[2] = io.readNumber(); |
|
vectorListPtr_->InsertNextTuple(v); |
|
io.readExpecting(')'); |
|
} |
|
vectorListPtr_->Squeeze(); |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected integer or (, found " << currToken; |
|
} |
|
} |
|
|
|
const vtkFoamEntryValue& operator>>(vtkStdString& str) const |
|
{ |
|
if(type_ == STRING) |
|
{ |
|
str = vtkStdString(t_.stringToken()); |
|
} |
|
else |
|
{ |
|
//vtkErrorMacro("token type does not match"); |
|
str = ""; |
|
} |
|
return *this; |
|
} |
|
|
|
const vtkFoamEntryValue& operator>>(double& d) const |
|
{ |
|
if(type_ == SCALAR || type_ == LABEL) |
|
{ |
|
d = t_.number(); |
|
} |
|
else |
|
{ |
|
//vtkErrorMacro("token type does not match"); |
|
d = 0.0; |
|
} |
|
return *this; |
|
} |
|
|
|
const vtkFoamEntryValue& operator>>(int& i) const |
|
{ |
|
if(type_ == LABEL) |
|
{ |
|
i = t_.labelToken(); |
|
} |
|
else |
|
{ |
|
//vtkErrorMacro("token type does not match"); |
|
i = 0; |
|
} |
|
return *this; |
|
} |
|
}; |
|
|
|
// 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_; |
|
|
|
public: |
|
vtkFoamEntry() {} |
|
~vtkFoamEntry() |
|
{ |
|
for(size_t i = 0; i < valuePtrs_.size(); i++) |
|
{ |
|
delete valuePtrs_[i]; |
|
} |
|
} |
|
|
|
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& firstValue() const { return *valuePtrs_[0]; } |
|
const vtkstd::vector<int>& labelList() const |
|
{ return firstValue().labelList(); } |
|
const vtkstd::vector<vtkstd::vector<int> >& labelListList() const |
|
{ return firstValue().labelListList(); } |
|
vtkDoubleArray& scalarList() |
|
{ return firstValue().scalarList(); } |
|
vtkDoubleArray& vectorList() |
|
{ return firstValue().vectorList(); } |
|
vtkFoamDict& dictionary() // not using firstValue() for breaking constness |
|
{ return valuePtrs_[0]->dictionary(); } |
|
void *ptr() { return firstValue().ptr(); } |
|
|
|
void readDictionary(vtkFoamIOobject& io) |
|
{ |
|
valuePtrs_.push_back(new vtkFoamEntryValue); |
|
valuePtrs_.back()->readDictionary(io); |
|
} |
|
|
|
// read values of an entry |
|
void read(vtkFoamIOobject& io); |
|
|
|
const vtkFoamEntry& operator>>(vtkStdString& str) const |
|
{ |
|
if(!found() || valuePtrs_[0]->type() != vtkFoamEntryValue::STRING) |
|
{ |
|
str = ""; |
|
} |
|
else |
|
{ |
|
valuePtrs_[0]->operator>>(str); |
|
} |
|
return *this; |
|
} |
|
|
|
const vtkFoamEntry& operator>>(double& d) const |
|
{ |
|
if(!found() || (valuePtrs_[0]->type() != vtkFoamEntryValue::SCALAR |
|
&& valuePtrs_[0]->type() != vtkFoamEntryValue::LABEL)) |
|
{ |
|
d = 0.0; |
|
} |
|
else |
|
{ |
|
valuePtrs_[0]->operator>>(d); |
|
} |
|
return *this; |
|
} |
|
|
|
const vtkFoamEntry& operator>>(int& i) const |
|
{ |
|
if(!found() || valuePtrs_[0]->type() != vtkFoamEntryValue::LABEL) |
|
{ |
|
i = 0; |
|
} |
|
else |
|
{ |
|
valuePtrs_[0]->operator>>(i); |
|
} |
|
return *this; |
|
} |
|
}; |
|
|
|
// a class that holds a FoamFile data structure |
|
struct vtkOpenFOAMReader::vtkFoamDict: public vtkFoamEntryValue |
|
{ |
|
public: |
|
enum dictType |
|
{ UNDEFINED, DICTIONARY, SCALARLIST, VECTORLIST, LABELLIST, LABELLISTLIST, |
|
UNIFORMLABELLIST, UNIFORMSCALARLIST }; |
|
|
|
private: |
|
dictType type_; |
|
vtkstd::vector<vtkFoamEntry*> entryPtrs_; |
|
vtkFoamEntry* dummyEntryPtr_; |
|
|
|
vtkFoamDict(const vtkFoamDict &); |
|
|
|
public: |
|
vtkFoamDict(): vtkFoamEntryValue(), type_(UNDEFINED), dummyEntryPtr_(NULL) {} |
|
~vtkFoamDict() |
|
{ |
|
if(type_ == DICTIONARY) |
|
{ |
|
for(size_t i = 0; i < entryPtrs_.size(); i++) |
|
{ |
|
delete entryPtrs_[i]; |
|
} |
|
} |
|
if(dummyEntryPtr_ != NULL) |
|
{ |
|
delete dummyEntryPtr_; |
|
} |
|
} |
|
|
|
dictType type() const { return type_; } |
|
size_t size() const { return entryPtrs_.size(); } |
|
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; |
|
} |
|
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 vtkStdString& firstKeyword = "") |
|
{ |
|
try |
|
{ |
|
vtkFoamToken currToken; |
|
if(firstKeyword == "") |
|
{ |
|
if(!isSubDictionary) |
|
{ |
|
// polyMesh/points, lagrangian vectors |
|
if(io.className() == "vectorField") |
|
{ |
|
readVectorList(io, false); |
|
type_ = VECTORLIST; |
|
return true; |
|
} |
|
else if(io.className() == "scalarField") // lagrangian scalars |
|
{ |
|
readScalarList(io); |
|
type_ = SCALARLIST; |
|
return true; |
|
} |
|
else if(io.className() == "Cloud") // lagrangian/positions |
|
{ |
|
readVectorList(io, true); |
|
type_ = VECTORLIST; |
|
return true; |
|
} |
|
else if(io.className() == "faceList") // polyMesh/faces |
|
{ |
|
readLabelListList(io); |
|
type_ = LABELLISTLIST; |
|
return true; |
|
} |
|
else if(io.className() == "labelList") // polyMesh/{owner|neighbour} |
|
{ |
|
readLabelList(io); |
|
type_ = LABELLIST; |
|
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.labelToken() > 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) |
|
{ |
|
token() = currToken.labelToken(); |
|
type_ = UNIFORMLABELLIST; |
|
io.readExpecting('}'); |
|
return true; |
|
} |
|
else if(isSubDictionary && currToken.type() == vtkFoamToken::SCALAR) |
|
{ |
|
token() = currToken.number(); |
|
type_ = UNIFORMSCALARLIST; |
|
io.readExpecting('}'); |
|
return true; |
|
} |
|
// return as empty dictionary |
|
else if(isSubDictionary && currToken == '}') |
|
{ |
|
type_ = DICTIONARY; |
|
return true; |
|
} |
|
} |
|
// if firstKeyword is set read the following stream as subdictionary |
|
else |
|
{ |
|
entryPtrs_.push_back(new vtkFoamEntry); |
|
entryPtrs_.back()->keyword() = firstKeyword; |
|
entryPtrs_.back()->readDictionary(io); |
|
if(!io.read(currToken) || currToken == '}' || currToken == ')') |
|
{ |
|
type_ = DICTIONARY; |
|
return true; |
|
} |
|
} |
|
|
|
if(currToken.type() == vtkFoamToken::STRING) // general dictionary |
|
{ |
|
// based on src/OpenFOAM/db/dictionary/dictionaryIO.C |
|
do |
|
{ |
|
if(currToken != ';') // ignore empty entry |
|
{ |
|
entryPtrs_.push_back(new vtkFoamEntry); |
|
entryPtrs_.back()->keyword() = currToken.stringToken(); |
|
entryPtrs_.back()->read(io); |
|
if(currToken == "FoamFile") |
|
{ |
|
// delete the FoamFile header subdictionary entry |
|
delete entryPtrs_.back(); |
|
entryPtrs_.pop_back(); |
|
} |
|
} |
|
} while(io.read(currToken) |
|
&& (currToken.type() == vtkFoamToken::STRING || currToken == ';')); |
|
|
|
if(currToken.type() == vtkFoamToken::ERROR || currToken == '}' |
|
|| currToken == ')') |
|
{ |
|
type_ = DICTIONARY; |
|
return true; |
|
} |
|
throw vtkFoamError() |
|
<< "Expected keyword, closing brace, ; or EOF, found " << currToken; |
|
} |
|
throw vtkFoamError() << "Bad first keyword for dictionary " << currToken; |
|
} |
|
catch(vtkFoamError& e) |
|
{ |
|
if(isSubDictionary) |
|
{ |
|
throw; |
|
} |
|
else |
|
{ |
|
io.setError(e); |
|
return false; |
|
} |
|
} |
|
} |
|
}; |
|
|
|
void vtkOpenFOAMReader::vtkFoamIOobject::readHeader() |
|
{ |
|
vtkFoamToken firstToken; |
|
|
|
readExpecting("FoamFile"); |
|
readExpecting('{'); |
|
|
|
vtkFoamDict headerDict; |
|
headerDict.read(*this, true); // throw exception in case of error |
|
|
|
vtkFoamEntry& formatEntry = headerDict.lookup("format"); |
|
if(!formatEntry.found()) |
|
{ |
|
throw vtkFoamError() |
|
<< "the format entry (binary/ascii) not found in FoamFile header"; |
|
} |
|
vtkStdString format; |
|
formatEntry >> format; |
|
// case does matter (e. g. "BINARY" is treated as ascii) |
|
// see src/OpenFOAM/db/IOstreams/IOstreams/IOstream.C |
|
if(format == "binary") |
|
{ |
|
format_ = BINARY; |
|
} |
|
else |
|
{ |
|
format_ = ASCII; |
|
} |
|
|
|
vtkFoamEntry& classEntry = headerDict.lookup("class"); |
|
if(!classEntry.found()) |
|
{ |
|
throw vtkFoamError() << "class name not found in FoamFile header"; |
|
} |
|
classEntry >> headerClassName_; |
|
|
|
vtkFoamEntry& objectEntry = headerDict.lookup("object"); |
|
if(!objectEntry.found()) |
|
{ |
|
throw vtkFoamError() << "object name not found in FoamFile header"; |
|
} |
|
objectEntry >> objectName_; |
|
} |
|
|
|
void vtkOpenFOAMReader::vtkFoamEntryValue::clear() |
|
{ |
|
if(managed_) |
|
{ |
|
if(type_ == LABELLIST) |
|
{ |
|
delete labelListPtr_; |
|
} |
|
else if(type_ == LABELLISTLIST) |
|
{ |
|
delete labelListListPtr_; |
|
} |
|
else if(type_ == SCALARLIST) |
|
{ |
|
scalarListPtr_->Delete(); |
|
} |
|
else if(type_ == VECTORLIST) |
|
{ |
|
vectorListPtr_->Delete(); |
|
} |
|
else if(type_ == STRINGLIST) |
|
{ |
|
delete stringListPtr_; |
|
} |
|
else if(type_ == ENTRYVALUELIST) |
|
{ |
|
for(size_t i = 0; i < entryValuePtrs_.size() ; i++) |
|
{ |
|
delete entryValuePtrs_[i]; |
|
} |
|
} |
|
else if(type_ == DICTIONARY) |
|
{ |
|
delete dictPtr_; |
|
} |
|
} |
|
} |
|
|
|
// 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) |
|
{ |
|
io.read(t_); |
|
|
|
// initial guess of the list type |
|
if(t_.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_ = new intVector; |
|
labelListPtr_->value.push_back(t_.labelToken()); |
|
labelListPtr_->value.push_back(nextToken.labelToken()); |
|
type_ = LABELLIST; |
|
} |
|
else if(nextToken.type() == vtkFoamToken::SCALAR) |
|
{ |
|
scalarListPtr_ = vtkDoubleArray::New(); |
|
scalarListPtr_->InsertNextValue(t_.number()); |
|
scalarListPtr_->InsertNextValue(nextToken.number()); |
|
type_ = SCALARLIST; |
|
} |
|
else if(nextToken == '(') // list of list: read recursively |
|
{ |
|
entryValuePtrs_.push_back(new vtkFoamEntryValue); |
|
entryValuePtrs_.back()->readList(io); |
|
type_ = ENTRYVALUELIST; |
|
} |
|
else if(nextToken == ')') // list with only one label element |
|
{ |
|
labelListPtr_ = new intVector; |
|
labelListPtr_->value.push_back(t_.labelToken()); |
|
type_ = LABELLIST; |
|
return; |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected number, ( or ), found " << nextToken; |
|
} |
|
} |
|
else if(t_.type() == vtkFoamToken::SCALAR) |
|
{ |
|
scalarListPtr_ = vtkDoubleArray::New(); |
|
scalarListPtr_->InsertNextValue(t_.number()); |
|
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(t_.type() == vtkFoamToken::STRING) |
|
{ |
|
vtkFoamToken nextToken; |
|
if(!io.read(nextToken)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
if(nextToken.type() == vtkFoamToken::STRING) // list of strings |
|
{ |
|
stringListPtr_ = new stringVector; |
|
stringListPtr_->value.push_back(t_.stringToken()); |
|
stringListPtr_->value.push_back(nextToken.stringToken()); |
|
type_ = STRINGLIST; |
|
} |
|
// dictionary with the already read stringToken as the first keyword |
|
else if(nextToken == '{') |
|
{ |
|
if(t_.stringToken() == "") |
|
{ |
|
throw "Empty string is invalid as a keyword for dictionary entry"; |
|
} |
|
readDictionary(io, t_.stringToken()); |
|
// 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_ = new stringVector; |
|
stringListPtr_->value.push_back(t_.stringToken()); |
|
type_ = STRINGLIST; |
|
return; |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected string, { or ), found " << nextToken; |
|
} |
|
} |
|
else if(t_ == '(') // list of lists: read recursively |
|
{ |
|
entryValuePtrs_.push_back(new vtkFoamEntryValue); |
|
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); |
|
entryValuePtrs_.back()->read(io); |
|
} |
|
while(*entryValuePtrs_.back() != ')' && *entryValuePtrs_.back() != '}' |
|
&& *entryValuePtrs_.back() != ';'); |
|
|
|
if(*entryValuePtrs_.back() != ')') |
|
{ |
|
throw vtkFoamError() << "Expected ) before " |
|
<< entryValuePtrs_.back()->token(); |
|
} |
|
|
|
// delete ')' |
|
delete entryValuePtrs_.back(); |
|
entryValuePtrs_.pop_back(); |
|
type_ = ENTRYVALUELIST; |
|
return; |
|
} |
|
else if(t_ == ')') // empty list |
|
{ |
|
type_ = EMPTYLIST; |
|
return; |
|
} |
|
|
|
while(io.read(t_) && t_ != ')') |
|
{ |
|
if(type_ == LABELLIST) |
|
{ |
|
if(t_.type() == vtkFoamToken::SCALAR) // switch to scalarList |
|
{ |
|
// labelListPtr_ and scalarListPtr_ are packed into a single union so |
|
// we need a temprary pointer |
|
vtkDoubleArray* slPtr = vtkDoubleArray::New(); |
|
const vtkIdType size = labelListPtr_->value.size(); |
|
slPtr->SetNumberOfValues(size); |
|
for(vtkIdType i = 0; i < size; i++) |
|
{ |
|
slPtr->SetValue(i, double(labelListPtr_->value[i])); |
|
} |
|
delete labelListPtr_; |
|
slPtr->InsertNextValue(t_.number()); |
|
scalarListPtr_ = slPtr; // copy after labelListPtr_ is deleted |
|
type_ = SCALARLIST; |
|
} |
|
else if(t_.type() == vtkFoamToken::LABEL) |
|
{ |
|
labelListPtr_->value.push_back(t_.labelToken()); |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected a number, found " << t_; |
|
} |
|
} |
|
else if(type_ == SCALARLIST) |
|
{ |
|
if(t_.isNumber()) |
|
{ |
|
scalarListPtr_->InsertNextValue(t_.number()); |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected a number, found " << t_; |
|
} |
|
} |
|
else if(type_ == STRINGLIST) |
|
{ |
|
if(t_.type() == vtkFoamToken::STRING) |
|
{ |
|
stringListPtr_->value.push_back(t_.stringToken()); |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Expected a string, found " << t_; |
|
} |
|
} |
|
else if(type_ == ENTRYVALUELIST) |
|
{ |
|
if(t_.type() == vtkFoamToken::LABEL) |
|
{ |
|
// skip the number of elements to make things simple |
|
if(!io.read(t_)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
} |
|
if(t_ != '(') |
|
{ |
|
throw vtkFoamError() << "Expected (, found " << t_; |
|
} |
|
entryValuePtrs_.push_back(new vtkFoamEntryValue); |
|
entryValuePtrs_.back()->readList(io); |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Unexpected token " << t_; |
|
} |
|
} |
|
|
|
if(type_ == SCALARLIST) |
|
{ |
|
scalarListPtr_->Squeeze(); |
|
} |
|
} |
|
|
|
// a list of dictionaries is actually read as a dictionary |
|
void vtkOpenFOAMReader::vtkFoamEntryValue::readDictionary(vtkFoamIOobject& io, |
|
const vtkStdString& firstKeyword) |
|
{ |
|
dictPtr_ = new vtkFoamDict; |
|
type_ = DICTIONARY; |
|
dictPtr_->read(io, true, firstKeyword); |
|
} |
|
|
|
// guess the type of the given entry value and read it |
|
void vtkOpenFOAMReader::vtkFoamEntryValue::read(vtkFoamIOobject& io) |
|
{ |
|
if(!io.read(t_)) |
|
{ |
|
throw vtkFoamError() << "Unexpected EOF"; |
|
} |
|
|
|
if(t_ == '{') |
|
{ |
|
readDictionary(io); |
|
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, Hrv's uniformFixedValue b.c.) |
|
else if(t_ == '(') |
|
{ |
|
readList(io); |
|
return; |
|
} |
|
else if(t_ == "uniform") |
|
{ |
|
if(!io.read(t_)) |
|
{ |
|
throw vtkFoamError() |
|
<< "Expected a uniform value or a list, found unexpected EOF"; |
|
} |
|
if(t_ == '(') |
|
{ |
|
readList(io); |
|
} |
|
else if(t_.type() == vtkFoamToken::LABEL) |
|
{ |
|
type_ = LABEL; |
|
} |
|
else if(t_.type() == vtkFoamToken::SCALAR) |
|
{ |
|
type_ = SCALAR; |
|
} |
|
else if(t_.type() == vtkFoamToken::STRING) |
|
{ |
|
type_ = STRING; |
|
} |
|
else // unexpected punctuation token |
|
{ |
|
throw vtkFoamError() << "Expected number, string or (, found " << t_; |
|
} |
|
isUniform_ = true; |
|
} |
|
else if(t_ == "nonuniform") |
|
{ |
|
if(!io.read(t_)) |
|
{ |
|
throw vtkFoamError() << "Expected list type specifier, found EOF"; |
|
} |
|
if(t_ == "List<vector>") |
|
{ |
|
isUniform_ = false; |
|
readVectorList(io, false); |
|
} |
|
else if(t_ == "List<scalar>") |
|
{ |
|
isUniform_ = false; |
|
readScalarList(io); |
|
} |
|
// List<bool> is read as List<label> |
|
else if(t_ == "List<label>" || t_ == "List<bool>") |
|
{ |
|
isUniform_ = false; |
|
readLabelList(io); |
|
} |
|
// an empty list doesn't have a list type specifier |
|
else if(t_.type() == vtkFoamToken::LABEL && t_.labelToken() == 0) |
|
{ |
|
type_ = EMPTYLIST; |
|
isUniform_ = false; |
|
io.readExpecting('('); |
|
io.readExpecting(')'); |
|
} |
|
else |
|
{ |
|
throw vtkFoamError() << "Unsupported nonuniform list type " << t_; |
|
} |
|
} |
|
// zones have list without a uniform/nonuniform keyword |
|
// List<bool> is read as List<label> |
|
// (e. g. flipMap entry in point/face/cellZones) |
|
else if(t_ == "List<label>" || t_ == "List<bool>") |
|
{ |
|
isUniform_ = false; |
|
readLabelList(io); |
|
} |
|
else if(t_.type() == vtkFoamToken::LABEL) |
|
{ |
|
type_ = LABEL; |
|
} |
|
else if(t_.type() == vtkFoamToken::SCALAR) |
|
{ |
|
type_ = SCALAR; |
|
} |
|
else if(t_.type() == vtkFoamToken::STRING) |
|
{ |
|
type_ = STRING; |
|
} |
|
else if(t_.type() == vtkFoamToken::PUNCTUATION) |
|
{ |
|
type_ = PUNCTUATION; |
|
} |
|
} |
|
|
|
// read values of an entry |
|
void vtkOpenFOAMReader::vtkFoamEntry::read(vtkFoamIOobject& io) |
{ | { |
vtkstd::vector< int > value; |
for(;;) |
}; |
{ |
|
valuePtrs_.push_back(new vtkFoamEntryValue); |
|
valuePtrs_.back()->read(io); |
| |
struct intVectorVector |
if(valuePtrs_.size() >= 2) |
{ |
{ |
vtkstd::vector< vtkstd::vector< int > > value; |
vtkFoamEntryValue& secondLastValue |
}; |
= *valuePtrs_[valuePtrs_.size() - 2]; |
|
if(secondLastValue.type() == vtkFoamEntryValue::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() == vtkFoamEntryValue::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() == vtkFoamEntryValue::DICTIONARY) |
|
{ |
|
if(lastValue.dictionary().type() == vtkFoamDict::UNIFORMLABELLIST) |
|
{ |
|
const int size = secondLastValue.token().labelToken(); |
|
const int value = lastValue.dictionary().token().labelToken(); |
|
// delete last two values |
|
delete valuePtrs_.back(); |
|
valuePtrs_.pop_back(); |
|
delete valuePtrs_.back(); |
|
valuePtrs_.pop_back(); |
|
// make new labelList |
|
valuePtrs_.push_back(new vtkFoamEntryValue); |
|
valuePtrs_.back()->makeLabelList(value, size); |
|
} |
|
else if(lastValue.dictionary().type() |
|
== vtkFoamDict::UNIFORMSCALARLIST) |
|
{ |
|
const int size = secondLastValue.token().labelToken(); |
|
const double value = lastValue.dictionary().token().number(); |
|
// delete last two values |
|
delete valuePtrs_.back(); |
|
valuePtrs_.pop_back(); |
|
delete valuePtrs_.back(); |
|
valuePtrs_.pop_back(); |
|
// make new labelList |
|
valuePtrs_.push_back(new vtkFoamEntryValue); |
|
valuePtrs_.back()->makeScalarList(value, size); |
|
} |
|
} |
|
} |
|
} |
| |
struct faceVectorVector |
if(*valuePtrs_.back() == ';') |
{ |
{ |
vtkstd::vector< vtkstd::vector< face > > value; |
delete valuePtrs_.back(); |
}; |
valuePtrs_.pop_back(); |
|
break; |
|
} |
|
else if(valuePtrs_.back()->type() == vtkFoamEntryValue::DICTIONARY) |
|
{ |
|
// subdictionary is not suffixed by an entry terminator ';' |
|
break; |
|
} |
|
else if(*valuePtrs_.back() == '}' || *valuePtrs_.back() == ')') |
|
{ |
|
throw vtkFoamError() << "Unmatched " << valuePtrs_.back()->token(); |
|
} |
|
} |
|
} |
| |
vtkOpenFOAMReader::vtkOpenFOAMReader() | vtkOpenFOAMReader::vtkOpenFOAMReader() |
{ | { |
|
|
this->FileName = NULL; | this->FileName = NULL; |
| |
//VTK CLASSES | //VTK CLASSES |
this->Points = vtkPoints::New(); |
this->PatchDataArraySelection = vtkDataArraySelection::New(); |
this->CellDataArraySelection = vtkDataArraySelection::New(); | this->CellDataArraySelection = vtkDataArraySelection::New(); |
|
this->PointDataArraySelection = 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); |
|
|
|
// Initialise the Selection status arrays |
|
this->CellSelectionOldStatus = 0; |
|
this->PointSelectionOldStatus = 0; |
|
this->PatchSelectionOldStatus = 0; |
|
this->CellSelectionStatus = 0; |
|
this->PointSelectionStatus = 0; |
|
this->PatchSelectionStatus = 0; |
| |
//DATA COUNTS | //DATA COUNTS |
this->NumFaces = 0; |
|
this->NumPoints = 0; |
|
this->NumCells = 0; | this->NumCells = 0; |
| |
this->TimeStepData = new stringVector; | this->TimeStepData = new stringVector; |
this->Path = new stdString; |
this->LagrangianTimeStepData = new stringVector; |
this->PathPrefix = new stdString; |
this->OldFileName = new vtkStdString; |
|
this->PathPrefix = new vtkStdString; |
this->PolyMeshPointsDir = new stringVector; | this->PolyMeshPointsDir = new stringVector; |
this->PolyMeshFacesDir = 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 | //DATA TIMES |
this->NumberOfTimeSteps = 0; | this->NumberOfTimeSteps = 0; |
this->Steps = NULL; | this->Steps = NULL; |
|
this->TimeNames = vtkStringArray::New(); |
this->TimeStep = 0; | this->TimeStep = 0; |
this->TimeStepRange[0] = 0; | this->TimeStepRange[0] = 0; |
this->TimeStepRange[1] = 0; | this->TimeStepRange[1] = 0; |
this->RequestInformationFlag = true; |
|
|
// for caching mesh |
|
this->CacheMesh = 1; |
|
this->OldTimeStep = -1; |
|
this->InternalMesh = NULL; |
|
this->BoundaryMesh = NULL; |
|
this->BoundaryDict = NULL; |
|
this->FaceOwner = NULL; |
|
this->PointZoneMesh = NULL; |
|
this->FaceZoneMesh = NULL; |
|
this->CellZoneMesh = NULL; |
|
|
|
// for reading zones |
|
this->ReadZones = 0; // turned off by default |
|
// for accumulating patches across time-steps (Turned on by default) |
|
// As of now, only accumulation of patches is implemented |
|
this->KeepPatches = 1; |
} | } |
| |
vtkOpenFOAMReader::~vtkOpenFOAMReader() | vtkOpenFOAMReader::~vtkOpenFOAMReader() |
{ | { |
vtkDebugMacro(<<"DeConstructor"); | vtkDebugMacro(<<"DeConstructor"); |
this->Points->Delete(); |
|
|
// Delete the Observers before deleting the Selection Arrays !!! |
|
this->PatchDataArraySelection->RemoveObserver(this->SelectionObserver); |
|
this->CellDataArraySelection->RemoveObserver(this->SelectionObserver); |
|
this->PointDataArraySelection->RemoveObserver(this->SelectionObserver); |
|
|
|
// Now delete the Selection Observer itself |
|
this->SelectionObserver->Delete(); |
|
|
|
// Finally delete the Selection Arrays |
|
this->PatchDataArraySelection->Delete(); |
this->CellDataArraySelection->Delete(); | this->CellDataArraySelection->Delete(); |
delete [] this->Steps; |
this->PointDataArraySelection->Delete(); |
| |
delete this->TimeStepData; |
delete this->OldFileName; |
delete this->Path; |
|
delete this->PathPrefix; | delete this->PathPrefix; |
delete this->PolyMeshPointsDir; | delete this->PolyMeshPointsDir; |
delete this->PolyMeshFacesDir; | delete this->PolyMeshFacesDir; |
delete this->BoundaryNames; |
this->TimeNames->Delete(); |
delete this->PointZoneNames; |
delete this->TimeStepData; |
delete this->FaceZoneNames; |
delete this->LagrangianTimeStepData; |
delete this->CellZoneNames; |
|
delete this->FacePoints; |
this->ClearMeshes(); |
delete this->FacesOwnerCell; |
} |
delete this->FacesNeighborCell; |
|
delete this->FacesOfCell; |
void vtkOpenFOAMReader::ClearMeshes() |
delete this->SizeOfBoundary; |
{ |
|
if(this->FaceOwner != NULL) |
|
{ |
|
this->FaceOwner->Delete(); |
|
this->FaceOwner = NULL; |
|
} |
|
if(this->InternalMesh != NULL) |
|
{ |
|
this->InternalMesh->Delete(); |
|
this->InternalMesh = NULL; |
|
} |
|
if(this->BoundaryMesh != NULL) |
|
{ |
|
for(size_t i = 0; i < this->BoundaryMesh->value.size(); i++) |
|
{ |
|
this->BoundaryMesh->value[i]->Delete(); |
|
} |
|
delete this->BoundaryMesh; |
|
this->BoundaryMesh = NULL; |
|
} |
|
delete this->BoundaryDict; |
|
if(this->PointZoneMesh != NULL) |
|
{ |
|
for(size_t i = 0; i < this->PointZoneMesh->value.size(); i++) |
|
{ |
|
this->PointZoneMesh->value[i]->Delete(); |
|
} |
|
delete this->PointZoneMesh; |
|
this->PointZoneMesh = NULL; |
|
} |
|
if(this->FaceZoneMesh != NULL) |
|
{ |
|
for(size_t i = 0; i < this->FaceZoneMesh->value.size(); i++) |
|
{ |
|
this->FaceZoneMesh->value[i]->Delete(); |
|
} |
|
delete this->FaceZoneMesh; |
|
this->FaceZoneMesh = NULL; |
|
} |
|
if(this->CellZoneMesh != NULL) |
|
{ |
|
for(size_t i = 0; i < this->CellZoneMesh->value.size(); i++) |
|
{ |
|
this->CellZoneMesh->value[i]->Delete(); |
|
} |
|
delete this->CellZoneMesh; |
|
this->CellZoneMesh = NULL; |
|
} |
} | } |
| |
int vtkOpenFOAMReader::RequestData( | int vtkOpenFOAMReader::RequestData( |
|
|
vtkInformation* outInfo = outputVector->GetInformationObject(0); | vtkInformation* outInfo = outputVector->GetInformationObject(0); |
vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::SafeDownCast( | vtkMultiBlockDataSet *output = vtkMultiBlockDataSet::SafeDownCast( |
outInfo->Get(vtkMultiBlockDataSet::DATA_OBJECT())); | outInfo->Get(vtkMultiBlockDataSet::DATA_OBJECT())); |
|
|
if(!this->FileName) | if(!this->FileName) |
{ | { |
vtkErrorMacro("FileName has to be specified!"); | vtkErrorMacro("FileName has to be specified!"); |
return 0; | return 0; |
} | } |
this->CreateDataSet(output); |
|
return 1; |
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()); |
|
int timeI = 0; |
|
while(timeI < nSteps - 1 && steps[timeI] < requestedTimeValues[0]) |
|
{ |
|
timeI++; |
|
} |
|
this->SetTimeStep(timeI); |
|
|
|
outInfo->Set(vtkDataObject::DATA_TIME_STEPS(), &steps[timeI], 1); |
|
} |
|
#endif |
|
this->MakeTimeStepData(); |
|
|
|
const int ret = this->CreateDataSet(output, this->TimeStep); |
|
|
|
// update selection status |
|
this->CellSelectionOldStatus = this->CellSelectionStatus; |
|
this->PointSelectionOldStatus = this->PointSelectionStatus; |
|
this->PatchSelectionOldStatus = this->PatchSelectionStatus; |
|
|
|
return ret; |
} | } |
| |
void vtkOpenFOAMReader::PrintSelf(ostream& os, vtkIndent indent) | void vtkOpenFOAMReader::PrintSelf(ostream& os, vtkIndent indent) |
|
|
this->Superclass::PrintSelf(os,indent); | this->Superclass::PrintSelf(os,indent); |
os << indent << "File Name: " | os << indent << "File Name: " |
<< (this->FileName ? this->FileName : "(none)") << "\n"; | << (this->FileName ? this->FileName : "(none)") << "\n"; |
os << indent << "Number Of Nodes: " << this->NumPoints << "\n"; |
// os << indent << "Number Of Nodes: " << this->NumPoints << "\n"; |
os << indent << "Number Of Cells: " << this->NumCells << "\n"; | os << indent << "Number Of Cells: " << this->NumCells << "\n"; |
os << indent << "Number of Time Steps: " << this->NumberOfTimeSteps << endl; | os << indent << "Number of Time Steps: " << this->NumberOfTimeSteps << endl; |
os << indent << "TimeStepRange: " | os << indent << "TimeStepRange: " |
|
|
vtkInformationVector **vtkNotUsed(inputVector), | vtkInformationVector **vtkNotUsed(inputVector), |
vtkInformationVector *outputVector) | vtkInformationVector *outputVector) |
{ | { |
if(!this->FileName) |
if(!this->FileName || strlen(this->FileName) == 0) |
{ | { |
vtkErrorMacro("FileName has to be specified!"); | vtkErrorMacro("FileName has to be specified!"); |
return 0; | return 0; |
} | } |
vtkDebugMacro(<<"Request Info"); |
vtkDebugMacro(<<"Request Info: " <<this->FileName); |
if(RequestInformationFlag) |
|
|
if(*this->OldFileName != vtkStdString(this->FileName)) |
{ | { |
vtkDebugMacro(<<this->FileName); |
// updated this->OldFileName |
this->Path->value.append(this->FileName); |
*this->OldFileName = vtkStdString(this->FileName); |
this->ReadControlDict(); |
|
|
// clear prior case information |
|
this->OldTimeStep = -1; |
|
if(this->Steps != NULL) |
|
{ |
|
delete [] this->Steps; |
|
this->Steps = NULL; |
|
} |
|
this->ClearMeshes(); |
|
|
|
this->CellDataArraySelection->RemoveAllArrays(); |
|
this->PointDataArraySelection->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[0] = 0; |
this->TimeStepRange[1] = this->NumberOfTimeSteps-1; |
this->TimeStepRange[1] = this->NumberOfTimeSteps; |
this->PopulatePolyMeshDirArrays(); | this->PopulatePolyMeshDirArrays(); |
outputVector->GetInformationObject(0)->Set( | outputVector->GetInformationObject(0)->Set( |
vtkStreamingDemandDrivenPipeline::TIME_STEPS(), this->Steps, | vtkStreamingDemandDrivenPipeline::TIME_STEPS(), this->Steps, |
this->NumberOfTimeSteps); | this->NumberOfTimeSteps); |
this->RequestInformationFlag = false; |
#if PARAVIEW_VERSION_MAJOR >= 3 |
} |
double timeRange[2]; |
|
timeRange[0] = this->Steps[0]; |
//Add scalars and vectors to metadata |
timeRange[1] = this->Steps[this->NumberOfTimeSteps - 1]; |
//create path to current time step |
outputVector->GetInformationObject(0)->Set( |
vtksys_ios::stringstream tempPath; |
vtkStreamingDemandDrivenPipeline::TIME_RANGE(), timeRange, 2); |
tempPath << this->PathPrefix->value.c_str(); |
#endif |
tempPath << this->Steps[this->TimeStep]; |
|
|
|
//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 |
|
} | } |
| |
//clear prior timestep data |
this->MakeTimeStepData(); |
this->TimeStepData->value.clear(); |
|
|
|
//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") |
|
{ |
|
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); |
|
} |
|
} |
|
} |
|
} |
|
| |
directory->Delete(); |
|
return 1; | return 1; |
} | } |
| |
|
|
return; | return; |
} | } |
| |
// **************************************************************************** |
// |
// Method: vtkOpenFOAMReader::CombineOwnerNeigbor |
// POINT METHODS |
// |
// |
// Purpose: |
int vtkOpenFOAMReader::GetNumberOfPointArrays() |
// add Owner faces to the faces of a cell and then add the neighor faces |
{ |
// |
return this->PointDataArraySelection->GetNumberOfArrays(); |
// **************************************************************************** |
} |
void vtkOpenFOAMReader::CombineOwnerNeigbor() |
|
{ |
const char* vtkOpenFOAMReader::GetPointArrayName(int index) |
vtkDebugMacro(<<"Combine owner & neighbor faces"); |
{ |
//reintialize faces of the cells |
return this->PointDataArraySelection->GetArrayName(index); |
face tempFace; |
} |
this->FacesOfCell->value.clear(); |
|
this->FacesOfCell->value.resize(this->NumCells); |
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); |
|
} |
|
return; |
|
} |
|
|
|
void vtkOpenFOAMReader::DisableAllPointArrays() |
|
{ |
|
this->PointDataArraySelection->DisableAllArrays(); |
|
return; |
|
} |
|
|
|
void vtkOpenFOAMReader::EnableAllPointArrays() |
|
{ |
|
this->PointDataArraySelection->EnableAllArrays(); |
|
return; |
|
} |
|
|
|
|
|
// |
|
// PATCH METHODS |
|
// |
|
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); |
|
} |
|
return; |
|
} |
|
|
|
void vtkOpenFOAMReader::DisableAllPatchArrays() |
|
{ |
|
this->PatchDataArraySelection->DisableAllArrays(); |
|
return; |
|
} |
|
|
|
void vtkOpenFOAMReader::EnableAllPatchArrays() |
|
{ |
|
this->PatchDataArraySelection->EnableAllArrays(); |
|
return; |
|
} |
|
|
|
// Define the Selection Observer |
|
void vtkOpenFOAMReader::SelectionModifiedCallback(vtkObject*, |
|
unsigned long, void* clientdata, void*) |
|
{ |
|
static_cast<vtkOpenFOAMReader*>(clientdata)->SelectionModified(); |
|
} |
|
|
|
void vtkOpenFOAMReader::SelectionModified() |
|
{ |
|
// 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) |
|
this->CellSelectionStatus = 0; |
|
for(int i = this->GetNumberOfCellArrays() - 1; i >= 0; i--) |
|
{ |
|
this->CellSelectionStatus = (this->CellSelectionStatus << 1) |
|
+ this->GetCellArrayStatus(this->GetCellArrayName(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(this->GetNumberOfCellArrays() |
|
<= static_cast<int>(sizeof(this->CellSelectionStatus) * 8 - 1)) |
|
{ |
|
this->CellSelectionStatus = (this->CellSelectionStatus << 1) |
|
+ (this->CellSelectionOldStatus & 0x1); |
|
} |
|
else |
|
{ |
|
this->CellSelectionStatus = (this->CellSelectionStatus << 1) |
|
+ ((~this->CellSelectionOldStatus) & 0x1); |
|
} |
|
// Point Selection Arrays |
|
// this->PointSelectionOldStatus = this->PointSelectionStatus; |
|
this->PointSelectionStatus = 0; |
|
for(int i = this->GetNumberOfPointArrays() - 1; i >= 0; i--) |
|
{ |
|
this->PointSelectionStatus = (this->PointSelectionStatus << 1) |
|
+ this->GetPointArrayStatus(this->GetPointArrayName(i)); |
|
} |
|
if(this->GetNumberOfPointArrays() |
|
<= static_cast<int>(sizeof(this->PointSelectionStatus) * 8 - 1)) |
|
{ |
|
this->PointSelectionStatus = (this->PointSelectionStatus << 1) |
|
+ (this->PointSelectionOldStatus & 0x1); |
|
} |
|
else |
|
{ |
|
this->PointSelectionStatus = (this->PointSelectionStatus << 1) |
|
+ (~(this->PointSelectionOldStatus) & 0x1); |
|
} |
|
// Patch Selection Arrays |
|
// this->PatchSelectionOldStatus = this->PatchSelectionStatus; |
|
this->PatchSelectionStatus = 0; |
|
for(int i = this->GetNumberOfPatchArrays() - 1; i >= 0; i--) |
|
{ |
|
this->PatchSelectionStatus = (this->PatchSelectionStatus << 1) |
|
+ this->GetPatchArrayStatus(this->GetPatchArrayName(i)); |
|
} |
|
if(this->GetNumberOfPatchArrays() |
|
<= static_cast<int>(sizeof(this->PatchSelectionStatus) * 8 - 1)) |
|
{ |
|
this->PatchSelectionStatus = (this->PatchSelectionStatus << 1) |
|
+ (this->PatchSelectionOldStatus & 0x1); |
|
} |
|
else |
|
{ |
|
this->PatchSelectionStatus = (this->PatchSelectionStatus << 1) |
|
+ (~(this->PatchSelectionOldStatus) & 0x1); |
|
} |
|
|
|
// Indicate that the pipeline needs to be updated (VTK Command) |
|
this->Modified(); |
|
} |
|
|
|
|
|
// create field data lists and cell/point array selection lists |
|
void vtkOpenFOAMReader::MakeTimeStepData() |
|
{ |
|
// Read the patches from the boundary file into selection array |
|
int timeState = this->TimeStep; |
|
vtkFoamDict* boundaryDictPtr |
|
= this->GatherBlocks("boundary", timeState, true); |
|
if(boundaryDictPtr == NULL) |
|
{ |
|
vtkErrorMacro(<< "Couldn't read polyMesh/boundary"); |
|
return; |
|
} |
|
|
|
vtkFoamDict& boundaryDictTmp = *boundaryDictPtr; |
|
|
|
// Add the internal mesh by default always |
|
const vtkStdString tmpStr = "Internal Mesh"; |
|
this->PatchDataArraySelection->AddArray(tmpStr.c_str()); |
|
|
|
// iterate through each entry in the boundary file |
|
for(size_t i = 0; i < boundaryDictTmp.size(); i++) |
|
{ |
|
vtkFoamEntry& boundaryEntryI = boundaryDictTmp.entry(i); |
|
int nFaces; |
|
boundaryEntryI.dictionary().lookup("nFaces") >> nFaces; |
|
|
|
// extract name of the current patch for insertion |
|
const vtkStdString& boundaryNameI = boundaryEntryI.keyword(); |
|
|
|
// If the size of patch becomes zero, but KeepPatches is selected, |
|
// do not remove from list, else, remove patch from list |
|
if(nFaces == 0) |
|
{ |
|
if((this->PatchDataArraySelection->ArrayExists(boundaryNameI.c_str())) |
|
&& (!this->GetKeepPatches())) |
|
{ |
|
this->PatchDataArraySelection->RemoveArrayByName(boundaryNameI.c_str()); |
|
} |
|
} |
|
else |
|
{ |
|
this->PatchDataArraySelection->AddArray(boundaryNameI.c_str()); |
|
} |
|
} |
|
delete boundaryDictPtr; |
|
|
|
// Commented out the "RemoveAllArrays()" line.... |
|
//this->CellDataArraySelection->RemoveAllArrays(); |
|
|
|
//clear prior timestep data |
|
this->TimeStepData->value.clear(); |
|
|
|
//Add scalars and vectors to metadata |
|
//create path to current time step |
|
vtkStdString tempPath |
|
= *this->PathPrefix + this->TimeNames->GetValue(this->TimeStep); |
|
|
|
//open the directory and get num of files |
|
vtkDirectory * directory = vtkDirectory::New(); |
|
if(!directory->Open(tempPath.c_str())) |
|
{ |
|
// no data |
|
directory->Delete(); |
|
return; |
|
} |
| |
//add owner faces to cell |
//loop over all files and locate |
for(int i = 0; i < (int)this->FacesOwnerCell->value.size(); i++) |
//volScalars and volVectors |
|
int nFieldFiles = directory->GetNumberOfFiles(); |
|
for(int j = 0; j < nFieldFiles; j++) |
{ | { |
for(int j = 0; j < (int)this->FacesOwnerCell->value[i].size(); j++) |
const vtkStdString fieldFile(directory->GetFile(j)); |
|
const int len = fieldFile.length(); |
|
|
|
// excluded extensions based on 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")) |
{ | { |
tempFace.faceIndex = this->FacesOwnerCell->value[i][j]; |
vtkFoamIOobject io; |
tempFace.neighborFace = false; |
if(io.open(tempPath + "/" + fieldFile)) // file exists and readable |
this->FacesOfCell->value[i].push_back(tempFace); |
{ |
|
if(io.className() == "volScalarField" || |
|
io.className() == "volVectorField") |
|
{ |
|
// real file name |
|
this->TimeStepData->value.push_back(fieldFile); |
|
// object name |
|
this->CellDataArraySelection->AddArray(io.objectName().c_str()); |
|
} |
|
io.close(); |
|
} |
|
#if 0 |
|
// warning is turned off in favor of silence |
|
else |
|
{ |
|
vtkWarningMacro(<< "File " << io.fileName().c_str() |
|
<< " is not a valid OpenFOAM object. Reason: " |
|
<< io.error().str().c_str() << " in line " |
|
<< io.lineNumber()); |
|
} |
|
#endif |
} | } |
} | } |
|
directory->Delete(); |
| |
//add neighbor faces to cell |
// locate laglangian fields |
for(int i = 0; i < (int)this->FacesNeighborCell->value.size(); i++) |
|
{ |
//clear prior timestep data |
for(int j = 0; j < (int)this->FacesNeighborCell->value[i].size(); j++) |
this->LagrangianTimeStepData->value.clear(); |
{ |
// Commented out the "RemoveAllArrays()" line.... |
tempFace.faceIndex = this->FacesNeighborCell->value[i][j]; |
//this->PointDataArraySelection->RemoveAllArrays(); |
tempFace.neighborFace = true; |
|
this->FacesOfCell->value[i].push_back(tempFace); |
//open the directory and get num of files |
|
tempPath += "/lagrangian"; |
|
directory = vtkDirectory::New(); |
|
if(directory->Open(tempPath.c_str())) |
|
{ |
|
nFieldFiles = directory->GetNumberOfFiles(); |
|
for(int j = 0; j < nFieldFiles; j++) |
|
{ |
|
const vtkStdString fieldFile(directory->GetFile(j)); |
|
const int len = fieldFile.length(); |
|
|
|
// excluded extensions based on 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; |
|
if(io.open(tempPath + "/" + fieldFile)) |
|
{ |
|
if(io.className() == "scalarField" |
|
|| io.className() == "vectorField") |
|
{ |
|
// real file name |
|
this->LagrangianTimeStepData->value.push_back(fieldFile); |
|
// object name |
|
this->PointDataArraySelection->AddArray( |
|
(vtkStdString("lagrangian/") + io.objectName()).c_str()); |
|
} |
|
else if(io.className() == "Cloud" && io.objectName() == "positions") |
|
{ |
|
this->PatchDataArraySelection->AddArray("Lagrangian Particles"); |
|
} |
|
io.close(); |
|
} |
|
} |
} | } |
} | } |
|
directory->Delete(); |
| |
//clean up memory |
// refresh selection status |
this->FacesOwnerCell->value.clear(); |
this->SelectionModified(); |
this->FacesNeighborCell->value.clear(); |
|
return; |
|
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
// Method: vtkOpenFOAMReader::MakeInternalMesh |
// Method: vtkOpenFOAMReader::InsertCellToGrid |
// | // |
// Purpose: | // Purpose: |
// derive cell types and create the internal mesh |
// determine cell shape and insert the cell into the mesh |
|
// hexahedron, prism, pyramid, tetrahedron, wedge&tetWedge |
// | // |
// **************************************************************************** | // **************************************************************************** |
vtkUnstructuredGrid * vtkOpenFOAMReader::MakeInternalMesh() |
void vtkOpenFOAMReader::InsertCellToGrid(vtkUnstructuredGrid* internalMesh, |
|
int cellId, faceVectorVector *facesOfCell, intVectorVector* facesPoints) |
{ | { |
vtkDebugMacro(<<"Make internal mesh"); |
// aliases |
//initialize variables |
const vtkstd::vector<vtkstd::vector<int> >& facePoints |
bool foundDup = false; |
= facesPoints->value; |
vtkstd::vector< int > cellPoints; |
const vtkstd::vector<face>& cellFaces = facesOfCell->value[cellId]; |
vtkstd::vector< int > tempFaces[2]; |
const size_t nCellFaces = cellFaces.size(); |
vtkstd::vector< int > firstFace; |
|
int pivotPoint = 0; |
|
int i, j, k, l, pCount; |
|
int faceCount = 0; |
|
|
|
//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 |
|
{ |
|
| |
//calculate the total points for the cell |
vtkIdList* cellPoints = vtkIdList::New(); |
//used to derive cell type |
|
int totalPointCount = 0; |
|
for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++) //each face |
|
{ |
|
totalPointCount += |
|
(int)this->FacePoints-> |
|
value[this->FacesOfCell->value[i][j].faceIndex].size(); |
|
} |
|
| |
// using cell type - order points, create cell, & add to mesh |
// determine type of the cell |
//OFhex | vtkHexahedron |
// based on src/OpenFOAM/meshes/meshShapes/cellMatcher/{hex|prism|pyr|tet}- |
if (totalPointCount == 24) |
// Matcher.C |
|
int cellType = VTK_CONVEX_POINT_SET; |
|
if(nCellFaces == 6) |
|
{ |
|
size_t j = 0; |
|
for(j = 0; j < nCellFaces; j++) |
{ | { |
faceCount = 0; |
if(facePoints[cellFaces[j].faceIndex].size() != 4) |
|
|
//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[ |
break; |
this->FacesOfCell->value[i][0].faceIndex][j]); |
|
} | } |
|
} |
//patch: if it is a neighbor face flip the points |
if(j == nCellFaces) |
if(this->FacesOfCell->value[i][0].neighborFace) |
{ |
|
cellType = VTK_HEXAHEDRON; |
|
} |
|
} |
|
else if(nCellFaces == 5) |
|
{ |
|
int nTris = 0, nQuads = 0; |
|
for(size_t j = 0; j < nCellFaces; j++) |
|
{ |
|
const int nPoints = facePoints[cellFaces[j].faceIndex].size(); |
|
if(nPoints == 3) |
{ | { |
int tempPop; |
nTris++; |
for(k = 0; k < (int)firstFace.size() - 1; k++) |
|
{ |
|
tempPop = firstFace[firstFace.size()-1]; |
|
firstFace.pop_back(); |
|
firstFace.insert(firstFace.begin()+1+k, tempPop); |
|
} |
|
} | } |
|
else if(nPoints == 4) |
//add first face to cell points |
|
for(j =0; j < (int)firstFace.size(); j++) |
|
{ | { |
cellPoints.push_back(firstFace[j]); |
nQuads++; |
} | } |
|
else |
//find the opposite face and order the points correctly |
|
for(int pointCount = 0; pointCount < (int)firstFace.size(); pointCount++) |
|
{ | { |
|
break; |
//find the other 2 faces containing each point |
|
for(j = 1; j < (int)this->FacesOfCell->value[i].size(); j++) //each face |
|
{ |
|
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++; |
|
} |
|
} |
|
} |
|
|
|
//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; |
|
} | } |
|
} |
//create the hex cell and insert it into the mesh |
if(nTris == 2 && nQuads == 3) |
vtkHexahedron * hexahedron= vtkHexahedron::New(); |
{ |
for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) |
cellType = VTK_WEDGE; |
|
} |
|
else if(nTris == 4 && nQuads == 1) |
|
{ |
|
cellType = VTK_PYRAMID; |
|
} |
|
} |
|
else if(nCellFaces == 4) |
|
{ |
|
size_t j = 0; |
|
for(j = 0; j < nCellFaces; j++) |
|
{ |
|
if(facePoints[cellFaces[j].faceIndex].size() != 3) |
{ | { |
hexahedron->GetPointIds()->SetId(pCount, cellPoints[pCount]); |
break; |
} | } |
internalMesh->InsertNextCell(hexahedron->GetCellType(), |
|
hexahedron->GetPointIds()); |
|
hexahedron->Delete(); |
|
cellPoints.clear(); |
|
firstFace.clear(); |
|
} | } |
|
if(j == nCellFaces) |
|
{ |
|
cellType = VTK_TETRA; |
|
} |
|
} |
| |
//OFprism | vtkWedge |
// not an Hex/Wedge/Pyramid/Tetra |
else if (totalPointCount == 18) |
if(cellType == VTK_CONVEX_POINT_SET) |
|
{ |
|
int nPoints = 0; |
|
for(size_t j = 0; j < nCellFaces; j++) |
{ | { |
faceCount = 0; |
nPoints += facePoints[cellFaces[j].faceIndex].size(); |
int index = 0; |
} |
|
if(nPoints == 0) |
|
{ |
|
cellType = VTK_EMPTY_CELL; |
|
} |
|
} |
| |
//find first triangular face |
// Cell shape constructor based on the one implementd by Terry |
for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++) //each face |
// Jordan, with some improvements. not as elegant as the one in |
|
// OpenFOAM but works reasonably fast. |
|
|
|
// OFhex | vtkHexahedron || OFprism | vtkWedge |
|
if (cellType == VTK_HEXAHEDRON || cellType == VTK_WEDGE) |
|
{ |
|
// find the base face number |
|
size_t face0Id = 0; |
|
if(cellType == VTK_HEXAHEDRON) |
|
{ |
|
cellPoints->SetNumberOfIds(8); |
|
face0Id = 0; |
|
} |
|
else // VTK_WEDGE |
|
{ |
|
cellPoints->SetNumberOfIds(6); |
|
for(size_t j = 0; j < nCellFaces; j++) |
{ | { |
if((int)this->FacePoints-> |
if(facePoints[cellFaces[j].faceIndex].size() == 3) |
value[this->FacesOfCell->value[i][j].faceIndex].size() == 3) |
|
{ | { |
for(k = 0; k < (int)this->FacePoints->value[ |
face0Id = j; |
this->FacesOfCell->value[i][j].faceIndex].size(); k++) |
|
{ |
|
firstFace.push_back(this->FacePoints->value[ |
|
this->FacesOfCell->value[i][j].faceIndex][k]); |
|
index = j; |
|
} |
|
break; | break; |
} | } |
} | } |
|
} |
| |
|
//get first face in correct order |
|
const vtkstd::vector<int>& face0Points |
|
= facePoints[cellFaces[face0Id].faceIndex]; |
|
size_t nFace0Points = face0Points.size(); |
|
vtkstd::vector<int> baseFace(nFace0Points); // ordered point list |
|
if(cellFaces[face0Id].neighborFace) |
|
{ |
//patch: if it is a neighbor face flip the points | //patch: if it is a neighbor face flip the points |
if(this->FacesOfCell->value[i][0].neighborFace) |
for(size_t j = 0; j < nFace0Points; j++) |
{ | { |
int tempPop; |
baseFace[j] = face0Points[nFace0Points - 1 - j]; |
for(k = 0; k < (int)firstFace.size() - 1; k++) |
//add base face to cell points |
{ |
cellPoints->SetId(j, baseFace[j]); |
tempPop = firstFace[firstFace.size()-1]; |
|
firstFace.pop_back(); |
|
firstFace.insert(firstFace.begin()+1+k, tempPop); |
|
} |
|
} | } |
|
} |
//add first face to cell points |
else |
for(j =0; j < (int)firstFace.size(); j++) |
{ |
|
for(size_t j = 0; j < nFace0Points; j++) |
{ | { |
cellPoints.push_back(firstFace[j]); |
baseFace[j] = face0Points[j]; |
|
//add base face to cell points |
|
cellPoints->SetId(j, baseFace[j]); |
} | } |
|
} |
| |
//find the opposite face and order the points correctly |
//find the opposite face points and order the points correctly |
for(int pointCount = 0; pointCount < (int)firstFace.size(); pointCount++) |
const size_t nBaseFacePoints = baseFace.size(); |
|
for(size_t pointCount = 0; pointCount < nBaseFacePoints; pointCount++) |
|
{ |
|
int pivotPoint = -1; |
|
const int baseFacePointI = baseFace[pointCount]; |
|
for(size_t j = 0; j < nCellFaces; j++) //each face |
{ | { |
//find the 2 other faces containing each point |
if(j == face0Id) |
for(j = 0; j < (int)this->FacesOfCell->value[i].size(); j++) //each face |
{ |
|
continue; |
|
} |
|
const vtkstd::vector<int>& faceJPoints |
|
= facePoints[cellFaces[j].faceIndex]; |
|
const size_t sizeK = faceJPoints.size(); |
|
if(sizeK == 3) // omit the other triangular wedge face |
|
{ |
|
continue; |
|
} |
|
for(size_t k = 0; k < sizeK; k++) //each point |
{ | { |
for(k = 0; k < (int)this->FacePoints->value[ |
// if the point matches the point of the base face... |
this->FacesOfCell->value[i][j].faceIndex].size(); k++) |
if(baseFacePointI == faceJPoints[k]) |
{ | { |
if(firstFace[pointCount] == this->FacePoints->value[ |
const bool isNeighbor = cellFaces[j].neighborFace; |
this->FacesOfCell->value[i][j].faceIndex][k] && j != index) |
const int faceJPrevPoint = faceJPoints[(sizeK + k - 1) % sizeK]; |
|
const int faceJNextPoint = faceJPoints[(k + 1) % sizeK]; |
|
const int baseFacePrevPoint = baseFace[(nBaseFacePoints |
|
+ pointCount - 1) % nBaseFacePoints]; |
|
const int baseFaceNextPoint |
|
= baseFace[(pointCount + 1) % nBaseFacePoints]; |
|
|
|
// if the next point of the j-th face matches the |
|
// previous point of the base face use the previous |
|
// point of the j-th face as the pivot point and use the |
|
// next point otherwise |
|
if(faceJNextPoint == (isNeighbor ? baseFaceNextPoint |
|
: baseFacePrevPoint)) |
{ | { |
//ANOTHER FACE WITH POINT |
pivotPoint = faceJPrevPoint; |
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++; |
|
} | } |
} |
else |
} |
{ |
|
pivotPoint = faceJNextPoint; |
|
} |
|
cellPoints->SetId(nBaseFacePoints + pointCount, pivotPoint); |
| |
//locate the pivot point of faces 0 & 1 |
// we further look at one more vertex: |
for(j = 0; j < (int)tempFaces[0].size(); j++) |
// if the j-th face also shares next point of the base face |
{ |
// add the corresponding opposite point to cell points |
for(k = 0; k < (int)tempFaces[1].size(); k++) |
if(pointCount < nBaseFacePoints - 1 && baseFaceNextPoint |
{ |
== (isNeighbor ? faceJNextPoint : faceJPrevPoint)) |
if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] != |
|
firstFace[pointCount]) |
|
{ | { |
pivotPoint = tempFaces[0][j]; |
pointCount++; |
break; |
cellPoints->SetId(nBaseFacePoints + pointCount, |
|
faceJPoints[(k + 2) % sizeK]); |
} | } |
|
break; // look no more points as to the face |
} | } |
} | } |
cellPoints.push_back(pivotPoint); |
if(pivotPoint >= 0) // break if the pivot point is found |
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; |
|
|
|
//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++) |
|
{ |
|
cellPoints.push_back(this->FacePoints->value[ |
|
this->FacesOfCell->value[i][j].faceIndex][k]); |
|
} |
|
break; | break; |
} | } |
} | } |
|
} |
|
//create the hex cell and insert it into the mesh |
|
internalMesh->InsertNextCell(cellType, cellPoints); |
|
} |
| |
//compare first face points to other faces |
//OFpyramid | vtkPyramid || OFtet | vtkTetrahedron |
for(j = 0; j < (int)cellPoints.size(); j++) //each point |
else if (cellType == VTK_PYRAMID || cellType == VTK_TETRA) |
|
{ |
|
int baseFaceId = -1; |
|
if(cellType == VTK_PYRAMID) |
|
{ |
|
for(size_t j = 0; j < nCellFaces; j++) |
{ | { |
for(k = 0; k < (int)this->FacePoints->value[ |
if(facePoints[cellFaces[j].faceIndex].size() == 4) |
this->FacesOfCell->value[i][1].faceIndex].size(); k++) |
|
{ |
|
if(cellPoints[j] == this->FacePoints->value[ |
|
this->FacesOfCell->value[i][1].faceIndex][k]) |
|
{ |
|
foundDup = true; |
|
} |
|
} |
|
if(!foundDup) |
|
{ | { |
cellPoints.push_back(this->FacePoints->value[ |
baseFaceId = j; |
this->FacesOfCell->value[i][j].faceIndex][k]); |
|
break; | break; |
} | } |
} | } |
|
cellPoints->SetNumberOfIds(5); |
//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]); |
|
} |
|
internalMesh->InsertNextCell(pyramid->GetCellType(), |
|
pyramid->GetPointIds()); |
|
cellPoints.clear(); |
|
pyramid->Delete(); |
|
} | } |
|
else // VTK_TETRA |
//OFtet | vtkTetrahedron |
|
else if (totalPointCount == 12) |
|
{ | { |
foundDup = false; |
baseFaceId = 0; |
|
cellPoints->SetNumberOfIds(4); |
|
} |
| |
//add first face to cell points |
//add first face to cell points |
for(j = 0; j < (int)this->FacePoints->value[ |
const vtkstd::vector<int>& baseFacePoints |
this->FacesOfCell->value[i][0].faceIndex].size(); j++) |
= facePoints[cellFaces[baseFaceId].faceIndex]; |
|
const size_t nBaseFacePoints = baseFacePoints.size(); |
|
if(cellFaces[baseFaceId].neighborFace) |
|
{ |
|
// if it is a neighbor face flip the points |
|
for(size_t j = 0; j < nBaseFacePoints; j++) |
{ | { |
cellPoints.push_back(this->FacePoints->value[ |
cellPoints->SetId(j, baseFacePoints[nBaseFacePoints - 1 - j]); |
this->FacesOfCell->value[i][0].faceIndex][j]); |
|
} | } |
|
} |
//compare first face to the points of second face |
else |
for(j = 0; j < (int)cellPoints.size(); j++) //each point |
{ |
|
for(size_t j = 0; j < nBaseFacePoints; j++) |
{ | { |
for(k = 0; k < (int)this->FacePoints->value[ |
cellPoints->SetId(j, baseFacePoints[j]); |
this->FacesOfCell->value[i][1].faceIndex].size(); k++) |
|
{ |
|
if(cellPoints[j] == this->FacePoints->value[ |
|
this->FacesOfCell->value[i][1].faceIndex][k]) |
|
{ |
|
foundDup = true; |
|
} |
|
} |
|
if(!foundDup) |
|
{ |
|
cellPoints.push_back(this->FacePoints->value[ |
|
this->FacesOfCell->value[i][j].faceIndex][k]); |
|
break; |
|
} |
|
} | } |
|
} |
| |
//create the wedge cell and insert it into the mesh |
// compare an adjacent face (any non base face is ok) point 1 to |
vtkTetra * tetra = vtkTetra::New(); |
// base face points |
for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) |
const int adjacentFaceId = (baseFaceId == 0) ? 1 : baseFaceId - 1; |
|
const vtkstd::vector<int>& adjacentFacePoints |
|
= facePoints[cellFaces[adjacentFaceId].faceIndex]; |
|
const int adjacentFacePoint1 = adjacentFacePoints[1]; |
|
bool foundDup = false; |
|
for(size_t j = 0; j < nBaseFacePoints; j++) |
|
{ |
|
// if point 1 of the adjacent face matchs point j of the base face... |
|
if(cellPoints->GetId(j) == adjacentFacePoint1) |
{ | { |
tetra->GetPointIds()->SetId(pCount, cellPoints[pCount]); |
// 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((cellFaces[adjacentFaceId].neighborFace |
|
? (j + 1) : (nBaseFacePoints + j - 1)) % nBaseFacePoints)) ? |
|
adjacentFacePoints[0] : adjacentFacePoints[2]); |
|
foundDup = true; |
|
break; |
} | } |
internalMesh->InsertNextCell(tetra->GetCellType(), |
|
tetra->GetPointIds()); |
|
cellPoints.clear(); |
|
tetra->Delete(); |
|
} | } |
|
// if point 1 of the adjacent face does not match any points of |
//erronous cells |
// the base face, it's the pivot point |
else if(totalPointCount == 0) |
if(!foundDup) |
{ | { |
vtkWarningMacro("Warning: No points in cell."); |
cellPoints->SetId(nBaseFacePoints, adjacentFacePoint1); |
} | } |
| |
//OFpolyhedron || vtkConvexPointSet |
//create the tetra cell and insert it into the mesh |
else |
internalMesh->InsertNextCell(cellType, cellPoints); |
{ |
} |
vtkWarningMacro("Warning: Polyhedral Data is very Slow!"); |
|
foundDup = false; |
|
| |
//get first face |
//erronous cells |
for(j = 0; j < (int)this->FacePoints->value[ |
else if(cellType == VTK_EMPTY_CELL) |
this->FacesOfCell->value[i][0].faceIndex].size(); j++) |
{ |
|
vtkWarningMacro("Warning: No points in cell."); |
|
} |
|
|
|
//OFpolyhedron || vtkConvexPointSet |
|
else |
|
{ |
|
// vtkWarningMacro("Warning: Polyhedral Data is very Slow!"); |
|
|
|
//get first face |
|
const vtkstd::vector<int>& baseFacePoints |
|
= facePoints[cellFaces[0].faceIndex]; |
|
const size_t nBaseFacePoints = baseFacePoints.size(); |
|
//add first face to cell points |
|
// not sure if flipping is necessary but do it anyway |
|
if(cellFaces[0].neighborFace) |
|
{ |
|
// if it is a neighbor face flip the points |
|
for(size_t j = 0; j < nBaseFacePoints; j++) |
{ | { |
firstFace.push_back(this->FacePoints->value[ |
cellPoints->InsertNextId(baseFacePoints[nBaseFacePoints - 1 - j]); |
this->FacesOfCell->value[i][0].faceIndex][j]); |
|
} | } |
|
} |
//add first face to cell points |
else |
for(j =0; j < (int)firstFace.size(); j++) |
{ |
|
for(size_t j = 0; j < nBaseFacePoints; j++) |
{ | { |
cellPoints.push_back(firstFace[j]); |
cellPoints->InsertNextId(baseFacePoints[j]); |
} | } |
|
} |
| |
//loop through faces and create a list of all points |
//loop through faces and create a list of all points |
//j = 1 skip firstFace |
//j = 1 skip baseFace |
for(j = 1; j < (int)this->FacesOfCell->value[i].size(); j++) |
for(size_t j = 1; j < nCellFaces; j++) |
|
{ |
|
//remove duplicate points from faces |
|
const vtkstd::vector<int>& faceJPoints |
|
= facePoints[cellFaces[j].faceIndex]; |
|
const size_t nFaceJPoints = faceJPoints.size(); |
|
for(size_t k = 0; k < nFaceJPoints; k++) |
{ | { |
//remove duplicate points from faces |
const int faceJPointK = faceJPoints[k]; |
for(k = 0; k < (int)this->FacePoints->value[ |
bool foundDup = false; |
this->FacesOfCell->value[i][j].faceIndex].size(); k++) |
for(int l = 0; l < cellPoints->GetNumberOfIds(); l++) |
{ | { |
for(l = 0; l < (int)cellPoints.size(); l++); |
if(cellPoints->GetId(l) == faceJPointK) |
{ |
|
if(cellPoints[l] == this->FacePoints->value[ |
|
this->FacesOfCell->value[i][j].faceIndex][k]) |
|
{ |
|
foundDup = true; |
|
} |
|
} |
|
if(!foundDup) |
|
{ | { |
cellPoints.push_back(this->FacePoints->value[ |
foundDup = true; |
this->FacesOfCell->value[i][j].faceIndex][k]); |
break; // look no more |
foundDup = false; |
|
} | } |
} | } |
|
if(!foundDup) |
|
{ |
|
cellPoints->InsertNextId(faceJPointK); |
|
} |
} | } |
|
|
//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]); |
|
} |
|
internalMesh->InsertNextCell(poly->GetCellType(), |
|
poly->GetPointIds()); |
|
cellPoints.clear(); |
|
firstFace.clear(); |
|
poly->Delete(); |
|
} | } |
} |
|
| |
//set the internal mesh points |
//create the poly cell and insert it into the mesh |
internalMesh->SetPoints(Points); |
internalMesh->InsertNextCell(VTK_CONVEX_POINT_SET, cellPoints); |
vtkDebugMacro(<<"Internal mesh made"); |
} |
return internalMesh; |
cellPoints->Delete(); |
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
// Method: vtkOpenFOAMReader::ControlDictDataParser |
// Method: vtkOpenFOAMReader::MakeInternalMesh |
// | // |
// Purpose: | // Purpose: |
// parse out double values for controlDict entries |
// derive cell types and create the internal mesh |
// utility function |
|
// | // |
// **************************************************************************** | // **************************************************************************** |
double vtkOpenFOAMReader::ControlDictDataParser(const char * lineIn) |
vtkUnstructuredGrid * vtkOpenFOAMReader::MakeInternalMesh( |
|
faceVectorVector *facesOfCell, intVectorVector* facesPoints, |
|
vtkPoints* points) |
{ | { |
double value; |
vtkDebugMacro(<<"Make internal mesh"); |
vtkstd::string line(lineIn); |
|
line.erase(line.begin()+line.find(";")); |
|
vtkstd::string token; |
|
vtksys_ios::stringstream tokenizer(line); |
|
| |
//parse to the final entry - double |
//Create Mesh |
//while(tokenizer>>token); |
vtkUnstructuredGrid* internalMesh = vtkUnstructuredGrid::New(); |
while(!tokenizer.eof()) |
internalMesh->Allocate(facesOfCell->value.size()); |
|
|
|
//loop through each cell, derive type and insert it into the mesh |
|
//hexahedron, prism, pyramid, tetrahedron, wedge&tetWedge |
|
for(size_t i = 0; i < facesOfCell->value.size(); i++) //each cell |
{ | { |
tokenizer >> token; |
this->InsertCellToGrid(internalMesh, i, facesOfCell, facesPoints); |
} | } |
|
//set the internal mesh points |
|
internalMesh->SetPoints(points); |
|
vtkDebugMacro(<<"Internal mesh made"); |
| |
vtksys_ios::stringstream conversion(token); |
return internalMesh; |
conversion >> value; |
|
return value; |
|
} | } |
| |
// **************************************************************************** |
// List time directories according to controlDict |
// Method: vtkOpenFOAMReader::ReadControlDict |
bool vtkOpenFOAMReader::ListTimeDirectoriesByControlDict(vtkFoamDict* dictPtr) |
// |
|
// Pupose: |
|
// reads the controlDict File |
|
// gather the necessary information to create a path to the data |
|
// |
|
// **************************************************************************** |
|
void vtkOpenFOAMReader::ReadControlDict () |
|
{ | { |
vtkDebugMacro(<<"Read controlDict"); |
vtkFoamDict& dict = *dictPtr; |
//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)) |
vtkFoamEntry& startTimeEntry = dict.lookup("startTime"); |
while (strcmp(temp.substr(0,9).c_str(), "startTime")) |
if(!startTimeEntry.found()) |
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<< "startTime entry not found in controlDict"); |
temp = tempStringStruct->value; |
return false; |
delete tempStringStruct; |
|
} | } |
startTime = this->ControlDictDataParser(temp.c_str()); |
double startTime; |
vtkDebugMacro(<<"Start time: "<<startTime); |
startTimeEntry >> startTime; |
| |
//find End Time |
vtkFoamEntry& endTimeEntry = dict.lookup("endTime"); |
//while(!(temp.compare(0,6,"endTime",0,6) == 0)) |
if(!endTimeEntry.found()) |
while (strcmp(temp.substr(0,7).c_str(), "endTime")) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<< "endTime entry not found in controlDict"); |
temp = tempStringStruct->value; |
return false; |
delete tempStringStruct; |
|
} | } |
endTime = this->ControlDictDataParser(temp.c_str()); |
double endTime; |
vtkDebugMacro(<<"End time: "<<endTime); |
endTimeEntry >> endTime; |
| |
//find Delta T |
vtkFoamEntry& deltaTEntry = dict.lookup("deltaT"); |
//while(!(temp.compare(0,5,"deltaT",0,5) == 0)) |
if(!deltaTEntry.found()) |
while (strcmp(temp.substr(0,6).c_str(), "deltaT")) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<< "deltaT entry not found in controlDict"); |
temp = tempStringStruct->value; |
return false; |
delete tempStringStruct; |
|
} | } |
deltaT = this->ControlDictDataParser(temp.c_str()); |
double deltaT; |
vtkDebugMacro(<<"deltaT: "<<deltaT); |
deltaTEntry >> deltaT; |
| |
//find write control |
vtkFoamEntry& writeIntervalEntry = dict.lookup("writeInterval"); |
//while(!(temp.compare(0,11,"writeControl",0,11) == 0)) |
if(!writeIntervalEntry.found()) |
while (strcmp(temp.substr(0,12).c_str(), "writeControl")) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<< "writeInterval entry not found in controlDict"); |
temp = tempStringStruct->value; |
return false; |
delete tempStringStruct; |
|
} | } |
|
double writeInterval; |
|
writeIntervalEntry >> writeInterval; |
| |
temp.erase(temp.begin()+temp.find(";")); |
vtkFoamEntry& timeFormatEntry = dict.lookup("timeFormat"); |
vtkstd::string token; |
if(!timeFormatEntry.found()) |
vtksys_ios::stringstream tokenizer(temp); |
|
|
|
//while(tokenizer >> token); |
|
while(!tokenizer.eof()) |
|
{ | { |
tokenizer >> token; |
vtkErrorMacro(<< "timeFormat entry not found in controlDict"); |
|
return false; |
} | } |
writeControl = token; |
vtkStdString timeFormat; |
vtkDebugMacro(<<"Write control: "<<writeControl.c_str()); |
timeFormatEntry >> timeFormat; |
| |
//find write interval |
vtkFoamEntry& timePrecisionEntry = dict.lookup("timePrecision"); |
//while(!(temp.compare(0,12,"writeInterval",0,12) == 0)) |
int timePrecision; |
while (strcmp(temp.substr(0,13).c_str(), "writeInterval")) |
if(timePrecisionEntry.found()) |
|
{ |
|
timePrecisionEntry >> timePrecision; |
|
} |
|
else |
{ | { |
tempStringStruct = this->GetLine(input); |
timePrecision = 6; // the default value |
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 | //calculate the time step increment based on type of run |
//if(writeControl.compare(0,7,"timeStep",0,7) == 0) |
vtkStdString writeControl; |
if(!strcmp(writeControl.substr(0,8).c_str(), "timeStep")) |
dict.lookup("writeControl") >> writeControl; |
|
double timeStepIncrement; |
|
if(writeControl == "timeStep") |
{ | { |
vtkDebugMacro(<<"Time step type data"); | vtkDebugMacro(<<"Time step type data"); |
timeStepIncrement = writeInterval * deltaT; | timeStepIncrement = writeInterval * deltaT; |
} | } |
else |
else if(writeControl == "runTime" || writeControl == "adjustableRunTime") |
{ | { |
vtkDebugMacro(<<"Run time type data"); | vtkDebugMacro(<<"Run time type data"); |
timeStepIncrement = writeInterval; | timeStepIncrement = writeInterval; |
} | } |
|
else |
//find time format |
|
while(temp.find("timeFormat") == vtkstd::string::npos) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"Time step can't be determined because writeControl is" |
temp = tempStringStruct->value; |
" set to " << writeControl.c_str()); |
delete tempStringStruct; |
return false; |
} | } |
timeFormat = temp; |
|
| |
//calculate how many timesteps there should be | //calculate how many timesteps there should be |
float tempResult = ((endTime-startTime)/timeStepIncrement); |
double tempResult = (endTime - startTime) / timeStepIncrement; |
int tempNumTimeSteps = (int)(tempResult+0.5)+1; //+0.1 to round up |
int tempNumTimeSteps = (int)(tempResult + 0.5) + 1; //+0.1 to round up |
|
|
//make sure time step dir exists | //make sure time step dir exists |
vtkstd::vector< double > tempSteps; | vtkstd::vector< double > tempSteps; |
vtkDirectory * test = vtkDirectory::New(); | vtkDirectory * test = vtkDirectory::New(); |
vtksys_ios::stringstream parser; |
this->TimeNames->Initialize(); |
double tempStep; |
|
for(int i = 0; i < tempNumTimeSteps; i++) | for(int i = 0; i < tempNumTimeSteps; i++) |
{ | { |
tempStep = i*timeStepIncrement + startTime; |
vtkstd::ostringstream parser; |
parser.clear(); |
const double tempStep = i * timeStepIncrement + startTime; |
if(timeFormat.find("general") != vtkstd::string::npos) |
|
|
// determine time name based on Foam::Time::timeName() |
|
// in src/OpenFOAM/db/Time/Time.C |
|
#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 |
{ | { |
parser << tempStep; |
vtkWarningMacro("Warning: unsupported time format. Assuming general."); |
|
parser.setf(vtkstd::ios_base::fmtflags(0), vtkstd::ios_base::floatfield); |
|
} |
|
parser.precision(timePrecision); |
|
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); |
|
} |
} | } |
else |
#endif |
|
if(test->Open((*this->PathPrefix + parser.str()).c_str())) |
{ | { |
parser << ios::scientific <<tempStep; |
tempSteps.push_back(tempStep); |
|
this->TimeNames->InsertNextValue(parser.str()); |
} | } |
if(test->Open((this->PathPrefix->value+parser.str().c_str()).c_str())) |
// necessary for reading the case/0 directory whatever the timeFormat is |
|
// based on Foam::Time::operator++() in 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); | tempSteps.push_back(tempStep); |
|
this->TimeNames->InsertNextValue(vtkStdString("0")); |
} | } |
} | } |
test->Delete(); | test->Delete(); |
|
this->TimeNames->Squeeze(); |
| |
//Add the time steps that actually exist to steps | //Add the time steps that actually exist to steps |
//allows the run to be stopped short of controlDict spec | //allows the run to be stopped short of controlDict spec |
//allows for removal of timesteps | //allows for removal of timesteps |
this->NumberOfTimeSteps = tempSteps.size(); | this->NumberOfTimeSteps = tempSteps.size(); |
this->Steps = new double[this->NumberOfTimeSteps]; |
if(this->NumberOfTimeSteps > 0) |
for(int i = 0; i < this->NumberOfTimeSteps; i++) |
{ |
|
this->Steps = new double[this->NumberOfTimeSteps]; |
|
for(int i = 0; i < this->NumberOfTimeSteps; i++) |
|
{ |
|
this->Steps[i] = tempSteps[i]; |
|
} |
|
} |
|
else |
{ | { |
this->Steps[i] =tempSteps[i]; |
// dummy for safely deleting later |
|
this->Steps = new double[1]; |
|
this->Steps[0] = 0.0; |
} | } |
|
return true; |
|
} |
| |
input->close(); |
// list time directories by searching all valid time instances in a |
delete input; |
// case directory |
vtkDebugMacro(<<"controlDict read"); |
bool vtkOpenFOAMReader::ListTimeDirectoriesByInstances() |
return; |
{ |
|
// 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(); |
|
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; |
|
} |
|
timeValues->Delete(); |
|
|
|
return true; |
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
// Method: vtkOpenFOAMReader::GetPoints |
// Method: vtkOpenFOAMReader::ReadControlDict |
// | // |
// Purpose: |
// Pupose: |
// read the points file into a vtkPoints |
// reads the controlDict File |
|
// gather the necessary information to create a path to the data |
// | // |
// **************************************************************************** | // **************************************************************************** |
void vtkOpenFOAMReader::GetPoints (int timeState) |
bool vtkOpenFOAMReader::ReadControlDict(const char* pathIn) |
{ | { |
//path to points file |
vtkStdString path(pathIn); |
vtkstd::string pointPath = this->PathPrefix->value + |
vtkFoamIOobject io; |
this->PolyMeshPointsDir->value[timeState] + |
|
"/polyMesh/points"; |
|
vtkDebugMacro(<<"Read points file: "<<pointPath.c_str()); |
|
| |
vtkstd::string temp; |
if(!io.open(path)) |
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(); |
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
delete input; |
<< io.error().str().c_str()); |
return; |
return false; |
} | } |
|
vtkFoamDict dict; |
//determine if file is binary or ascii |
if(!dict.read(io)) |
while(temp.find("format") == vtkstd::string::npos) |
{ |
|
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
|
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
|
return false; |
|
} |
|
if(dict.type() != vtkFoamDict::DICTIONARY) |
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"The file type of " << io.fileName().c_str() |
temp = tempStringStruct->value; |
<< " is not a dictionary"); |
delete tempStringStruct; |
return false; |
} | } |
input->close(); |
|
| |
//reopen file in correct format |
//create the path to the data directory |
if(temp.find("binary") != vtkstd::string::npos) |
// note that if a file is specified from command line (with |
|
// --data=opt) its path may be a relative one |
|
vtkStdString prefix(path); |
|
// remove trailing "/controlDict.foam" |
|
#if defined(_WIN32) |
|
size_t pos = prefix.find_last_of("/\\"); |
|
#else |
|
size_t pos = prefix.find_last_of('/'); |
|
#endif |
|
if(pos != vtkStdString::npos) |
{ | { |
#ifdef _WIN32 |
prefix.erase(pos); |
input->open(pointPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); |
// remove trailing "/system" (or any other directory name) |
|
#if defined(_WIN32) |
|
pos = prefix.find_last_of("/\\"); |
|
#else |
|
pos = prefix.find_last_of('/'); |
|
#endif |
|
if(pos != vtkStdString::npos) |
|
{ |
|
prefix.erase(pos + 1); // preserve the last "/" |
|
} |
|
else |
|
{ |
|
#if defined(_WIN32) && PARAVIEW_VERSION_MAJOR >= 3 |
|
prefix = ".\\"; |
#else | #else |
input->open(pointPath.c_str(), ios::in VTK_IOS_NOCREATE); |
prefix = "./"; |
#endif | #endif |
binaryWriteFormat = true; |
} |
} | } |
else | else |
{ | { |
input->open(pointPath.c_str(),ios::in); |
#if defined(_WIN32) && PARAVIEW_VERSION_MAJOR >= 3 |
binaryWriteFormat = false; |
prefix = "..\\"; |
} |
#else |
|
prefix = "../"; |
double x,y,z; |
#endif |
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; |
|
} | } |
|
*this->PathPrefix = prefix; |
|
vtkDebugMacro(<<"Path: "<<this->PathPrefix->c_str()); |
| |
//find number of points |
vtkFoamEntry& writeControlEntry = dict.lookup("writeControl"); |
tempStringStruct = this->GetLine(input); |
if(!writeControlEntry.found()) |
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
while(temp.empty()) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<< "writeControl entry not found in " << pathIn); |
temp = tempStringStruct->value; |
return false; |
delete tempStringStruct; |
|
} | } |
|
vtkStdString writeControl; |
//read number of points |
writeControlEntry >> writeControl; |
tokenizer << temp; |
|
tokenizer >> NumPoints; |
vtkStdString adjustTimeStep; |
//binary data |
dict.lookup("adjustTimeStep") >> adjustTimeStep; // empty if not found |
if(binaryWriteFormat) |
|
|
// 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 taken from 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")) |
{ | { |
input->get(); //parenthesis |
return this->ListTimeDirectoriesByControlDict(&dict); |
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 | else |
{ | { |
tempStringStruct = this->GetLine(input); |
return this->ListTimeDirectoriesByInstances(); |
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; |
|
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
// Method: vtkOpenFOAMReader::ReadFacesFile |
// Method: vtkOpenFOAMReader::GetPoints |
// | // |
// Purpose: | // Purpose: |
// read the faces into a vtkstd::vector |
// read the points file into a vtkPoints |
// | // |
// **************************************************************************** | // **************************************************************************** |
void vtkOpenFOAMReader::ReadFacesFile (const char * facePathIn) |
vtkPoints* vtkOpenFOAMReader::GetPoints (int timeState) |
{ | { |
vtkstd::string facePath(facePathIn); |
//path to points file |
vtkDebugMacro(<<"Read faces file: "<<facePath.c_str()); |
vtkStdString pointPath = *this->PathPrefix + |
vtkstd::string temp; |
this->PolyMeshPointsDir->value[timeState] + "/polyMesh/points"; |
stdString* tempStringStruct; |
vtkDebugMacro(<<"Read points file: "<<pointPath.c_str()); |
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 |
vtkFoamIOobject io; |
while(temp.find("format") == vtkstd::string::npos) |
if(!(io.open(pointPath) || io.open(pointPath + ".gz"))) |
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
temp = tempStringStruct->value; |
<< io.error().str().c_str()); |
delete tempStringStruct; |
return NULL; |
} | } |
input->close(); |
vtkFoamDict dict; |
|
if(!dict.read(io)) |
//reopen file in correct format |
|
if(temp.find("binary") != vtkstd::string::npos) |
|
{ | { |
#ifdef _WIN32 |
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
input->open(facePath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); |
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
#else |
return NULL; |
input->open(facePath.c_str(), ios::in VTK_IOS_NOCREATE); |
|
#endif |
|
binaryWriteFormat = true; |
|
} | } |
else |
if(dict.type() != vtkFoamDict::VECTORLIST) |
{ | { |
input->open(facePath.c_str(),ios::in); |
vtkErrorMacro(<<"The file type of " << io.fileName().c_str() |
binaryWriteFormat = false; |
<< " is not a vectorList"); |
|
return NULL; |
} | } |
| |
vtksys_ios::stringstream tokenizer; |
vtkDoubleArray& vl = dict.vectorList(); |
size_t pos; |
|
int numFacePoints; |
|
this->FacePoints->value.clear(); |
|
| |
//find end of header |
//instantiate the points class |
//while(temp.compare(0,4, "// *", 0, 4) != 0) |
vtkPoints* points = vtkPoints::New(); |
while (strcmp(temp.substr(0,4).c_str(), "// *")) |
const int nPoints = vl.GetNumberOfTuples(); |
{ |
points->SetNumberOfPoints(nPoints); |
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} |
|
| |
//find number of faces |
for(int i = 0, index = 0; i < nPoints; i++, index += 3) |
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
while(temp.empty()) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
points->SetPoint(i, vl.GetPointer(index)); |
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} | } |
|
vtkDebugMacro(<<"Point file read"); |
|
return points; |
|
} |
| |
//read number of faces |
// **************************************************************************** |
tokenizer << temp; |
// Method: vtkOpenFOAMReader::ReadFacesFile |
tokenizer >> this->NumFaces; |
// |
this->FacePoints->value.resize(this->NumFaces); |
// Purpose: |
|
// read the faces into a vtkstd::vector |
tempStringStruct = this->GetLine(input); |
// |
temp = tempStringStruct->value; |
// **************************************************************************** |
delete tempStringStruct;//THROW OUT "(" |
intVectorVector* vtkOpenFOAMReader::ReadFacesFile (const char* facePathIn) |
|
{ |
|
const vtkStdString facePath(facePathIn); |
|
vtkDebugMacro(<<"Read faces file: "<<facePath.c_str()); |
| |
//binary data |
vtkFoamIOobject io; |
if(binaryWriteFormat) |
if(!(io.open(facePath) || io.open(facePath + ".gz"))) |
{ | { |
//char paren; |
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
int tempPoint; |
<< io.error().str().c_str()); |
for(int i = 0; i < NumFaces; i++) |
return NULL; |
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct;//THROW OUT blankline |
|
|
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; //grab point count |
|
|
|
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++) |
|
{ |
|
input->read((char *) &tempPoint, sizeof(int)); |
|
this->FacePoints->value[i][j] = tempPoint; |
|
} |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; //throw out ) and rest of line |
|
} |
|
} | } |
|
vtkFoamDict dict; |
//ascii data |
if(!dict.read(io)) |
else |
|
{ | { |
//create vtkstd::vector of points in each face |
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
for(int i = 0; i < this->NumFaces; i++) |
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
{ |
return NULL; |
tempStringStruct = this->GetLine(input); |
} |
temp = tempStringStruct->value; |
if(dict.type() != vtkFoamDict::LABELLISTLIST) |
delete tempStringStruct; |
{ |
|
vtkErrorMacro(<<"The file type of " << io.fileName().c_str() |
pos = temp.find("("); |
<< " is not a labelListList"); |
vtksys_ios::stringstream ascTokenizer; |
return NULL; |
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++) |
|
{ |
|
pos = temp.find(" "); |
|
vtksys_ios::stringstream lineTokenizer; |
|
lineTokenizer << temp.substr(0, pos); |
|
temp.erase(0, pos+1); |
|
lineTokenizer >> this->FacePoints->value[i][j]; |
|
} |
|
} |
|
} | } |
| |
input->close(); |
|
delete input; |
|
vtkDebugMacro(<<"Faces read"); | vtkDebugMacro(<<"Faces read"); |
return; |
return (intVectorVector *)dict.ptr(); |
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
// Method: vtkOpenFOAMReader::ReadOwnerFile |
// Method: vtkOpenFOAMReader::ReadOwnerNeighborFiles |
// | // |
// Purpose: | // Purpose: |
// read the owner file into a vtkstd::vector | // read the owner file into a vtkstd::vector |
// | // |
// **************************************************************************** | // **************************************************************************** |
void vtkOpenFOAMReader::ReadOwnerFile(const char * ownerPathIn) |
bool vtkOpenFOAMReader::ReadOwnerNeighborFiles(faceVectorVector* facesOfCell, |
|
const char* ownerPathIn, const char* neighborPathIn) |
{ | { |
vtkstd::string ownerPath(ownerPathIn); |
const vtkStdString ownerPath(ownerPathIn); |
vtkDebugMacro(<<"Read owner file: "<<ownerPath.c_str()); | 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 |
vtkFoamIOobject io; |
while(temp.find("format") == vtkstd::string::npos) |
if(!(io.open(ownerPath) || io.open(ownerPath + ".gz"))) |
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
temp = tempStringStruct->value; |
<< io.error().str().c_str()); |
delete tempStringStruct; |
return false; |
} | } |
input->close(); |
vtkFoamDict ownerDict; |
|
if(!ownerDict.read(io)) |
//reopen file in correct format |
|
if(temp.find("binary") != vtkstd::string::npos) |
|
{ | { |
#ifdef _WIN32 |
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
input->open(ownerPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); |
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
#else |
return false; |
input->open(ownerPath.c_str(), ios::in VTK_IOS_NOCREATE); |
|
#endif |
|
binaryWriteFormat = true; |
|
} | } |
else |
if(ownerDict.type() != vtkFoamDict::LABELLIST) |
{ | { |
input->open(ownerPath.c_str(),ios::in); |
vtkErrorMacro(<<"The file type of " << io.fileName().c_str() |
binaryWriteFormat = false; |
<< " is not a labelList"); |
|
return false; |
} | } |
|
io.close(); |
| |
vtkstd::string numFacesStr; |
const vtkStdString neighborPath(neighborPathIn); |
int faceValue; |
vtkDebugMacro(<<"Read neighbor file: "<<neighborPath.c_str()); |
|
|
this->FaceOwner = vtkIntArray::New(); |
|
| |
vtksys_ios::stringstream tokenizer; |
if(!(io.open(neighborPath) || io.open(neighborPath + ".gz"))) |
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); |
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
temp = tempStringStruct->value; |
<< io.error().str().c_str()); |
delete tempStringStruct; |
return false; |
} | } |
|
vtkFoamDict neighborDict; |
this->FaceOwner->SetNumberOfValues(this->NumFaces); |
if(!neighborDict.read(io)) |
|
|
//binary data |
|
if(binaryWriteFormat) |
|
{ | { |
input->get(); //parenthesis |
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
for(int i = 0; i < NumFaces; i++) |
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
{ |
return false; |
input->read((char *) &faceValue, sizeof(int)); |
|
this->FaceOwner->SetValue(i, faceValue); |
|
} |
|
} | } |
|
if(neighborDict.type() != vtkFoamDict::LABELLIST) |
//ascii data |
|
else |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"The file type of " << io.fileName().c_str() |
temp = tempStringStruct->value; |
<< " is not a labelList"); |
delete tempStringStruct; |
return false; |
|
|
//read face owners into int array |
|
for(int i = 0; i < this->NumFaces; i++) |
|
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
|
|
tokenizer.clear(); |
|
tokenizer << temp; |
|
tokenizer >> faceValue; |
|
this->FaceOwner->SetValue(i, faceValue); |
|
} |
|
} | } |
| |
//find the number of cells |
const vtkstd::vector<int>& faceOwner = ownerDict.labelList(); |
double * range; |
const vtkstd::vector<int>& faceNeighbor = neighborDict.labelList(); |
range = this->FaceOwner->GetRange(); |
|
this->NumCells = (int)range[1]+1; |
|
| |
//add the face number to the correct cell |
if(faceOwner.size() != faceNeighbor.size()) |
//according to owner |
|
this->FacesOwnerCell->value.resize(this->NumCells); |
|
int tempCellId; |
|
for(int j = 0; j < this->NumFaces; j++) |
|
{ | { |
tempCellId = this->FaceOwner->GetValue(j); |
vtkErrorMacro(<<"Numbers of faces in owner and neighbor don't match"); |
if(tempCellId != -1) |
return false; |
{ |
|
this->FacesOwnerCell->value[tempCellId].push_back(j); |
|
} |
|
} | } |
| |
input->close(); |
const size_t nFaces = faceOwner.size(); |
delete input; |
|
vtkDebugMacro(<<"Owner file read"); |
|
return; |
|
} |
|
| |
// **************************************************************************** |
if(nFaces == 0) |
// Method: vtkOpenFOAMReader::ReadNeighborFile |
|
// |
|
// Purpose: |
|
// read the neighbor file into a vtkstd::vector |
|
// |
|
// **************************************************************************** |
|
void vtkOpenFOAMReader::ReadNeighborFile(const char * neighborPathIn) |
|
{ |
|
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(); |
vtkWarningMacro(<<"The mesh contains no faces"); |
delete input; |
|
return; |
|
} | } |
| |
//determine if file is binary or ascii |
this->FaceOwner = vtkIntArray::New(); |
while(temp.find("format") == vtkstd::string::npos) |
vtkIntArray& fo = *this->FaceOwner; |
{ |
fo.SetNumberOfValues(nFaces); |
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} |
|
input->close(); |
|
| |
//reopen file in correct format |
//read face owners into int array |
if(temp.find("binary") != vtkstd::string::npos) |
for(size_t i = 0; i < nFaces; i++) |
{ |
|
#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 |
|
{ | { |
input->open(neighborPath.c_str(),ios::in); |
fo.SetValue(i, faceOwner[i]); |
binaryWriteFormat = false; |
|
} |
|
|
|
vtkstd::string numFacesStr; |
|
int faceValue; |
|
vtkIntArray * faceNeighbor = vtkIntArray::New(); |
|
|
|
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; |
|
} | } |
| |
//read face owners into int array |
//add the face numbers to the correct cell |
faceNeighbor->SetNumberOfValues(this->NumFaces); |
// based on Terry's code and |
|
// src/OpenFOAM/meshes/primitiveMesh/primitiveMeshCells.C |
| |
//binary data |
//find the number of cells |
if(binaryWriteFormat) |
int nCells = -1; |
|
for(size_t i = 0; i < nFaces; i++) |
{ | { |
input->get(); //parenthesis |
if(nCells < faceOwner[i]) // max(nCells, faceOwner[i]) |
for(int i = 0; i < this->NumFaces; i++) |
{ |
|
nCells = faceOwner[i]; |
|
} |
|
if(nCells < faceNeighbor[i]) // max(nCells, faceNeighbor[i]) |
{ | { |
input->read((char *) &faceValue, sizeof(int)); |
nCells = faceNeighbor[i]; |
faceNeighbor->SetValue(i, faceValue); |
|
} | } |
} | } |
|
nCells++; |
| |
//ascii data |
if(nCells == 0) |
else |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkWarningMacro(<<"The mesh contains no cells"); |
temp = tempStringStruct->value; |
|
delete tempStringStruct;//throw away ( |
|
//read face owners into int array |
|
for(int i = 0; i < this->NumFaces; i++) |
|
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
|
|
tokenizer.clear(); |
|
tokenizer << temp; |
|
tokenizer >> faceValue; |
|
faceNeighbor->SetValue(i, faceValue); |
|
} |
|
} | } |
//No need to recalulate the Number of Cells |
|
this->FacesNeighborCell->value.resize(this->NumCells); |
|
| |
//add face number to correct cell |
this->NumCells = nCells; |
int tempCellId; |
|
for(int j = 0; j < this->NumFaces; j++) |
// count number of faces per cell |
|
vtkstd::vector<int> nCellFaces(nCells, 0); |
|
for(size_t i = 0; i < nFaces; i++) |
{ | { |
tempCellId = faceNeighbor->GetValue(j); |
// simpleFoam/pitzDaily3Blocks has faces with owner cell number -1 |
if(tempCellId != -1) |
if(faceOwner[i] >= 0) |
|
{ |
|
nCellFaces[faceOwner[i]]++; |
|
} |
|
if(faceNeighbor[i] >= 0) |
{ | { |
this->FacesNeighborCell->value[tempCellId].push_back(j); |
nCellFaces[faceNeighbor[i]]++; |
} | } |
} | } |
| |
faceNeighbor->Delete(); |
// size cellFaces |
input->close(); |
vtkstd::vector<vtkstd::vector<face> >& cellFaces = facesOfCell->value; |
delete input; |
cellFaces.resize(nCells); |
vtkDebugMacro(<<"Neighbor file read"); |
for(int i = 0; i < nCells; i++) |
return; |
|
} |
|
|
|
// **************************************************************************** |
|
// 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); |
|
|
|
//loop through each timestep |
|
for(int i = 0; i < this->NumberOfTimeSteps; i++) |
|
{ | { |
polyMeshFound = false; |
cellFaces[i].resize(nCellFaces[i]); |
facesFound = false; |
} |
pointsFound = false; |
|
|
|
//create the path to the timestep |
|
path.clear(); |
|
timeStep.clear(); |
|
timeStep << Steps[i]; |
|
path << this->PathPrefix->value <<timeStep.str() << "/"; |
|
| |
//get the number of files |
//add face numbers to correct cell |
vtkDirectory * directory = vtkDirectory::New(); |
for(size_t i = 0; i < nFaces; i++) |
directory->Open(path.str().c_str()); |
{ |
int numFiles = directory->GetNumberOfFiles(); |
const int ownerCell = faceOwner[i]; // must be a signed int |
//Look for polyMesh Dir |
// simpleFoam/pitzDaily3Blocks has faces with owner cell number -1 |
for(int j = 0; j < numFiles; j++) |
if(ownerCell >= 0) |
{ | { |
vtkstd::string tempFile(directory->GetFile(j)); |
face& ownerCellFace = cellFaces[ownerCell][--nCellFaces[ownerCell]]; |
if(tempFile.find("polyMesh") != vtkstd::string::npos) |
ownerCellFace.faceIndex = i; |
{ |
ownerCellFace.neighborFace = false; |
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 |
|
} |
|
} | } |
| |
//if there is no polyMesh dir |
const int neighborCell = faceNeighbor[i]; // must be a signed int |
//set it equal to prev timestep |
if(neighborCell >= 0) |
//if no prev set to "constant" dir |
|
if(!polyMeshFound) |
|
{ | { |
if(i != 0) |
face& neighborCellFace |
{ |
= cellFaces[neighborCell][--nCellFaces[neighborCell]]; |
//set points/faces location to previous timesteps value |
neighborCellFace.faceIndex = i; |
this->PolyMeshPointsDir->value[i] = this->PolyMeshPointsDir->value[i-1]; |
neighborCellFace.neighborFace = true; |
this->PolyMeshFacesDir->value[i] = this->PolyMeshFacesDir->value[i-1]; |
|
} |
|
else |
|
{ |
|
//set points/faces to constant |
|
this->PolyMeshPointsDir->value[i] = vtkstd::string("constant"); |
|
this->PolyMeshFacesDir->value[i] = vtkstd::string("constant"); |
|
} |
|
} | } |
directory->Delete(); |
|
} | } |
| |
vtkDebugMacro(<<"Points/faces list created"); |
vtkDebugMacro(<<"Owner file read"); |
return; |
return true; |
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
// Method: vtkOpenFOAMReader::GetDataType |
// Method: vtkOpenFOAMReader::PopulatePolyMeshDirArrays |
// | // |
// Purpose: | // Purpose: |
// determines whether a variable is a volume scalar, vector or neither |
// create a Lookup Table containing the location of the points |
// for meta data |
// and faces files for each time steps mesh |
// | // |
// **************************************************************************** | // **************************************************************************** |
const char * vtkOpenFOAMReader::GetDataType(const char * pathIn, |
void vtkOpenFOAMReader::PopulatePolyMeshDirArrays() |
const char * fileNameIn) |
|
{ | { |
vtkstd::string path(pathIn); |
vtkDebugMacro(<<"Create list of points/faces file directories"); |
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; |
|
|
|
//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"; |
|
} |
|
| |
//find class entry |
//intialize size to number of timesteps |
tempStringStruct = this->GetLine(input); |
this->PolyMeshPointsDir->value.resize(this->NumberOfTimeSteps); |
temp = tempStringStruct->value; |
this->PolyMeshFacesDir->value.resize(this->NumberOfTimeSteps); |
delete tempStringStruct; |
|
while(temp.find("class") == vtkstd::string::npos && !input->eof()) |
|
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} |
|
| |
//return type |
//loop through each timestep |
if(!input->eof()) |
for(int i = 0; i < this->NumberOfTimeSteps; i++) |
{ | { |
temp.erase(temp.begin()+temp.find(";")); |
//create the path to the timestep |
//PARSE OUT CLASS TYPE |
vtkStdString polyMeshPath |
tokenizer << temp; |
= *this->PathPrefix + this->TimeNames->GetValue(i) + "/polyMesh/"; |
//while(tokenizer >> foamClass); |
vtkFoamIOobject io; |
while(!tokenizer.eof()) |
|
{ |
if(io.open(polyMeshPath + "faces") || io.open(polyMeshPath + "faces.gz")) |
tokenizer >> foamClass; |
{ |
|
io.close(); |
|
//set points/faces location to current timesteps value |
|
this->PolyMeshFacesDir->value[i] = this->TimeNames->GetValue(i); |
} | } |
//return scalar, vector, or invalid |
else |
if(foamClass =="volScalarField") |
|
{ | { |
input->close(); |
if(i != 0) |
delete input; |
{ |
return "Scalar"; |
//set points/faces location to previous timesteps value |
|
this->PolyMeshFacesDir->value[i] = this->PolyMeshFacesDir->value[i-1]; |
|
} |
|
else |
|
{ |
|
//set points/faces to constant |
|
this->PolyMeshFacesDir->value[i] = vtkStdString("constant"); |
|
} |
} | } |
else if (foamClass =="volVectorField") |
|
|
if(io.open(polyMeshPath + "points") || io.open(polyMeshPath + "points.gz")) |
{ | { |
input->close(); |
io.close(); |
delete input; |
//set points/faces location to current timesteps value |
return "Vector"; |
this->PolyMeshPointsDir->value[i] = this->TimeNames->GetValue(i); |
} | } |
else | else |
{ | { |
input->close(); |
if(i != 0) |
delete input; |
{ |
return "Invalid"; |
//set points/faces location to previous timesteps value |
|
this->PolyMeshPointsDir->value[i] |
|
= this->PolyMeshPointsDir->value[i-1]; |
|
} |
|
else |
|
{ |
|
//set points/faces to constant |
|
this->PolyMeshPointsDir->value[i] = vtkStdString("constant"); |
|
} |
} | } |
} | } |
|
vtkDebugMacro(<<"Points/faces list created"); |
//if the file format is wrong return invalid |
return; |
else |
|
{ |
|
input->close(); |
|
delete input; |
|
return "invalid"; |
|
} |
|
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
// Method: vtkOpenFOAMReader::GetInternalVariableAtTimestep |
// Method: vtkOpenFOAMReader::GetVariableAtTimestep |
// | // |
// Purpose: | // Purpose: |
// returns the values for a request variable for the internal mesh |
// returns the values for a request variable for the internal and boundary |
|
// meshes |
// | // |
// **************************************************************************** | // **************************************************************************** |
vtkDoubleArray * vtkOpenFOAMReader::GetInternalVariableAtTimestep |
bool vtkOpenFOAMReader::GetVariableAtTimestep( |
(const char * varNameIn, int timeState) |
vtkUnstructuredGrid* internalMesh, unstructuredGridVector* boundaryMesh, |
|
vtkFoamDict* boundaryDictPtr, const char* varNameIn, int timeState) |
{ | { |
vtkstd::string varName(varNameIn); |
vtkStdString varPath = *this->PathPrefix |
vtksys_ios::stringstream varPath; |
+ this->TimeNames->GetValue(timeState) + "/" + vtkStdString(varNameIn); |
varPath << this->PathPrefix->value << this->Steps[timeState] << "/" << varName; |
vtkDebugMacro(<<"Get variable: "<<varPath.c_str()); |
vtkDebugMacro(<<"Get internal variable: "<<varPath.str().c_str()); |
|
vtkDoubleArray *data = vtkDoubleArray::New(); |
|
| |
vtkstd::string temp; |
// open the file |
stdString* tempStringStruct; |
vtkFoamIOobject io; |
bool binaryWriteFormat; |
if(!io.open(varPath)) |
ifstream * input = new ifstream(varPath.str().c_str(), ios::in VTK_IOS_NOCREATE); |
|
//make sure file exists |
|
if(input->fail()) |
|
{ | { |
input->close(); |
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
delete input; |
<< io.error().str().c_str()); |
return data; |
return false; |
} | } |
| |
//determine if file is binary or ascii |
// if the variable is disabled on selection panel then skip it |
while(temp.find("format") == vtkstd::string::npos) |
if(this->CellDataArraySelection->ArrayExists(io.objectName().c_str()) |
|
&& !this->CellDataArraySelection->ArrayIsEnabled(io.objectName().c_str())) |
{ | { |
tempStringStruct = this->GetLine(input); |
return true; |
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} | } |
input->close(); |
|
| |
//reopen file in correct format |
// read the field file into dictionary |
if(temp.find("binary") != vtkstd::string::npos) |
vtkFoamDict dict; |
{ |
if(!dict.read(io)) |
#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; |
|
} |
|
else |
|
{ | { |
input->open(varPath.str().c_str(),ios::in); |
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
binaryWriteFormat = false; |
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
|
return false; |
} | } |
| |
vtkstd::string foamClass; |
if(dict.type() != vtkFoamDict::DICTIONARY) |
vtksys_ios::stringstream tokenizer; |
|
double value; |
|
|
|
//find class |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
|
|
while(temp.find("class") == vtkstd::string::npos) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"File " << io.fileName().c_str() |
temp = tempStringStruct->value; |
<< "is not valid as a field file"); |
delete tempStringStruct; |
return false; |
} | } |
temp.erase(temp.begin()+temp.find(";")); |
|
tokenizer << temp; |
// set internal values |
//while(tokenizer >> foamClass); |
vtkDoubleArray* iData; |
while(!tokenizer.eof()) |
vtkFoamEntry& iEntry = dict.lookup("internalField"); |
|
if(!iEntry.found()) |
{ | { |
tokenizer >> foamClass; |
vtkErrorMacro(<<"internalField not found in " << io.fileName().c_str()); |
|
return false; |
} | } |
temp=""; |
if(iEntry.firstValue().type() == vtkFoamEntryValue::EMPTYLIST) |
//create scalar arrays |
|
if(foamClass =="volScalarField") |
|
{ | { |
while(temp.find("internalField") == vtkstd::string::npos) |
if(this->NumCells == 0) |
{ | { |
tempStringStruct = this->GetLine(input); |
// if there's no cell there shouldn't be any boundary faces either |
temp = tempStringStruct->value; |
return true; |
delete tempStringStruct; |
|
} | } |
//nonuniform |
else |
if(!(temp.find("nonuniform") == vtkstd::string::npos)) |
|
{ | { |
//create an array |
vtkErrorMacro(<<"internalField is empty"); |
tempStringStruct = this->GetLine(input); |
return false; |
temp = tempStringStruct->value; |
} |
delete tempStringStruct; |
} |
|
|
int scalarCount; |
|
tokenizer.clear(); |
|
tokenizer << temp; |
|
tokenizer >> scalarCount; |
|
data->SetNumberOfValues(NumCells); |
|
|
|
//binary data |
|
if(binaryWriteFormat) |
|
{ |
|
//add values to array |
|
input->get(); //parenthesis |
|
for(int i = 0; i < scalarCount; i++) |
|
{ |
|
input->read((char *) &value, sizeof(double)); |
|
data->SetValue(i, value); |
|
} |
|
} |
|
| |
//ascii data |
if(io.className() == "volScalarField") |
else |
{ |
|
if(iEntry.firstValue().isUniform()) |
|
{ |
|
iData = vtkDoubleArray::New(); |
|
iData->SetNumberOfValues(this->NumCells); |
|
double num; |
|
iEntry >> num; |
|
for(int i = 0; i < this->NumCells; i++) |
{ | { |
//add values to array |
iData->SetValue(i, num); |
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); |
|
} |
|
} | } |
} | } |
|
else // nonuniform |
//uniform |
|
else if(!(temp.find("uniform") == vtkstd::string::npos)) |
|
{ | { |
//parse out the uniform value |
if(iEntry.firstValue().type() != vtkFoamEntryValue::SCALARLIST) |
vtkstd::string token; |
|
temp.erase(temp.begin()+temp.find(";")); |
|
tokenizer.clear(); |
|
tokenizer << temp; |
|
//while(tokenizer>>token); |
|
while(!tokenizer.eof()) |
|
{ | { |
tokenizer >> token; |
vtkErrorMacro(<<"internalField is not a scalarField"); |
|
return false; |
} | } |
tokenizer.clear(); |
if(iEntry.scalarList().GetSize() != this->NumCells) |
tokenizer << token; |
|
tokenizer >> value; |
|
data->SetNumberOfValues(NumCells); |
|
|
|
//create array of uniform values |
|
for(int i = 0; i < NumCells; i++) |
|
{ | { |
data->SetValue(i, value); |
vtkErrorMacro(<<"Number of cells in mesh and field don't match: " |
|
<< "mesh = " << this->NumCells << ", field = " |
|
<< iEntry.scalarList().GetSize()); |
|
return false; |
} | } |
} |
iData = (vtkDoubleArray *)iEntry.ptr(); |
|
|
//no data |
|
else |
|
{ |
|
input->close(); |
|
delete input; |
|
return data; |
|
} | } |
} | } |
|
else if(io.className() == "volVectorField") |
//create vector arrays |
|
else if(foamClass == "volVectorField") |
|
{ | { |
tempStringStruct = this->GetLine(input); |
if(iEntry.firstValue().isUniform()) |
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
while(temp.find("internalField") == vtkstd::string::npos) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
iData = vtkDoubleArray::New(); |
temp = tempStringStruct->value; |
iData->SetNumberOfComponents(3); |
delete tempStringStruct; |
iData->SetNumberOfTuples(this->NumCells); |
} |
// have to determine the type of vector |
if(!(temp.find("nonuniform") == vtkstd::string::npos)) |
if(iEntry.firstValue().type() == vtkFoamEntryValue::LABELLIST) |
{ |
|
//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) |
|
{ | { |
//add values to the array |
const vtkstd::vector<int>& ll = iEntry.labelList(); |
input->get(); //parenthesis |
if(ll.size() != 3) |
for(int i = 0; i < vectorCount; i++) |
|
{ | { |
input->read((char *) &value, sizeof(double)); |
vtkErrorMacro(<<"The uniform list isn't a vector of size 3"); |
data->InsertComponent(i, 0, value); |
iData->Delete(); |
input->read((char *) &value, sizeof(double)); |
return false; |
data->InsertComponent(i, 1, value); |
} |
input->read((char *) &value, sizeof(double)); |
double v[3]; |
data->InsertComponent(i, 2, value); |
v[0] = static_cast<double>(ll[0]); |
|
v[1] = static_cast<double>(ll[1]); |
|
v[2] = static_cast<double>(ll[2]); |
|
for(int i = 0; i < this->NumCells; i++) |
|
{ |
|
iData->SetTuple(i, v); |
} | } |
} | } |
|
else if(iEntry.firstValue().type() == vtkFoamEntryValue::SCALARLIST) |
//ascii data |
|
else |
|
{ | { |
//add values to the array |
vtkDoubleArray& sl = iEntry.scalarList(); |
tempStringStruct = this->GetLine(input); |
if(sl.GetSize() != 3) |
temp = tempStringStruct->value; |
|
delete tempStringStruct; //discard ( |
|
for(int i = 0; i < vectorCount; i++) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro( |
temp = tempStringStruct->value; |
<< "The uniform list isn't a vector of size 3 (actual size " |
delete tempStringStruct; |
<< sl.GetSize() << ")"); |
|
iData->Delete(); |
//REMOVE BRACKETS |
return false; |
temp.erase(temp.begin()+temp.find("(")); |
} |
temp.erase(temp.begin()+temp.find(")")); |
double* v = sl.GetPointer(0); |
|
for(int i = 0; i < this->NumCells; i++) |
//GRAB X,Y,&Z VALUES |
{ |
tokenizer.clear(); |
iData->SetTuple(i, v); |
tokenizer << temp; |
|
tokenizer >> value; |
|
data->InsertComponent(i, 0, value); |
|
tokenizer >> value; |
|
data->InsertComponent(i, 1, value); |
|
tokenizer >> value; |
|
data->InsertComponent(i, 2, value); |
|
} | } |
} | } |
} |
else |
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++) |
|
{ | { |
data->InsertComponent(i, 0, value1); |
vtkErrorMacro(<<"Wrong list type"); |
data->InsertComponent(i, 1, value2); |
iData->Delete(); |
data->InsertComponent(i, 2, value3); |
return false; |
} | } |
} | } |
|
else // nonuniform |
//no data |
|
else |
|
{ | { |
input->close(); |
if(iEntry.firstValue().type() != vtkFoamEntryValue::VECTORLIST) |
delete input; |
{ |
return data; |
vtkErrorMacro(<<"internalField is not a vectorField"); |
|
return false; |
|
} |
|
if(iEntry.vectorList().GetNumberOfTuples() != this->NumCells) |
|
{ |
|
vtkErrorMacro(<<"Number of cells in mesh and field don't match: " |
|
<< "mesh = " << this->NumCells << ", field = " |
|
<< iEntry.vectorList().GetNumberOfTuples()); |
|
return false; |
|
} |
|
iData = (vtkDoubleArray *)iEntry.ptr(); |
} | } |
} | } |
input->close(); |
else |
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) |
|
{ |
|
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()) |
|
{ | { |
input->close(); |
vtkErrorMacro(<<"Unsupported field class"); |
delete input; |
return false; |
return data; |
|
} | } |
| |
//determine if file is binary or ascii |
// Add field only if internal Mesh exists (skip if not selected) |
while(temp.find("format") == vtkstd::string::npos) |
// 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((iData->GetSize() > 0) |
|
&& (this->GetPatchArrayStatus(this->GetPatchArrayName(0))) |
|
&& (internalMesh != NULL)) |
{ | { |
tempStringStruct = this->GetLine(input); |
iData->SetName(io.objectName().c_str()); |
temp = tempStringStruct->value; |
internalMesh->GetCellData()->AddArray(iData); |
delete tempStringStruct; |
|
} | } |
input->close(); |
|
| |
//reopen file in correct format |
// set boundary values |
if(temp.find("binary") != vtkstd::string::npos) |
vtkFoamEntry& bEntry = dict.lookup("boundaryField"); |
{ |
vtkFoamDict& boundaryDict = *boundaryDictPtr; |
#ifdef _WIN32 |
for(size_t boundaryIndex = 0, i = 0; i < boundaryDict.size(); i++) |
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; |
|
} |
|
else |
|
{ | { |
input->open(varPath.str().c_str(),ios::in); |
vtkFoamEntry& boundaryEntryI = boundaryDict.entry(i); |
binaryWriteFormat = false; |
int nFaces; |
} |
boundaryEntryI.dictionary().lookup("nFaces") >> nFaces; |
|
|
vtkstd::string foamClass; |
|
vtksys_ios::stringstream tokenizer; |
|
double value; |
|
| |
//find class |
// skip empty boundary |
tempStringStruct = this->GetLine(input); |
if(nFaces == 0) |
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
while(temp.find("class") == vtkstd::string::npos) |
|
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} |
|
temp.erase(temp.begin()+temp.find(";")); |
|
tokenizer << temp; |
|
//while(tokenizer >> foamClass); |
|
while(!tokenizer.eof()) |
|
{ |
|
tokenizer >> foamClass; |
|
} |
|
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); |
continue; |
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} | } |
if(input->eof()) |
|
|
const vtkStdString& boundaryNameI = boundaryEntryI.keyword(); |
|
|
|
// Add field only if given boundary is selected for display |
|
if(!this->GetPatchArrayStatus(boundaryNameI.c_str())) |
{ | { |
input->close(); |
continue; |
delete input; |
|
return data; |
|
} | } |
//find value entry |
|
while(temp.find("}") == vtkstd::string::npos && |
vtkFoamEntry& bEntryI = bEntry.dictionary().lookup(boundaryNameI); |
temp.find("value ") == vtkstd::string::npos) |
if(!bEntryI.found()) |
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<< "boundaryField " << boundaryNameI.c_str() |
temp = tempStringStruct->value; |
<< " not found in object " << varNameIn << " at time = " |
delete tempStringStruct; //find value |
<< this->TimeNames->GetValue(timeState).c_str()); |
|
iData->Delete(); |
|
return false; |
} | } |
| |
//nonuniform |
if(bEntryI.firstValue().type() != vtkFoamEntryValue::DICTIONARY) |
if(!(temp.find("nonuniform") == vtkstd::string::npos)) |
|
{ | { |
|
vtkErrorMacro(<< "Type of boundaryField " << boundaryNameI.c_str() |
|
<< " is not a subdictionary in object " << varNameIn << " at time = " |
|
<< this->TimeNames->GetValue(timeState).c_str()); |
|
iData->Delete(); |
|
return false; |
|
} |
| |
//binary data |
vtkDoubleArray* vData; |
if(binaryWriteFormat) |
|
{ |
|
//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 |
vtkFoamEntry& vEntry = bEntryI.dictionary().lookup("value"); |
input->get(); //parenthesis |
// uniformValue is for Hrv's dev version |
for(int i = 0; i < scalarCount; i++) |
vtkFoamEntry& uvEntry = bEntryI.dictionary().lookup("uniformValue"); |
|
|
|
if(vEntry.found() || uvEntry.found()) // the boundary has a value entry |
|
{ |
|
if(io.className() == "volScalarField") |
|
{ |
|
if((vEntry.found() && vEntry.firstValue().isUniform()) |
|
|| uvEntry.found()) |
|
{ |
|
vData = vtkDoubleArray::New(); |
|
vData->SetNumberOfValues(nFaces); |
|
double num; |
|
if(vEntry.found()) // "value" entry has the priority |
|
{ |
|
vEntry >> num; |
|
} |
|
else |
|
{ |
|
uvEntry >> num; |
|
} |
|
for(int j = 0; j < nFaces; j++) |
|
{ |
|
vData->SetValue(j, num); |
|
} |
|
} |
|
else // nonuniform |
{ | { |
input->read((char *) &value, sizeof(double)); |
if(vEntry.firstValue().type() != vtkFoamEntryValue::SCALARLIST) |
data->SetValue(i, value); |
{ |
|
vtkErrorMacro(<<"boundaryField " << boundaryNameI.c_str() |
|
<< " is not a scalarField"); |
|
iData->Delete(); |
|
return false; |
|
} |
|
if(vEntry.scalarList().GetSize() != nFaces) |
|
{ |
|
vtkErrorMacro(<<"Number of faces in field and bondary don't match"); |
|
iData->Delete(); |
|
return false; |
|
} |
|
vData = (vtkDoubleArray *)vEntry.ptr(); |
} | } |
} | } |
|
else if(io.className() == "volVectorField") |
//ascii data |
|
else |
|
{ | { |
temp.erase(temp.begin(), temp.begin()+temp.find(">")+1); |
if((vEntry.found() && vEntry.firstValue().isUniform()) |
//ascii data with 10 or less values are on the same line |
|| uvEntry.found()) |
//>10 |
{ |
if(temp == vtkstd::string(" ")) |
vData = vtkDoubleArray::New(); |
{ |
vData->SetNumberOfComponents(3); |
//create an array of data |
vData->SetNumberOfTuples(nFaces); |
tempStringStruct = this->GetLine(input); |
// the "value" entry has the priority |
temp = tempStringStruct->value; |
vtkFoamEntry& vvEntry = vEntry.found() ? vEntry : uvEntry; |
delete tempStringStruct; |
// have to determine the type of vector |
|
if(vvEntry.firstValue().type() == vtkFoamEntryValue::LABELLIST) |
int scalarCount; |
{ |
tokenizer.clear(); |
const vtkstd::vector<int>& ll = vvEntry.labelList(); |
tokenizer << temp; |
if(ll.size() != 3) |
tokenizer >> scalarCount; |
{ |
data->SetNumberOfValues(scalarCount); |
vtkErrorMacro(<<"The uniform list isn't a vector of size 3"); |
tempStringStruct = this->GetLine(input); |
iData->Delete(); |
temp = tempStringStruct->value; |
vData->Delete(); |
delete tempStringStruct; //discard ( |
return false; |
|
} |
for(int i = 0; i < scalarCount; i++) |
double v[3]; |
{ |
v[0] = static_cast<double>(ll[0]); |
tempStringStruct = this->GetLine(input); |
v[1] = static_cast<double>(ll[1]); |
temp = tempStringStruct->value; |
v[2] = static_cast<double>(ll[2]); |
delete tempStringStruct; |
for(int j = 0; j < nFaces; j++) |
|
{ |
tokenizer.clear(); |
vData->SetTuple(j, v); |
tokenizer << temp; |
} |
tokenizer >> value; |
} |
data->SetValue(i, value); |
else if(vvEntry.firstValue().type() == vtkFoamEntryValue::SCALARLIST) |
|
{ |
|
vtkDoubleArray& sl = vvEntry.scalarList(); |
|
if(sl.GetSize() != 3) |
|
{ |
|
vtkErrorMacro(<< "The uniform value list in patch " |
|
<< boundaryNameI.c_str() << " of file " |
|
<< io.fileName().c_str() |
|
<< " isn't a vector of size 3 (actual size " << sl.GetSize() |
|
<< ")"); |
|
iData->Delete(); |
|
vData->Delete(); |
|
return false; |
|
} |
|
double* v = sl.GetPointer(0); |
|
for(int j = 0; j < nFaces; j++) |
|
{ |
|
vData->SetTuple(j, v); |
|
} |
|
} |
|
else |
|
{ |
|
vtkErrorMacro(<<"Wrong list type"); |
|
iData->Delete(); |
|
vData->Delete(); |
|
return false; |
} | } |
} | } |
//=<10 |
else // nonuniform |
else |
|
{ | { |
//create an array with data |
if(vEntry.firstValue().type() != vtkFoamEntryValue::VECTORLIST) |
int scalarCount; |
{ |
tokenizer.clear(); |
vtkErrorMacro(<<"boundaryField " << boundaryNameI.c_str() |
tokenizer << temp; |
<< " is not a vectorField"); |
tokenizer >> scalarCount; |
iData->Delete(); |
data->SetNumberOfValues(scalarCount); |
return false; |
temp.erase(temp.begin(), temp.begin()+temp.find("(")+1); |
} |
temp.erase(temp.begin()+temp.find(")"), temp.end()); |
if(vEntry.vectorList().GetNumberOfTuples() != nFaces) |
|
|
tokenizer.clear(); |
|
tokenizer << temp; |
|
for(int i = 0; i < scalarCount; i++) |
|
{ | { |
tokenizer >> value; |
vtkErrorMacro(<<"Number of faces in field and bondary don't match"); |
data->SetValue(i, value); |
iData->Delete(); |
|
return false; |
} | } |
|
vData = (vtkDoubleArray *)vEntry.ptr(); |
} | } |
} | } |
} |
else // other field types |
|
|
//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 |
|
{ |
|
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); |
vtkErrorMacro(<<"Unsupported field class"); |
data->SetValue(i, internalData->GetComponent(cellId, 0)); |
iData->Delete(); |
|
return false; |
} | } |
input->close(); |
|
delete input; |
|
return data; |
|
} |
|
} |
|
//CREATE VECTOR ARRAYS |
|
else if(foamClass == "volVectorField") |
|
{ |
|
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; |
|
} | } |
while(temp.find("}") == vtkstd::string::npos && |
else // doesn't have a value entry |
temp.find("value ") == vtkstd::string::npos) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
int startFace; |
temp = tempStringStruct->value; |
boundaryEntryI.dictionary().lookup("startFace") >> startFace; |
delete tempStringStruct; //find value |
vData = vtkDoubleArray::New(); |
} |
|
//nonuniform |
|
if(!(temp.find("nonuniform") == vtkstd::string::npos)) |
|
{ |
|
//create an array |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
| |
int vectorCount; |
if(io.className() == "volScalarField") |
tokenizer.clear(); |
|
tokenizer << temp; |
|
tokenizer >> vectorCount; |
|
data->SetNumberOfComponents(3); |
|
|
|
//binary data |
|
if(binaryWriteFormat) |
|
{ | { |
//insert values into the array |
vData->SetNumberOfValues(nFaces); |
input->get(); //parenthesis |
for(int j = 0; j < nFaces; j++) |
for(int i = 0; i < vectorCount; i++) |
|
{ | { |
input->read((char *) &value, sizeof(double)); |
const int cellId = this->FaceOwner->GetValue(startFace + j); |
data->InsertComponent(i, 0, value); |
vData->SetValue(j, iData->GetValue(cellId)); |
input->read((char *) &value, sizeof(double)); |
|
data->InsertComponent(i, 1, value); |
|
input->read((char *) &value, sizeof(double)); |
|
data->InsertComponent(i, 2, value); |
|
} | } |
} | } |
|
else if(io.className() == "volVectorField") |
//ascii data |
{ |
else |
vData->SetNumberOfComponents(3); |
|
vData->SetNumberOfTuples(nFaces); |
|
for(int j = 0; j < nFaces; j++) |
{ | { |
//insert values into the array |
const int cellId = this->FaceOwner->GetValue(startFace + j); |
tempStringStruct = this->GetLine(input); |
// in this case GetTuple should be thread-safe accoding to |
temp = tempStringStruct->value; |
// the FAQ on ParaView Wiki |
delete tempStringStruct; //discard ( |
vData->SetTuple(j, iData->GetTuple(cellId)); |
for(int i = 0; i < vectorCount; i++) |
|
{ |
|
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); |
|
} |
|
} | } |
} | } |
|
else |
//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; |
|
|
|
data->SetNumberOfComponents(3); |
|
for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++) |
|
{ | { |
data->InsertComponent(i, 0, value1); |
vtkErrorMacro(<<"Unsupported field class"); |
data->InsertComponent(i, 1, value2); |
iData->Delete(); |
data->InsertComponent(i, 2, value3); |
vData->Delete(); |
|
return false; |
} | } |
} | } |
|
if(vData->GetSize() > 0) |
//no data |
|
else |
|
{ | { |
int cellId; |
vData->SetName(io.objectName().c_str()); |
vtkDataArray * internalData = internalMesh->GetCellData()-> |
boundaryMesh->value[boundaryIndex]->GetCellData() |
GetArray(varName.c_str()); |
->AddArray(vData); |
data->SetNumberOfComponents(3); |
|
for(int i = 0; i < this->SizeOfBoundary->value[boundaryIndex]; i++) |
|
{ |
|
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)); |
|
} |
|
input->close(); |
|
delete input; |
|
return data; |
|
} | } |
|
vData->Delete(); |
|
boundaryIndex++; |
} | } |
input->close(); |
|
delete input; |
iData->Delete(); |
vtkDebugMacro(<<"Boundary data read"); |
vtkDebugMacro(<<"Internal variable data read"); |
return data; |
return true; |
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
// Method: vtkOpenFOAMReader::GatherBlocks | // Method: vtkOpenFOAMReader::GatherBlocks |
// | // |
// Purpose: | // Purpose: |
// returns a vector of block names for a specified domain |
// returns a dictionary of block names for a specified domain |
// | // |
// **************************************************************************** | // **************************************************************************** |
stringVector * vtkOpenFOAMReader::GatherBlocks(const char * typeIn, |
vtkOpenFOAMReader::vtkFoamDict* vtkOpenFOAMReader::GatherBlocks( |
int timeState) |
const char* typeIn, int timeState, bool mustRead) |
{ | { |
vtkstd::string type(typeIn); |
vtkStdString type(typeIn); |
vtkstd::string blockPath = this->PathPrefix->value + |
vtkStdString blockPath = *this->PathPrefix |
this->PolyMeshFacesDir->value[timeState] + |
+ this->PolyMeshFacesDir->value[timeState] + "/polyMesh/" + type; |
"/polyMesh/"+type; |
|
vtkstd::vector< vtkstd::string > blocks; |
vtkFoamIOobject io; |
stringVector *returnValue = new stringVector; |
if(!(io.open(blockPath) || io.open(blockPath + ".gz"))) |
vtkDebugMacro(<<"Get blocks: "<<blockPath.c_str()); |
{ |
|
if(mustRead) |
ifstream * input = new ifstream(blockPath.c_str(), ios::in VTK_IOS_NOCREATE); |
{ |
//if there is no file return a null vector |
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
if(input->fail()) |
<< io.error().str().c_str()); |
{ |
} |
input->close(); |
return NULL; |
delete input; |
} |
returnValue->value = blocks; |
|
return returnValue; |
vtkFoamDict* dictPtr = new vtkFoamDict; |
} |
vtkFoamDict& dict = *dictPtr; |
|
if(!dict.read(io)) |
vtkstd::string temp; |
{ |
stdString* tempStringStruct; |
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
vtkstd::string token; |
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
vtksys_ios::stringstream tokenizer; |
delete dictPtr; |
vtkstd::string tempName; |
return NULL; |
|
} |
//find end of header |
if(dict.type() != vtkFoamDict::DICTIONARY) |
//while(temp.compare(0,4,"// *",0,4)!=0) |
{ |
while (strcmp(temp.substr(0,4).c_str(), "// *")) |
vtkErrorMacro(<<"The file type of " << io.fileName().c_str() |
{ |
<< " is not a dictionary"); |
tempStringStruct = this->GetLine(input); |
delete dictPtr; |
temp = tempStringStruct->value; |
return NULL; |
delete tempStringStruct; |
} |
} |
return dictPtr; |
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; |
|
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
|
|
// returns a requested boundary mesh | // returns a requested boundary mesh |
// | // |
// **************************************************************************** | // **************************************************************************** |
vtkUnstructuredGrid * vtkOpenFOAMReader::GetBoundaryMesh(int timeState, |
unstructuredGridVector* vtkOpenFOAMReader::GetBoundaryMesh( |
int boundaryIndex) |
vtkFoamDict* boundaryDictPtr, intVectorVector* facesPoints, |
|
vtkPoints* points) |
{ | { |
vtkUnstructuredGrid * boundaryMesh = vtkUnstructuredGrid::New(); |
vtkFoamDict& boundaryDict = *boundaryDictPtr; |
vtkstd::string boundaryPath = this->PathPrefix->value + |
unstructuredGridVector* boundaryMesh = new unstructuredGridVector; |
this->PolyMeshFacesDir->value[timeState] + |
|
"/polyMesh/boundary"; |
|
vtkDebugMacro(<<"Create boundary mesh: "<<boundaryPath.c_str()); |
|
| |
int nFaces; |
for(size_t boundaryIndex = 0; boundaryIndex < boundaryDict.size(); |
|
boundaryIndex++) |
ifstream * input = new ifstream(boundaryPath.c_str(), ios::in VTK_IOS_NOCREATE); |
|
//return a Null object |
|
if(input->fail()) |
|
{ | { |
input->close(); |
vtkFoamDict& dict = boundaryDict.entry(boundaryIndex).dictionary(); |
delete input; |
|
return boundaryMesh; |
|
} |
|
| |
vtkstd::string temp; |
int nFaces; |
stdString* tempStringStruct; |
vtkFoamEntry& nFacesEntry = dict.lookup("nFaces"); |
vtkstd::string token; |
vtkFoamEntry& startFaceEntry = dict.lookup("startFace"); |
vtksys_ios::stringstream tokenizer; |
if(!nFacesEntry.found() || !startFaceEntry.found()) |
|
{ |
|
vtkWarningMacro( |
|
<< "Entry nFaces or startFace not found in boundary entry " |
|
<< boundaryDict.entry(boundaryIndex).keyword().c_str()); |
|
for(size_t i = 0; i < boundaryMesh->value.size(); i++) |
|
{ |
|
boundaryMesh->value[i]->Delete(); |
|
} |
|
delete boundaryMesh; |
|
return NULL; |
|
} |
|
nFacesEntry >> nFaces; |
| |
//find desired mesh entry |
// skip empty boundary |
while(temp.find(this->BoundaryNames->value[boundaryIndex]) == |
if(nFaces == 0) |
vtkstd::string::npos) |
{ |
{ |
continue; |
tempStringStruct = this->GetLine(input); |
} |
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} |
|
| |
//get nFaces |
// Create a boundary mesh only if selected in the list for display |
while(temp.find("nFaces") == vtkstd::string::npos) |
vtkFoamEntry& boundaryEntryI = boundaryDict.entry(boundaryIndex); |
{ |
const vtkStdString& boundaryNameI = boundaryEntryI.keyword(); |
tempStringStruct = this->GetLine(input); |
if(!this->GetPatchArrayStatus(boundaryNameI.c_str())) |
temp = tempStringStruct->value; |
{ |
delete tempStringStruct; |
continue; |
} |
} |
temp.erase(temp.begin()+temp.find(";")); //remove ; |
|
tokenizer << temp; |
|
//while(tokenizer >> token); |
|
while(!tokenizer.eof()) |
|
{ |
|
tokenizer >> token; |
|
} |
|
tokenizer.clear(); |
|
tokenizer << token; |
|
tokenizer >> nFaces; |
|
| |
//get startface |
int startFace; |
tempStringStruct = this->GetLine(input); |
startFaceEntry >> startFace; |
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
| |
//look for "startFaces" |
int endFace = startFace + nFaces; |
while(temp.find("startFace") == vtkstd::string::npos) |
|
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
} |
|
temp.erase(temp.begin()+temp.find(";")); //remove ; |
|
tokenizer.clear(); |
|
tokenizer << temp; |
|
//while(tokenizer >> token); |
|
while(!tokenizer.eof()) |
|
{ |
|
tokenizer >> token; |
|
} |
|
tokenizer.clear(); |
|
tokenizer << token; |
|
tokenizer >> this->StartFace; |
|
| |
//Create the mesh |
//Create the mesh |
int j, k; |
boundaryMesh->value.push_back(vtkUnstructuredGrid::New()); |
vtkTriangle * triangle; |
vtkUnstructuredGrid& bm = *boundaryMesh->value.back(); |
vtkQuad * quad; |
bm.Allocate(nFaces); |
vtkPolygon * polygon; |
|
int endFace = this->StartFace + nFaces; |
|
//loop through each face |
|
for(j = this->StartFace; j < endFace; j++) |
|
{ |
|
| |
//triangle |
// aloocate array for converting int vector to vtkIdType vector: |
if(this->FacePoints->value[j].size() == 3) |
// workaround for 64bit machines |
|
int maxNFacePoints = 0; |
|
for(int j = startFace; j < endFace; j++) |
{ | { |
triangle = vtkTriangle::New(); |
const int nFacePoints = facesPoints->value[j].size(); |
for(k = 0; k < 3; k++) |
if(nFacePoints > maxNFacePoints) |
{ | { |
triangle->GetPointIds()->SetId(k, this->FacePoints->value[j][k]); |
maxNFacePoints = nFacePoints; |
} | } |
boundaryMesh->InsertNextCell(triangle->GetCellType(), |
|
triangle->GetPointIds()); |
|
triangle->Delete(); |
|
} | } |
|
vtkIdType* facePointsVtkId = new vtkIdType[maxNFacePoints]; |
| |
//quad |
//loop through each face |
else if(this->FacePoints->value[j].size() == 4) |
for(int j = startFace; j < endFace; j++) |
{ | { |
quad = vtkQuad::New(); |
vtkstd::vector<int>& facePoints = facesPoints->value[j]; |
for(k = 0; k < 4; k++) |
size_t nFacePoints = facePoints.size(); |
|
|
|
for(size_t k = 0; k < nFacePoints; k++) |
{ | { |
quad->GetPointIds()->SetId(k, this->FacePoints->value[j][k]); |
facePointsVtkId[k] = facePoints[k]; |
} | } |
boundaryMesh->InsertNextCell(quad->GetCellType(), |
|
quad->GetPointIds()); |
|
quad->Delete(); |
|
} |
|
| |
//polygon |
//triangle |
else |
if(nFacePoints == 3) |
{ |
{ |
polygon = vtkPolygon::New(); |
bm.InsertNextCell(VTK_TRIANGLE, 3, facePointsVtkId); |
for(k = 0; k < (int)this->FacePoints->value[j].size(); k++) |
} |
|
// quad |
|
else if(nFacePoints == 4) |
{ | { |
polygon->GetPointIds()->InsertId(k, this->FacePoints->value[j][k]); |
bm.InsertNextCell(VTK_QUAD, 4, facePointsVtkId); |
|
} |
|
//polygon |
|
else |
|
{ |
|
bm.InsertNextCell(VTK_POLYGON, nFacePoints, |
|
facePointsVtkId); |
} | } |
boundaryMesh->InsertNextCell(polygon->GetCellType(), |
|
polygon->GetPointIds()); |
|
polygon->Delete(); |
|
} | } |
} |
delete [] facePointsVtkId; |
| |
//set points for boundary |
//set points for boundary |
boundaryMesh->SetPoints(this->Points); |
bm.SetPoints(points); |
//add size of mesh |
} |
this->SizeOfBoundary->value.push_back(boundaryMesh->GetNumberOfCells()); |
|
input->close(); |
|
delete input; |
|
vtkDebugMacro(<<"Boundary mesh created"); | vtkDebugMacro(<<"Boundary mesh created"); |
return boundaryMesh; | return boundaryMesh; |
} | } |
|
|
// returns a requested point zone mesh | // returns a requested point zone mesh |
// | // |
// **************************************************************************** | // **************************************************************************** |
vtkUnstructuredGrid * vtkOpenFOAMReader::GetPointZoneMesh(int timeState, |
bool vtkOpenFOAMReader::GetPointZoneMesh(unstructuredGridVector* pointZoneMesh, |
int pointZoneIndex) |
vtkPoints* points, int timeState) |
{ | { |
vtkUnstructuredGrid * pointZoneMesh = vtkUnstructuredGrid::New(); |
vtkDebugMacro(<<"Create point zone mesh"); |
vtkstd::string pointZonesPath = this->PathPrefix->value[timeState]+ |
|
"/polyMesh/pointZones"; |
|
vtkDebugMacro(<<"Create point zone mesh: "<<pointZonesPath.c_str()); |
|
| |
vtkstd::string temp; |
vtkFoamDict* pointZoneDictPtr |
stdString* tempStringStruct; |
= this->GatherBlocks("pointZones", timeState, false); |
bool binaryWriteFormat; |
|
ifstream * input = new ifstream(pointZonesPath.c_str(), ios::in VTK_IOS_NOCREATE); |
|
//make sure file exists |
|
if(input->fail()) |
|
{ |
|
input->close(); |
|
delete input; |
|
return pointZoneMesh; |
|
} |
|
| |
//determine if file is binary or ascii |
if(pointZoneDictPtr == NULL) |
while(temp.find("format") == vtkstd::string::npos) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
// not an error |
temp = tempStringStruct->value; |
return true; |
delete tempStringStruct; |
|
} | } |
input->close(); |
|
| |
//reopen file in correct format |
vtkFoamDict& pointZoneDict = *pointZoneDictPtr; |
if(temp.find("binary") != vtkstd::string::npos) |
size_t nPointZones = pointZoneDict.size(); |
{ |
|
#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; |
|
} |
|
else |
|
{ |
|
input->open(pointZonesPath.c_str(),ios::in); |
|
binaryWriteFormat = false; |
|
} |
|
| |
vtkstd::string token; |
for(size_t i = 0; i < nPointZones; i++) |
vtksys_ios::stringstream tokenizer; |
{ |
vtkVertex * pointCell; |
// look up point labels |
int tempElement; |
vtkFoamDict& dict = pointZoneDict.entry(i).dictionary(); |
vtkstd::vector< vtkstd::vector < int > > tempElementZones; |
vtkFoamEntry& pointLabelsEntry = dict.lookup("pointLabels"); |
int numElement; |
if(!pointLabelsEntry.found()) |
|
|
//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(); |
vtkErrorMacro(<<"pointLabels not found in pointZones"); |
delete input; |
return false; |
return NULL; |
|
} | } |
|
// skip if the list is empty |
//binary data |
if(pointLabelsEntry.firstValue().type() == vtkFoamEntryValue::EMPTYLIST) |
if(binaryWriteFormat) |
|
{ | { |
input->get(); //parenthesis |
continue; |
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(); |
|
} |
|
} | } |
|
if(pointLabelsEntry.firstValue().type() != vtkFoamEntryValue::LABELLIST) |
//ascii data |
|
else |
|
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"pointLabels not of type labelList: type = " |
temp = tempStringStruct->value; |
<< pointLabelsEntry.firstValue().type()); |
delete tempStringStruct;//THROW OUT ( |
return false; |
|
} |
| |
//GET EACH ELEMENT & ADD TO VECTOR |
const vtkstd::vector<int>& labels = pointLabelsEntry.labelList(); |
for(int j = 0; j < numElement; j++) |
|
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
| |
tokenizer.clear(); |
// allocate new grid: we do not use resize() beforehand since it |
tokenizer << temp; |
// could lead to undefined pointer if we return by error |
tokenizer >> tempElement; |
pointZoneMesh->value.push_back(vtkUnstructuredGrid::New()); |
pointCell = vtkVertex::New(); |
vtkUnstructuredGrid& pzm = *pointZoneMesh->value.back(); |
pointCell->GetPointIds()->SetId(0,tempElement); |
|
pointZoneMesh->InsertNextCell(pointCell->GetCellType(), |
|
pointCell->GetPointIds()); |
|
pointCell->Delete(); |
|
} |
|
} |
|
} |
|
| |
//there is no entry |
// set pointZone size |
else |
size_t nPoints = labels.size(); |
{ |
pzm.Allocate(nPoints); |
input->close(); |
|
delete input; |
// insert points |
return NULL; |
for(size_t j = 0; j < nPoints; j++) |
|
{ |
|
vtkIdType pointLabel = labels[j]; |
|
pzm.InsertNextCell(VTK_VERTEX, 1, &pointLabel); |
|
} |
|
pzm.SetPoints(points); |
} | } |
//set point zone points |
|
pointZoneMesh->SetPoints(Points); |
delete pointZoneDictPtr; |
input->close(); |
|
delete input; |
|
vtkDebugMacro(<<"Point zone mesh created"); | vtkDebugMacro(<<"Point zone mesh created"); |
return pointZoneMesh; |
return true; |
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
|
|
// returns a requested face zone mesh | // returns a requested face zone mesh |
// | // |
// **************************************************************************** | // **************************************************************************** |
vtkUnstructuredGrid * vtkOpenFOAMReader::GetFaceZoneMesh(int timeState, |
bool vtkOpenFOAMReader::GetFaceZoneMesh( |
int faceZoneIndex) |
unstructuredGridVector* faceZoneMesh, intVectorVector* facesPoints, |
|
vtkPoints* points, int timeState) |
{ | { |
vtkUnstructuredGrid * faceZoneMesh = vtkUnstructuredGrid::New(); |
vtkDebugMacro(<<"Create face zone mesh"); |
vtkstd::string faceZonesPath = this->PathPrefix->value + |
|
this->PolyMeshFacesDir->value[timeState] + |
|
"/polyMesh/faceZones"; |
|
vtkDebugMacro(<<"Create face zone mesh: "<<faceZonesPath.c_str()); |
|
|
|
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()) |
|
{ |
|
input->close(); |
|
delete input; |
|
return faceZoneMesh; |
|
} |
|
|
|
//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(faceZonesPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); |
|
#else |
|
input->open(faceZonesPath.c_str(), ios::in); |
|
#endif |
|
binaryWriteFormat = true; |
|
} |
|
else |
|
{ |
|
input->open(faceZonesPath.c_str(),ios::in); |
|
binaryWriteFormat = false; |
|
} |
|
| |
vtkstd::string token; |
vtkFoamDict* faceZoneDictPtr |
vtksys_ios::stringstream tokenizer; |
= this->GatherBlocks("faceZones", timeState, false); |
vtkstd::vector< int > faceZone; |
|
int tempElement; |
|
vtkstd::vector< vtkstd::vector < int > > tempElementZones; |
|
int numElement; |
|
| |
//find desired mesh entry |
if(faceZoneDictPtr == NULL) |
while(temp.find(this->FaceZoneNames->value[faceZoneIndex]) == |
|
vtkstd::string::npos) |
|
{ | { |
tempStringStruct = this->GetLine(input); |
// not an error |
temp = tempStringStruct->value; |
return true; |
delete tempStringStruct; |
|
} | } |
| |
tempStringStruct = this->GetLine(input); |
vtkFoamDict& faceZoneDict = *faceZoneDictPtr; |
temp = tempStringStruct->value; |
size_t nFaceZones = faceZoneDict.size(); |
delete tempStringStruct;//throw out { |
|
| |
tempStringStruct = this->GetLine(input); |
for(size_t i = 0; i < nFaceZones; i++) |
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 values or flipmap |
|
|
|
if(temp.find("flipMap") == vtkstd::string::npos) |
|
{ | { |
//number of elements |
// look up face labels |
tokenizer << temp; |
vtkFoamDict& dict = faceZoneDict.entry(i).dictionary(); |
tokenizer >> numElement; |
vtkFoamEntry& faceLabelsEntry = dict.lookup("faceLabels"); |
if(numElement == 0) |
if(!faceLabelsEntry.found()) |
{ | { |
input->close(); |
delete faceZoneDictPtr; |
delete input; |
vtkErrorMacro(<<"faceLabels not found in faceZones"); |
return NULL; |
return false; |
} | } |
|
// skip if the list is empty |
//binary |
if(faceLabelsEntry.firstValue().type() == vtkFoamEntryValue::EMPTYLIST) |
if(binaryWriteFormat) |
|
{ | { |
input->get(); //parenthesis |
continue; |
for(int j = 0; j < numElement; j++) |
|
{ |
|
input->read((char *) &tempElement, sizeof(int)); |
|
faceZone.push_back(tempElement); |
|
} |
|
} | } |
|
if(faceLabelsEntry.firstValue().type() != vtkFoamEntryValue::LABELLIST) |
//ascii |
|
else |
|
{ | { |
//THROW OUT ( |
delete faceZoneDictPtr; |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"faceLabels not of type labelList"); |
temp = tempStringStruct->value; |
return false; |
delete tempStringStruct; |
|
|
|
//get each element & add to vector |
|
for(int j = 0; j < numElement; j++) |
|
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
|
|
tokenizer.clear(); |
|
tokenizer << temp; |
|
tokenizer >> tempElement; |
|
faceZone.push_back(tempElement); |
|
} |
|
} | } |
} |
|
| |
//Create the mesh |
const vtkstd::vector<int>& labels = faceLabelsEntry.labelList(); |
int k; |
|
vtkTriangle * triangle; |
|
vtkQuad * quad; |
|
vtkPolygon * polygon; |
|
| |
//LOOP THROUGH EACH FACE |
// allocate new grid: we do not use resize() beforehand since it |
for(int j = 0; j < (int)faceZone.size(); j++) |
// could lead to undefined pointer if we return by error |
{ |
faceZoneMesh->value.push_back(vtkUnstructuredGrid::New()); |
|
vtkUnstructuredGrid& fzm = *faceZoneMesh->value.back(); |
|
|
|
// set faceZone size |
|
size_t nFaces = labels.size(); |
|
fzm.Allocate(nFaces); |
| |
//Triangular Face |
// aloocate array for converting int vector to vtkIdType vector: |
if(this->FacePoints->value[faceZone[j]].size() == 3) |
// workaround for 64bit machines |
|
int maxNFacePoints = 0; |
|
for(size_t j = 0; j < nFaces; j++) |
{ | { |
triangle = vtkTriangle::New(); |
const int nFacePoints = facesPoints->value[labels[j]].size(); |
for(k = 0; k < 3; k++) |
if(nFacePoints > maxNFacePoints) |
{ | { |
triangle->GetPointIds()->SetId(k, this->FacePoints->value[ |
maxNFacePoints = nFacePoints; |
faceZone[j]][k]); |
|
} | } |
faceZoneMesh->InsertNextCell(triangle->GetCellType(), |
|
triangle->GetPointIds()); |
|
triangle->Delete(); |
|
} | } |
|
vtkIdType* facePointsVtkId = new vtkIdType[maxNFacePoints]; |
| |
//Quadraic Face |
// insert faces |
else if(this->FacePoints->value[faceZone[j]].size() == 4) |
for(size_t j = 0; j < nFaces; j++) |
{ | { |
quad = vtkQuad::New(); |
vtkstd::vector<int>& facePoints = facesPoints->value[labels[j]]; |
for(k = 0; k < 4; k++) |
size_t nFacePoints = facePoints.size(); |
|
|
|
for(size_t k = 0; k < nFacePoints; k++) |
{ | { |
quad->GetPointIds()->SetId(k, |
facePointsVtkId[k] = facePoints[k]; |
this->FacePoints->value[faceZone[j]][k]); |
|
} | } |
faceZoneMesh->InsertNextCell(quad->GetCellType(), |
|
quad->GetPointIds()); |
|
quad->Delete(); |
|
} |
|
| |
//Polygonal Face |
//triangle |
else |
if(nFacePoints == 3) |
{ |
{ |
polygon = vtkPolygon::New(); |
fzm.InsertNextCell(VTK_TRIANGLE, 3, facePointsVtkId); |
for(k = 0; k < (int)this->FacePoints->value[faceZone[j]].size(); k++) |
} |
|
// quad |
|
else if(nFacePoints == 4) |
|
{ |
|
fzm.InsertNextCell(VTK_QUAD, 4, facePointsVtkId); |
|
} |
|
//polygon |
|
else |
{ | { |
polygon->GetPointIds()->InsertId(k, this->FacePoints->value[ |
fzm.InsertNextCell(VTK_POLYGON, nFacePoints, |
faceZone[j]][k]); |
facePointsVtkId); |
} | } |
faceZoneMesh->InsertNextCell(polygon->GetCellType(), |
|
polygon->GetPointIds()); |
|
polygon->Delete(); |
|
} | } |
|
|
|
delete [] facePointsVtkId; |
|
fzm.SetPoints(points); |
} | } |
| |
//set the face zone points |
delete faceZoneDictPtr; |
faceZoneMesh->SetPoints(this->Points); |
|
input->close(); |
|
delete input; |
|
vtkDebugMacro(<<"Face zone mesh created"); | vtkDebugMacro(<<"Face zone mesh created"); |
return faceZoneMesh; |
return true; |
} | } |
| |
// **************************************************************************** | // **************************************************************************** |
|
|
// returns a requested cell zone mesh | // returns a requested cell zone mesh |
// | // |
// **************************************************************************** | // **************************************************************************** |
vtkUnstructuredGrid * vtkOpenFOAMReader::GetCellZoneMesh(int timeState, |
bool vtkOpenFOAMReader::GetCellZoneMesh( |
int cellZoneIndex) |
unstructuredGridVector* cellZoneMesh, faceVectorVector* facesOfCell, |
|
intVectorVector* facesPoints, vtkPoints* points, int timeState) |
{ | { |
vtkUnstructuredGrid * cellZoneMesh = vtkUnstructuredGrid::New(); |
vtkDebugMacro(<<"Create cell zone mesh"); |
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()) |
|
{ |
|
input->close(); |
|
delete input; |
|
return cellZoneMesh; |
|
} |
|
|
|
//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 |
vtkFoamDict* cellZoneDictPtr |
if(temp.find("binary") != vtkstd::string::npos) |
= this->GatherBlocks("cellZones", timeState, false); |
|
|
|
if(cellZoneDictPtr == NULL) |
{ | { |
#ifdef _WIN32 |
// not an error |
input->open(cellZonesPath.c_str(), ios::binary | ios::in VTK_IOS_NOCREATE); |
return true; |
#else |
|
input->open(cellZonesPath.c_str(), ios::in VTK_IOS_NOCREATE); |
|
#endif |
|
binaryWriteFormat = true; |
|
} | } |
else |
|
|
vtkFoamDict& cellZoneDict = *cellZoneDictPtr; |
|
size_t nCellZones = cellZoneDict.size(); |
|
|
|
for(size_t i = 0; i < nCellZones; i++) |
{ | { |
input->open(cellZonesPath.c_str(),ios::in); |
// look up cell labels |
binaryWriteFormat = false; |
vtkFoamDict& dict = cellZoneDict.entry(i).dictionary(); |
|
vtkFoamEntry& cellLabelsEntry = dict.lookup("cellLabels"); |
|
if(!cellLabelsEntry.found()) |
|
{ |
|
delete cellZoneDictPtr; |
|
vtkErrorMacro(<<"cellLabels not found in cellZones"); |
|
return false; |
|
} |
|
// skip if the list is empty |
|
if(cellLabelsEntry.firstValue().type() == vtkFoamEntryValue::EMPTYLIST) |
|
{ |
|
continue; |
|
} |
|
if(cellLabelsEntry.firstValue().type() != vtkFoamEntryValue::LABELLIST) |
|
{ |
|
delete cellZoneDictPtr; |
|
vtkErrorMacro(<<"cellLabels not of type labelList"); |
|
return false; |
|
} |
|
|
|
const vtkstd::vector<int>& labels = cellLabelsEntry.labelList(); |
|
|
|
// allocate new grid: we do not use resize() beforehand since it |
|
// could lead to undefined pointer if we return by error |
|
cellZoneMesh->value.push_back(vtkUnstructuredGrid::New()); |
|
vtkUnstructuredGrid* czm = cellZoneMesh->value.back(); |
|
|
|
// set cellZone size |
|
size_t nCells = labels.size(); |
|
czm->Allocate(nCells); |
|
|
|
// insert cells |
|
for(size_t j = 0; j < nCells; j++) |
|
{ |
|
this->InsertCellToGrid(czm, labels[j], facesOfCell, facesPoints); |
|
} |
|
|
|
//set cell zone points |
|
cellZoneMesh->value[i]->SetPoints(points); |
} | } |
| |
vtkstd::string token; |
delete cellZoneDictPtr; |
vtksys_ios::stringstream tokenizer; |
vtkDebugMacro(<<"Cell zone mesh created"); |
vtkstd::vector< int > cellZone; |
return true; |
int tempElement; |
} |
vtkstd::vector< vtkstd::vector < int > > tempElementZones; |
|
int numElement; |
vtkPolyData* vtkOpenFOAMReader::MakeLagrangianMesh(int timeState) |
|
{ |
|
vtkStdString positionsPath = *this->PathPrefix |
|
+ this->TimeNames->GetValue(timeState) + "/lagrangian/positions"; |
| |
//find desired mesh entry |
vtkFoamIOobject io; |
while(temp.find(this->CellZoneNames->value[cellZoneIndex]) == |
if(!(io.open(positionsPath) || io.open(positionsPath + ".gz"))) |
vtkstd::string::npos) |
{ |
|
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
|
<< io.error().str().c_str()); |
|
return NULL; |
|
} |
|
vtkFoamDict dict; |
|
if(!dict.read(io)) |
|
{ |
|
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
|
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
|
return NULL; |
|
} |
|
if(dict.type() != vtkFoamDict::VECTORLIST) |
{ | { |
tempStringStruct = this->GetLine(input); |
vtkErrorMacro(<<"The file type of " << io.fileName().c_str() |
temp = tempStringStruct->value; |
<< " is not a vectorList"); |
delete tempStringStruct; |
return NULL; |
} | } |
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct;//throw out { |
|
| |
tempStringStruct = this->GetLine(input); |
vtkDoubleArray& vl = dict.vectorList(); |
temp = tempStringStruct->value; |
const vtkIdType nParticles = vl.GetNumberOfTuples(); |
delete tempStringStruct;//type |
//instantiate the points class |
|
vtkPoints* points = vtkPoints::New(); |
|
points->SetNumberOfPoints(nParticles); |
|
vtkPolyData* lagrangianMesh = vtkPolyData::New(); |
|
lagrangianMesh->Allocate(nParticles); |
| |
tempStringStruct = this->GetLine(input); |
for(vtkIdType i = 0, index = 0; i < nParticles; i++, index += 3) |
temp = tempStringStruct->value; |
{ |
delete tempStringStruct; |
points->SetPoint(i, vl.GetPointer(index)); |
|
lagrangianMesh->InsertNextCell(VTK_VERTEX, 1, &i); |
|
} |
| |
tempStringStruct = this->GetLine(input); |
lagrangianMesh->SetPoints(points); |
temp = tempStringStruct->value; |
points->Delete(); |
delete tempStringStruct; |
return lagrangianMesh; |
|
} |
| |
//number of elements |
bool vtkOpenFOAMReader::GetLagrangianVariableAtTimestep( |
tokenizer << temp; |
vtkPolyData* lagrangianMesh, const char* varNameIn, int timeState) |
tokenizer >> numElement; |
{ |
|
vtkStdString varPath = *this->PathPrefix |
|
+ this->TimeNames->GetValue(timeState) + "/lagrangian/" |
|
+ vtkStdString(varNameIn); |
| |
//binary |
// open the file |
if(binaryWriteFormat) |
vtkFoamIOobject io; |
|
if(!io.open(varPath)) |
{ | { |
input->get(); //parenthesis |
vtkErrorMacro(<<"Error opening " << io.fileName().c_str() << ": " |
for(int j = 0; j < numElement; j++) |
<< io.error().str().c_str()); |
{ |
return false; |
input->read((char *) &tempElement, sizeof(int)); |
|
cellZone.push_back(tempElement); |
|
} |
|
} | } |
| |
//ascii |
// if the variable is disabled on selection panel then skip it |
else |
vtkStdString selectionName |
|
= vtkStdString("lagrangian/") + io.objectName(); |
|
if(this->PointDataArraySelection->ArrayExists(selectionName.c_str()) |
|
&& !this->PointDataArraySelection->ArrayIsEnabled(selectionName.c_str())) |
{ | { |
tempStringStruct = this->GetLine(input); |
return true; |
temp = tempStringStruct->value; |
|
delete tempStringStruct;//throw out ( |
|
|
|
//get each element & add to vector |
|
for(int j = 0; j < numElement; j++) |
|
{ |
|
tempStringStruct = this->GetLine(input); |
|
temp = tempStringStruct->value; |
|
delete tempStringStruct; |
|
|
|
tokenizer.clear(); |
|
tokenizer << temp; |
|
tokenizer >> tempElement; |
|
cellZone.push_back(tempElement); |
|
} |
|
} | } |
| |
//Create the mesh |
// read the field file into dictionary |
bool foundDup = false; |
vtkFoamDict dict; |
vtkstd::vector< int > cellPoints; |
if(!dict.read(io)) |
vtkstd::vector< int > tempFaces[2]; |
{ |
vtkstd::vector< int > firstFace; |
vtkErrorMacro(<<"Error reading line " << io.lineNumber() |
int pivotPoint = 0; |
<< " of " << io.fileName().c_str() << ": " << io.error().str().c_str()); |
int i, j, k, l, pCount; |
return false; |
int faceCount = 0; |
} |
| |
//Create Mesh |
// set lagrangian values |
for(i = 0; i < (int)cellZone.size(); i++) //each cell |
if(dict.type() != vtkFoamDict::SCALARLIST |
|
&& dict.type() != vtkFoamDict::VECTORLIST) |
{ | { |
//calculate total points for all faces of a cell |
vtkErrorMacro(<<"Unsupported lagrangian field type"); |
//used to determine cell type |
return false; |
int totalPointCount = 0; |
} |
for(j = 0; j < (int)this->FacesOfCell->value[ |
|
cellZone[i]].size(); j++) //each face |
|
{ |
|
totalPointCount += (int)this->FacePoints->value[this->FacesOfCell->value[ |
|
cellZone[i]][j].faceIndex].size(); |
|
} |
|
| |
// using cell type - order points, create cell, add to mesh |
vtkDoubleArray* lData = (vtkDoubleArray *)dict.ptr(); |
| |
//OFhex | vtkHexahedron |
// GetNumberOfTuples() works for both scalar and vector |
if (totalPointCount == 24) |
const int nParticles = lData->GetNumberOfTuples(); |
{ |
if(nParticles != lagrangianMesh->GetNumberOfCells()) |
faceCount = 0; |
{ |
|
vtkErrorMacro(<<"Sizes of lagrangian mesh and field don't match"); |
|
return false; |
|
} |
| |
//get first face |
lData->SetName(selectionName.c_str()); |
for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[ |
lagrangianMesh->GetPointData()->AddArray(lData); |
cellZone[i]][0].faceIndex].size(); j++) |
lData->Delete(); |
{ |
|
firstFace.push_back(this->FacePoints->value[this->FacesOfCell->value[ |
return true; |
cellZone[i]][0].faceIndex][j]); |
} |
} |
|
| |
//-if it is a neighbor face flip it |
// return 0 if there's any error, 1 if success |
if(FacesOfCell->value[i][0].neighborFace) |
int vtkOpenFOAMReader::CreateDataSet(vtkMultiBlockDataSet *output, |
|
int timeState) |
|
{ |
|
int oldTimeState = this->OldTimeStep; |
|
vtkPolyData* lagrangianMesh = NULL; |
|
bool updateVariables = true; |
|
|
|
// determine if we need to reconstruct meshes |
|
if(this->CacheMesh && oldTimeState >= 0 |
|
&& this->PolyMeshFacesDir->value[timeState] |
|
== this->PolyMeshFacesDir->value[oldTimeState] |
|
&& this->FaceOwner != NULL |
|
&& this->PatchSelectionStatus == this->PatchSelectionOldStatus) |
|
{ |
|
if((timeState == oldTimeState) |
|
&& (this->CellSelectionStatus == this->CellSelectionOldStatus) |
|
&& (this->PointSelectionStatus == this->PointSelectionOldStatus)) |
|
{ |
|
updateVariables = false; |
|
} |
|
else |
|
{ |
|
// clean up arrays of the previous timestep |
|
// Check if Internal Mesh Exists first... |
|
if(this->InternalMesh != NULL) |
{ | { |
int tempPop; |
vtkCellData* internalCellData = this->InternalMesh->GetCellData(); |
for(k = 0; k < (int)firstFace.size() - 1; k++) |
while(internalCellData->GetArrayName(0)) |
{ | { |
tempPop = firstFace[firstFace.size()-1]; |
internalCellData->RemoveArray(internalCellData->GetArrayName(0)); |
firstFace.pop_back(); |
|
firstFace.insert(firstFace.begin()+1+k, tempPop); |
|
} | } |
} | } |
|
// Check if Boundary Mesh Exists first... |
//add first face to cell points |
if(this->BoundaryMesh != NULL) |
for(j =0; j < (int)firstFace.size(); j++) |
|
{ |
|
cellPoints.push_back(firstFace[j]); |
|
} |
|
|
|
for(int pointCount = 0;pointCount < (int)firstFace.size();pointCount++) |
|
{ | { |
//find the 2 other faces containing each point - start with face 1 |
for(size_t i = 0; i < this->BoundaryMesh->value.size(); i++) |
for(j = 1; j < (int)this->FacesOfCell->value[ |
|
cellZone[i]].size(); j++) //each face |
|
{ | { |
for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell-> |
vtkCellData* boundaryCellData |
value[cellZone[i]][j].faceIndex].size(); k++) |
= this->BoundaryMesh->value[i]->GetCellData(); |
|
while(boundaryCellData->GetArrayName(0)) |
{ | { |
if(firstFace[pointCount] == this->FacePoints-> |
boundaryCellData->RemoveArray(boundaryCellData->GetArrayName(0)); |
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 |
// if only point coordinates change refresh point vector |
for(j = 0; j < (int)tempFaces[0].size(); j++) |
if(this->PolyMeshPointsDir->value[timeState] |
|
!= this->PolyMeshPointsDir->value[oldTimeState]) |
|
{ |
|
//get the points |
|
vtkPoints* points = this->GetPoints(timeState); |
|
if(points == NULL) |
{ | { |
for(k = 0; k < (int)tempFaces[1].size(); k++) |
return 0; |
{ |
|
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; |
|
} |
|
| |
//create the hex cell and insert it into the mesh |
// refresh the points in each mesh |
vtkHexahedron * hexahedron = vtkHexahedron::New(); |
// Check if Internal Mesh exists first.... |
for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) |
if(this->InternalMesh != NULL) |
{ | { |
hexahedron->GetPointIds()->SetId(pCount, cellPoints[pCount]); |
this->InternalMesh->SetPoints(points); |
} | } |
cellZoneMesh->InsertNextCell(hexahedron->GetCellType(), |
// Check if Boundary Mesh exists first.... |
hexahedron->GetPointIds()); |
if(this->BoundaryMesh != NULL) |
hexahedron->Delete(); |
|
cellPoints.clear(); |
|
firstFace.clear(); |
|
} |
|
|
|
//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 |
|
{ |
|
if((int)this->FacePoints->value[this->FacesOfCell->value[ |
|
cellZone[i]][j].faceIndex].size() == 3) |
|
{ | { |
for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ |
for(size_t i = 0; i < this->BoundaryMesh->value.size(); i++) |
cellZone[i]][j].faceIndex].size(); k++) |
|
{ | { |
firstFace.push_back(this->FacePoints->value[this->FacesOfCell-> |
this->BoundaryMesh->value[i]->SetPoints(points); |
value[cellZone[i]][j].faceIndex][k]); |
|
index = j; |
|
} | } |
break; |
|
} | } |
} |
if(this->PointZoneMesh != NULL) |
|
|
//-if it is a neighbor face flip it |
|
if(this->FacesOfCell->value[i][0].neighborFace) |
|
{ |
|
int tempPop; |
|
for(k = 0; k < (int)firstFace.size() - 1; k++) |
|
{ | { |
tempPop = firstFace[firstFace.size()-1]; |
for(size_t i = 0; i < this->PointZoneMesh->value.size(); i++) |
firstFace.pop_back(); |
{ |
firstFace.insert(firstFace.begin()+1+k, tempPop); |
this->PointZoneMesh->value[i]->SetPoints(points); |
|
} |
} | } |
} |
if(this->FaceZoneMesh != NULL) |
|
|
//add first face to cell points |
|
for(j =0; j < (int)firstFace.size(); j++) |
|
{ |
|
cellPoints.push_back(firstFace[j]); |
|
} |
|
|
|
for(int pointCount = 0;pointCount < (int)firstFace.size();pointCount++) |
|
{ |
|
//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[ |
for(size_t i = 0; i < this->FaceZoneMesh->value.size(); i++) |
cellZone[i]][j].faceIndex].size(); k++) //each point |
|
{ | { |
if(firstFace[pointCount] == this->FacePoints-> |
this->FaceZoneMesh->value[i]->SetPoints(points); |
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++; |
|
} |
|
} | } |
} | } |
|
if(this->CellZoneMesh != NULL) |
//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++) |
for(size_t i = 0; i < this->CellZoneMesh->value.size(); i++) |
{ | { |
if(tempFaces[0][j] == tempFaces[1][k] && tempFaces[0][j] != |
this->CellZoneMesh->value[i]->SetPoints(points); |
firstFace[pointCount]) |
|
{ |
|
pivotPoint = tempFaces[0][j]; |
|
break; |
|
} |
|
} | } |
} | } |
cellPoints.push_back(pivotPoint); |
points->Delete(); |
tempFaces[0].clear(); |
|
tempFaces[1].clear(); |
|
faceCount=0; |
|
} | } |
|
} |
|
} |
|
else |
|
{ |
|
this->ClearMeshes(); |
| |
//create the wedge cell and insert it into the mesh |
vtkStdString meshDir = *this->PathPrefix |
vtkWedge * wedge = vtkWedge::New(); |
+ this->PolyMeshFacesDir->value[timeState] + "/polyMesh/"; |
for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) |
|
{ |
//create paths to polyMesh files |
wedge->GetPointIds()->SetId(pCount, cellPoints[pCount]); |
vtkStdString facePath = meshDir + "faces"; |
} |
vtkStdString ownerPath = meshDir + "owner"; |
cellZoneMesh->InsertNextCell(wedge->GetCellType(), |
vtkStdString neighborPath = meshDir + "neighbour"; |
wedge->GetPointIds()); |
|
cellPoints.clear(); |
//create the faces vector |
wedge->Delete(); |
intVectorVector* facePoints = this->ReadFacesFile(facePath.c_str()); |
firstFace.clear(); |
if(facePoints == NULL) |
|
{ |
|
return 0; |
} | } |
|
this->UpdateProgress(0.2); |
| |
//OFpyramid | vtkPyramid |
//read owner/neighbor and create the faces owner/facesOfCell vector |
else if (totalPointCount == 16) |
faceVectorVector* facesOfCell = new faceVectorVector; |
|
if(!this->ReadOwnerNeighborFiles(facesOfCell, ownerPath.c_str(), |
|
neighborPath.c_str())) |
{ | { |
foundDup = false; |
delete facePoints; |
|
delete facesOfCell; |
|
return 0; |
|
} |
|
this->UpdateProgress(0.3); |
| |
//find quad |
//get the points |
for(j = 0; j < (int)this->FacesOfCell->value[ |
vtkPoints* points = this->GetPoints(timeState); |
cellZone[i]].size(); j++) //each face |
if(points == NULL) |
{ |
{ |
if((int)this->FacePoints->value[this->FacesOfCell->value[ |
delete facePoints; |
cellZone[i]][j].faceIndex].size() == 4) |
delete facesOfCell; |
{ |
return 0; |
for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ |
} |
cellZone[i]][j].faceIndex].size(); k++) |
this->UpdateProgress(0.4); |
{ |
|
cellPoints.push_back(this->FacePoints->value[this->FacesOfCell-> |
|
value[cellZone[i]][j].faceIndex][k]); |
|
} |
|
break; |
|
} |
|
} |
|
| |
//compare first face points to second faces |
// make internal mesh |
for(j = 0; j < (int)cellPoints.size(); j++) //each point |
// Create Internal Mesh only if required for display |
|
if(this->GetPatchArrayStatus(GetPatchArrayName(0))) |
|
{ |
|
this->InternalMesh = this->MakeInternalMesh(facesOfCell, facePoints, |
|
points); |
|
} |
|
else |
|
{ |
|
if(this->InternalMesh != NULL) |
{ | { |
for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ |
this->InternalMesh->Delete(); |
cellZone[i]][1].faceIndex].size(); k++) |
this->InternalMesh = NULL; |
{ |
|
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; |
|
} |
|
} | } |
|
} |
| |
//create the pyramid cell and insert it into the mesh |
// read polyMesh/bondary |
vtkPyramid * pyramid = vtkPyramid::New(); |
this->BoundaryDict = this->GatherBlocks("boundary", timeState, true); |
for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) |
if(this->BoundaryDict == NULL) |
{ |
{ |
pyramid->GetPointIds()->SetId(pCount, cellPoints[pCount]); |
delete facePoints; |
} |
delete facesOfCell; |
cellZoneMesh->InsertNextCell(pyramid->GetCellType(), |
points->Delete(); |
pyramid->GetPointIds()); |
vtkErrorMacro("Couldn't read polyMesh/boundary"); |
cellPoints.clear(); |
return 0; |
pyramid->Delete(); |
|
} | } |
| |
//OFtet | vtkTetrahedron |
// create boundary mesh |
else if (totalPointCount == 12) |
this->BoundaryMesh = this->GetBoundaryMesh(this->BoundaryDict, facePoints, |
|
points); |
|
if(this->BoundaryMesh == NULL) |
{ | { |
foundDup = false; |
delete facePoints; |
|
delete facesOfCell; |
|
points->Delete(); |
|
return 0; |
|
} |
| |
//grab first face |
// read and construct zones |
for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[ |
if(ReadZones) |
cellZone[i]][0].faceIndex].size(); j++) |
{ |
|
this->PointZoneMesh = new unstructuredGridVector; |
|
if(!this->GetPointZoneMesh(this->PointZoneMesh, points, timeState)) |
|
{ |
|
for(size_t i = 0; i < this->PointZoneMesh->value.size(); i++) |
|
{ |
|
this->PointZoneMesh->value[i]->Delete(); |
|
} |
|
delete this->PointZoneMesh; |
|
this->PointZoneMesh = NULL; |
|
delete facePoints; |
|
delete facesOfCell; |
|
points->Delete(); |
|
return 0; |
|
} |
|
if(this->PointZoneMesh->value.size() == 0) |
{ | { |
cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->value[ |
delete this->PointZoneMesh; |
cellZone[i]][0].faceIndex][j]); |
this->PointZoneMesh = NULL; |
} | } |
| |
//compare first face points to second faces |
this->FaceZoneMesh = new unstructuredGridVector; |
for(j = 0; j < (int)cellPoints.size(); j++) //each point |
if(!this->GetFaceZoneMesh(this->FaceZoneMesh, facePoints, points, |
|
timeState)) |
{ | { |
for(k = 0; k < (int)this->FacePoints->value[this->FacesOfCell->value[ |
for(size_t i = 0; i < this->FaceZoneMesh->value.size(); i++) |
cellZone[i]][1].faceIndex].size(); k++) |
|
{ | { |
if(cellPoints[j] == this->FacePoints->value[this->FacesOfCell->value[ |
this->FaceZoneMesh->value[i]->Delete(); |
cellZone[i]][1].faceIndex][k]) |
|
{ |
|
foundDup = true; |
|
} |
|
} | } |
if(!foundDup) |
delete this->FaceZoneMesh; |
|
this->FaceZoneMesh = NULL; |
|
delete facePoints; |
|
delete facesOfCell; |
|
points->Delete(); |
|
return 0; |
|
} |
|
if(this->FaceZoneMesh->value.size() == 0) |
|
{ |
|
delete this->FaceZoneMesh; |
|
this->FaceZoneMesh = NULL; |
|
} |
|
|
|
this->CellZoneMesh = new unstructuredGridVector; |
|
if(!this->GetCellZoneMesh(this->CellZoneMesh, facesOfCell, facePoints, |
|
points, timeState)) |
|
{ |
|
for(size_t i = 0; i < this->CellZoneMesh->value.size(); i++) |
{ | { |
cellPoints.push_back(this->FacePoints->value[this->FacesOfCell->value[ |
this->CellZoneMesh->value[i]->Delete(); |
cellZone[i]][j].faceIndex][k]); |
|
break; |
|
} | } |
|
delete this->CellZoneMesh; |
|
this->CellZoneMesh = NULL; |
|
delete facePoints; |
|
delete facesOfCell; |
|
points->Delete(); |
|
return 0; |
} | } |
|
if(this->CellZoneMesh->value.size() == 0) |
//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]); |
delete this->CellZoneMesh; |
|
this->CellZoneMesh = NULL; |
} | } |
cellZoneMesh->InsertNextCell(tetra->GetCellType(), |
|
tetra->GetPointIds()); |
|
cellPoints.clear(); |
|
tetra->Delete(); |
|
} | } |
| |
//erronous cells |
delete facesOfCell; |
else if(totalPointCount == 0) |
delete facePoints; |
{ |
points->Delete(); |
vtkWarningMacro("Warning: No points in cell."); |
} |
} |
this->UpdateProgress(0.5); |
| |
//OFpolyhedron || vtkConvexPointSet |
if(updateVariables) |
else |
{ |
|
// read field data variables into Internal/Boundary meshes |
|
for(int i = 0; i < (int)this->TimeStepData->value.size(); i++) |
{ | { |
vtkWarningMacro("Warning: Polyhedral Data is very Slow!"); |
if(!this->GetVariableAtTimestep(this->InternalMesh, this->BoundaryMesh, |
foundDup = false; |
this->BoundaryDict, this->TimeStepData->value[i].c_str(), timeState)) |
|
|
//grab face 0 |
|
for(j = 0; j < (int)this->FacePoints->value[this->FacesOfCell->value[ |
|
cellZone[i]][0].faceIndex].size(); j++) |
|
{ | { |
firstFace.push_back(this->FacePoints->value[ |
// error occurred while reading a field data variable, but continue |
this->FacesOfCell->value[i][0].faceIndex][j]); |
// to the next variable |
|
continue; |
} | } |
|
this->UpdateProgress(0.5 |
|
+ 0.5 * ((float)(i + 1) / (float)this->TimeStepData->value.size())); |
|
} |
| |
//ADD FIRST FACE TO CELL POINTS |
// read lagrangian mesh and fields |
for(j =0; j < (int)firstFace.size(); j++) |
if(this->LagrangianTimeStepData->value.size() > 0 |
|
&& this->GetPatchArrayStatus("Lagrangian Particles")) |
|
{ |
|
// construct lagrangian mesh |
|
lagrangianMesh = this->MakeLagrangianMesh(timeState); |
|
if(lagrangianMesh == NULL) |
{ | { |
cellPoints.push_back(firstFace[j]); |
return 0; |
} | } |
//j = 1 skip firstFace |
|
for(j = 1; j < (int) this->FacesOfCell->value[ |
// read lagrangian variables |
cellZone[i]].size(); j++) |
for(size_t i = 0; i < this->LagrangianTimeStepData->value.size(); i++) |
{ | { |
//remove duplicate points from faces |
if(!this->GetLagrangianVariableAtTimestep(lagrangianMesh, |
for(k = 0; k < (int)this->FacePoints->value[ |
this->LagrangianTimeStepData->value[i].c_str(), timeState)) |
this->FacesOfCell->value[i][j].faceIndex].size(); k++) |
|
{ | { |
for(l = 0; l < (int)cellPoints.size(); l++); |
// error occurred while reading a field data variable, but continue |
{ |
// to the next variable |
if(cellPoints[l] == this->FacePoints->value[this->FacesOfCell-> |
continue; |
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; |
|
} |
|
} | } |
} | } |
|
} |
|
} |
| |
//create the poly cell and insert it into the mesh |
// assign group to each of data and point/face/cell-Zones |
vtkConvexPointSet * poly = vtkConvexPointSet::New(); |
int nGroups = 1 + ((lagrangianMesh != NULL |
poly->GetPointIds()->SetNumberOfIds(cellPoints.size()); |
&& lagrangianMesh->GetPointData()->GetNumberOfArrays() > 0) ? 1 : 0) |
for(pCount = 0; pCount < (int)cellPoints.size(); pCount++) |
+ (this->PointZoneMesh != NULL ? 1 : 0) |
{ |
+ (this->FaceZoneMesh != NULL ? 1 : 0) |
poly->GetPointIds()->SetId(pCount, cellPoints[pCount]); |
+ (this->CellZoneMesh != NULL ? 1 : 0); |
} |
output->SetNumberOfGroups(nGroups); |
cellZoneMesh->InsertNextCell(poly->GetCellType(), |
|
poly->GetPointIds()); |
// set internal mesh/data as output |
cellPoints.clear(); |
//output->SetNumberOfDataSets(0,output->GetNumberOfDataSets(0)); |
firstFace.clear(); |
|
poly->Delete(); |
// Add Internal Mesh to final output only if selected for display |
|
if(GetPatchArrayStatus(GetPatchArrayName(0))) |
|
{ |
|
output->SetDataSet(0, output->GetNumberOfDataSets(0), this->InternalMesh); |
|
} |
|
|
|
// set boundary meshes/data as output |
|
for(size_t j = 0; j < this->BoundaryMesh->value.size(); j++) |
|
{ |
|
output->SetDataSet(0, output->GetNumberOfDataSets(0), |
|
this->BoundaryMesh->value[j]); |
|
if(!this->CacheMesh) |
|
{ |
|
this->BoundaryMesh->value[j]->Delete(); |
} | } |
} | } |
//set cell zone points |
|
cellZoneMesh->SetPoints(Points); |
|
input->close(); |
|
delete input; |
|
vtkDebugMacro(<<"Cell zone mesh created"); |
|
return cellZoneMesh; |
|
} |
|
| |
void vtkOpenFOAMReader::CreateDataSet(vtkMultiBlockDataSet *output) |
if(!this->CacheMesh) |
{ |
{ |
int timeState = this->TimeStep; |
// First check if these meshes exist before deleting them.... |
//create paths to polyMesh files |
if(this->BoundaryMesh != NULL) |
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 = this->BoundaryNames->value.size(); |
|
int numPointZones = this->PointZoneNames->value.size(); |
|
int numFaceZones = this->FaceZoneNames->value.size(); |
|
int numCellZones = 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()); |
delete this->BoundaryMesh; |
internalMesh->GetCellData()->AddArray(data); |
this->BoundaryMesh = NULL; |
} | } |
data->Delete(); |
if(this->InternalMesh != NULL) |
|
{ |
|
this->InternalMesh->Delete(); |
|
this->InternalMesh = NULL; |
|
} |
|
delete this->BoundaryDict; |
|
this->BoundaryDict = NULL; |
|
this->FaceOwner->Delete(); |
|
this->FaceOwner = NULL; |
} | } |
//output->SetNumberOfDataSets(0,output->GetNumberOfDataSets(0)); |
|
output->SetDataSet(0, output->GetNumberOfDataSets(0), internalMesh); |
|
| |
//Boundary Meshes |
int groupI = 0; |
for(int i = 0; i < (int)numBoundaries; i++) |
|
|
// set lagrangian mesh as output |
|
if(lagrangianMesh != NULL |
|
&& lagrangianMesh->GetPointData()->GetNumberOfArrays() > 0) |
{ | { |
vtkUnstructuredGrid * boundaryMesh = this->GetBoundaryMesh(timeState, i); |
groupI++; |
for(int j = 0; j < (int)this->TimeStepData->value.size(); j++) |
output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI), |
|
lagrangianMesh); |
|
lagrangianMesh->Delete(); |
|
} |
|
|
|
// set Zone Meshes as output |
|
if(this->PointZoneMesh != NULL) |
|
{ |
|
groupI++; |
|
for(size_t i = 0; i < this->PointZoneMesh->value.size(); i++) |
{ | { |
vtkDoubleArray * data = |
output->SetDataSet(groupI, output->GetNumberOfDataSets(groupI), |
this->GetBoundaryVariableAtTimestep(i, TimeStepData->value[j].c_str(), |
this->PointZoneMesh->value[i]); |
timeState, internalMesh); |
if(!this->CacheMesh) |
if(data->GetSize() > 0) |
|
{ | { |
data->SetName(this->TimeStepData->value[j].c_str()); |
this->PointZoneMesh->value[i]->Delete(); |
boundaryMesh->GetCellData()->AddArray(data); |
|
} | } |
data->Delete(); |
|
} | } |
output->SetDataSet(0, output->GetNumberOfDataSets(0), boundaryMesh); |
if(!this->CacheMesh) |
boundaryMesh->Delete(); |
{ |
|
delete this->PointZoneMesh; |
|
this->PointZoneMesh = NULL; |
|
} |
} | } |
| |
internalMesh->Delete(); |
if(this->FaceZoneMesh != NULL) |
this->FaceOwner->Delete(); |
|
//Zone Meshes |
|
for(int i = 0; i < (int)numPointZones; i++) |
|
{ | { |
vtkUnstructuredGrid * pointMesh = this->GetPointZoneMesh(timeState, i); |
groupI++; |
output->SetDataSet(0, output->GetNumberOfDataSets(0), |
for(size_t i = 0; i < this->FaceZoneMesh->value.size(); i++) |
pointMesh); |
{ |