Merge branch 'master' of /home/noisy3/OpenFOAM/OpenFOAM-dev

This commit is contained in:
mattijs
2010-01-04 13:37:37 +00:00
30 changed files with 289480 additions and 605 deletions

View File

@ -0,0 +1,15 @@
#!/bin/sh
cd ${0%/*} || exit 1 # run from this directory
# this will have to do until we have a makefile rule
if type Coco > /dev/null 2>&1
then
Coco \
-frames $WM_THIRD_PARTY_DIR/coco-r \
calcEntry/calcEntry.atg
else
echo "Coco not installed"
fi
wmake

View File

@ -1,11 +0,0 @@
#/bin/sh
cd ${0%/*} || exit 1 # run from this directory
# this will have to do until we make a makefile rule
Coco \
-frames $WM_THIRD_PARTY_DIR/coco-r \
-prefix calcEntry \
-namespace Foam::functionEntries::calcEntryInternal \
SimpleCalc.atg

View File

@ -26,8 +26,6 @@ License
#include "calcEntry.H"
#include "dictionary.H"
#include "IStringStream.H"
#include "OStringStream.H"
#include "addToMemberFunctionSelectionTable.H"
#include "ISstream.H"
@ -60,121 +58,33 @@ bool Foam::functionEntries::calcEntry::execute
(
const dictionary& parentDict,
primitiveEntry& entry,
Istream& istr
Istream& is
)
{
static const int maxLen = 1024;
static const int errLen = 80; // truncate error message for readability
static char buf[maxLen];
ISstream& is = dynamicCast<ISstream>(istr);
// get the { ... } argument without the enclosing brace brackets
//
// THIS NEEDS REWORKING (LATER) ...
char c = 0;
if (!is.read(c).good() || c != token::BEGIN_BLOCK)
{
is.setBad();
FatalIOErrorIn("functionEntries::calcEntry::execute()", is)
<< "Expected a '" << token::BEGIN_BLOCK
<< "', found '" << c << "'" << exit(FatalIOError);
return false;
}
register int nChar = 0;
buf[nChar++] = token::BEGIN_BLOCK;
int listDepth = 1; // already saw the first '{'
while (is.get(c).good())
{
buf[nChar++] = c;
if (nChar == maxLen)
{
buf[errLen] = '\0';
FatalIOErrorIn("functionEntries::calcEntry::execute()", is)
<< "argument \"" << buf << "...\"\n"
<< " is too long (max. " << maxLen << " characters)"
<< exit(FatalIOError);
return false;
}
// handle nested blocks, even if we don't know what they'd
// be useful for
if (c == token::BEGIN_BLOCK)
{
++listDepth;
}
else if (c == token::END_BLOCK)
{
if (--listDepth == 0)
{
// done reading - overwrite the final '}'
// --nChar;
break;
}
}
}
buf[nChar] = '\0';
// emit some info
Info<< "grabbed " << nChar << " characters:" << nl
<< "----------\n"
<< buf << nl
<< "----------\n"
<< nl;
std::istream& iss = dynamicCast<ISstream>(is).stdStream();
// define parser error handler
CocoParserErrors<calcEntryInternal::Errors>
myErrorHandler("calcEntry::Parser--");
myErrorHandler("calcEntryInternal::Parser");
calcEntryInternal::Scanner scanner(buf, nChar);
calcEntryInternal::Scanner scanner(iss);
calcEntryInternal::Parser parser(&scanner, &myErrorHandler);
// Attach dictionary context
parser.dict(parentDict);
// Attach scalar functions
// parser.functions(parentDict);
parser.Parse();
// Info<<"got: " << parser.Result() << endl;
// make a small input list to contain the answer
tokenList tokens(2);
tokens[0] = parser.Result();
tokens[1] = token::END_STATEMENT;
// Info<<"tokens[0] = " << tokens[0].info() <<nl;
// Info<<"tokens[1] = " << tokens[1].info() <<nl;
//
// {
// const tokenList& toks = entry;
//
// forAll(toks, tokI)
// {
// Info<< tokI <<":= " << toks[tokI].info() << endl;
// }
// }
entry.read(parentDict, ITstream("ParserResult", tokens)());
ITstream its("ParserResult", tokens);
entry.read(parentDict, its);
// Info<< "size: " << entry.size() << endl;
// entry = newente;
// entry.print(Info);
/// const tokenList& toks = entry;
///
/// forAll(toks, tokI)
/// {
/// Info<< tokI <<":= " << toks[tokI].info() << endl;
/// }
///
return true;
}

View File

@ -2,9 +2,7 @@
compile with:
Coco \
-frames $WM_THIRD_PARTY_DIR/coco-r \
-prefix calcEntry \
-namespace Foam::functionEntries::calcEntryInternal \
SimpleCalc.atg
calcEntry.atg
-------------------------------------------------------------------------*/
#include "dictionary.H"
@ -13,7 +11,11 @@
#include "wchar.H"
COMPILER SimpleCalc
COMPILER calcEntry
$prefix=calcEntry
$namespace=Foam::functionEntries::calcEntryInternal
$eof=true // grammar handles eof itself
// Simple four function calculator for OpenFOAM dictionaries
//! with debug
@ -22,9 +24,13 @@ COMPILER SimpleCalc
//! The parent dictionary
mutable dictionary* dict_;
//! Track that parent dictionary was set
bool hasDict_;
//! The calculation result
scalar val;
//! token -> scalar
scalar getScalar() const
{
@ -40,11 +46,11 @@ COMPILER SimpleCalc
return s;
}
//! attach a dictionary
void dict(const dictionary& dict) const
void dict(const dictionary& dict)
{
dict_ = const_cast<dictionary*>(&dict);
hasDict_ = true;
}
@ -53,11 +59,11 @@ COMPILER SimpleCalc
{
scalar dictValue = 0;
if (!dict_)
if (!hasDict_)
{
FatalErrorIn
(
"SimpleCalc::getDictEntry() const"
"calcEntry::getDictEntry() const"
) << "No dictionary attached!"
<< exit(FatalError);
@ -81,13 +87,22 @@ COMPILER SimpleCalc
entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false);
if (entryPtr && !entryPtr->isDict())
{
if (entryPtr->stream().size() != 1)
{
FatalErrorIn
(
"calcEntry::getDictEntry() const"
) << "keyword " << keyword << " has "
<< entryPtr->stream().size() << " values in dictionary "
<< exit(FatalError);
}
entryPtr->stream() >> dictValue;
}
else
{
FatalErrorIn
(
"SimpleCalc::getDictEntry() const"
"calcEntry::getDictEntry() const"
) << "keyword " << keyword << " is undefined in dictionary "
<< exit(FatalError);
}
@ -102,7 +117,7 @@ COMPILER SimpleCalc
}
// * * * * * * * * * * * * * * * CHARACTERS * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*/
CHARACTERS
letter = 'A'..'Z' + 'a'..'z'.
@ -145,38 +160,49 @@ number =
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
// ignore unprintables
IGNORE ANY - printable
IGNORE cr + lf + tab
// * * * * * * * * * * * * * * * PRODUCTIONS * * * * * * * * * * * * * * * //
PRODUCTIONS
SimpleCalc (. val = 0;
if (debug){Info<<"start val"<< nl;}
calcEntry (. val = 0;
if (debug){Info<<"start val pos:"<< t->pos << nl;}
.)
=
( '{' Expr<val> '}' | Expr<val> )
EOF
'{' Expr<val> '}' (.
if (debug){
Info<<"end {} at pos:"<< t->pos
<<" val:"<< t->val
<<" len:"<< coco_string_length(t->val)
<<" la pos:"<< la->pos << nl;
}
// reposition to immediately after the closing '}'
scanner->buffer->SetPos
(
t->pos + coco_string_length(t->val)
);
.)
| ( Expr<val> EOF )
.
/*---------------------------------------------------------------------------*/
Expr<scalar& val> (. scalar val2 = 0;
if (debug) {Info<<"Expr:"<< val<< nl;}
if (debug) {Info<<"Expr:"<< val<< " pos:"<< t->pos << nl;}
.)
=
Term<val>
{
"+" Term<val2> (. if (debug) {Info<<"+Term:"<<val2 <<nl;}
"+" Term<val2> (. if (debug) {Info<<"+Term:"<<val2 << " pos:"<< t->pos << nl;}
val += val2;
if (debug) {Info<<"="<< val << nl;}
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
.)
| "-" Term<val2> (. if (debug) {Info<<"-Term:"<<val2 <<nl;}
| "-" Term<val2> (. if (debug) {Info<<"-Term:"<<val2<< " pos:"<< t->pos << nl;}
val -= val2;
if (debug) {Info<<"="<< val << nl;}
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
.)
}
.
@ -185,18 +211,18 @@ Expr<scalar& val> (. scalar val2 = 0;
/*---------------------------------------------------------------------------*/
Term<scalar& val> (. scalar val2 = 0;
if (debug) {Info<<"Term:"<< val<< nl;}
if (debug) {Info<<"Term:"<< val<< " pos:"<< t->pos << nl;}
.)
=
Factor<val>
{
"*" Factor<val2> (. if (debug) {Info<<"*Factor:"<<val2 << nl;}
"*" Factor<val2> (. if (debug) {Info<<"*Factor:"<<val2<< " pos:"<< t->pos << nl;}
val *= val2;
if (debug) {Info<<"="<< val << nl; }
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
.)
| "/" Factor<val2> (. if (debug) {Info<<"/Factor:"<<val2 << nl;}
| "/" Factor<val2> (. if (debug) {Info<<"/Factor:"<<val2<< " pos:"<< t->pos << nl;}
val /= val2;
if (debug) {Info<<"="<< val << nl; }
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
.)
}
.
@ -206,20 +232,21 @@ Term<scalar& val> (. scalar val2 = 0;
Factor<scalar& val>
=
variable (. val = getDictLookup();
if (debug) {Info<<"lookup:"<<val<<nl;}
if (debug) {Info<<"lookup:"<<val<< " pos:"<< t->pos << nl;}
.)
| number (. val = getScalar();
if (debug) {Info<<"got num:"<<val<<nl;}
if (debug) {Info<<"got num:"<<val<< " pos:"<< t->pos << nl;}
.)
| '-' '(' Expr<val> ')' (. val = -val;
if (debug) {Info<<"inv:"<<val<<nl;}
if (debug) {Info<<"inv:"<<val<< " pos:"<< t->pos << nl;}
.)
| '(' Expr<val> ')' (. if (debug){Info<<"got Expr:"<<val<< " pos:"<< t->pos << nl;}
.)
| '(' Expr<val> ')' (. if (debug){Info<<"got Expr:"<<val<<nl;} .)
.
/*---------------------------------------------------------------------------*/
END SimpleCalc.
END calcEntry.
// ************************************************************************* //

View File

@ -90,39 +90,51 @@ bool Parser::WeakSeparator(int n, int syFol, int repFol) {
}
void Parser::SimpleCalc() {
void Parser::calcEntry() {
val = 0;
if (debug){Info<<"start val"<< nl;}
if (debug){Info<<"start val pos:"<< t->pos << nl;}
if (la->kind == 5) {
Get();
Expr(val);
Expect(6);
if (debug){
Info<<"end {} at pos:"<< t->pos
<<" val:"<< t->val
<<" len:"<< coco_string_length(t->val)
<<" la pos:"<< la->pos << nl;
}
// reposition to immediately after the closing '}'
scanner->buffer->SetPos
(
t->pos + coco_string_length(t->val)
);
} else if (StartOf(1)) {
Expr(val);
Expect(0);
} else SynErr(14);
Expect(0);
}
void Parser::Expr(scalar& val) {
scalar val2 = 0;
if (debug) {Info<<"Expr:"<< val<< nl;}
if (debug) {Info<<"Expr:"<< val<< " pos:"<< t->pos << nl;}
Term(val);
while (la->kind == 7 || la->kind == 8) {
if (la->kind == 7) {
Get();
Term(val2);
if (debug) {Info<<"+Term:"<<val2 <<nl;}
if (debug) {Info<<"+Term:"<<val2 << " pos:"<< t->pos << nl;}
val += val2;
if (debug) {Info<<"="<< val << nl;}
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
} else {
Get();
Term(val2);
if (debug) {Info<<"-Term:"<<val2 <<nl;}
if (debug) {Info<<"-Term:"<<val2<< " pos:"<< t->pos << nl;}
val -= val2;
if (debug) {Info<<"="<< val << nl;}
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
}
}
@ -130,23 +142,23 @@ void Parser::Expr(scalar& val) {
void Parser::Term(scalar& val) {
scalar val2 = 0;
if (debug) {Info<<"Term:"<< val<< nl;}
if (debug) {Info<<"Term:"<< val<< " pos:"<< t->pos << nl;}
Factor(val);
while (la->kind == 9 || la->kind == 10) {
if (la->kind == 9) {
Get();
Factor(val2);
if (debug) {Info<<"*Factor:"<<val2 << nl;}
if (debug) {Info<<"*Factor:"<<val2<< " pos:"<< t->pos << nl;}
val *= val2;
if (debug) {Info<<"="<< val << nl; }
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
} else {
Get();
Factor(val2);
if (debug) {Info<<"/Factor:"<<val2 << nl;}
if (debug) {Info<<"/Factor:"<<val2<< " pos:"<< t->pos << nl;}
val /= val2;
if (debug) {Info<<"="<< val << nl; }
if (debug) {Info<<"="<< val<< " pos:"<< t->pos << nl;}
}
}
@ -156,12 +168,12 @@ void Parser::Factor(scalar& val) {
if (la->kind == 3) {
Get();
val = getDictLookup();
if (debug) {Info<<"lookup:"<<val<<nl;}
if (debug) {Info<<"lookup:"<<val<< " pos:"<< t->pos << nl;}
} else if (la->kind == 4) {
Get();
val = getScalar();
if (debug) {Info<<"got num:"<<val<<nl;}
if (debug) {Info<<"got num:"<<val<< " pos:"<< t->pos << nl;}
} else if (la->kind == 8) {
Get();
@ -169,13 +181,14 @@ void Parser::Factor(scalar& val) {
Expr(val);
Expect(12);
val = -val;
if (debug) {Info<<"inv:"<<val<<nl;}
if (debug) {Info<<"inv:"<<val<< " pos:"<< t->pos << nl;}
} else if (la->kind == 11) {
Get();
Expr(val);
Expect(12);
if (debug){Info<<"got Expr:"<<val<<nl;}
if (debug){Info<<"got Expr:"<<val<< " pos:"<< t->pos << nl;}
} else SynErr(15);
}
@ -189,9 +202,9 @@ void Parser::Parse() {
la = dummyToken = new Token();
la->val = coco_string_create(L"Dummy Token");
Get();
SimpleCalc();
calcEntry();
// let grammar deal with end-of-file expectations
Expect(0);
}
@ -199,14 +212,12 @@ Parser::Parser(Scanner* scan, Errors* err)
:
dummyToken(NULL),
deleteErrorsDestruct_(!err),
minErrDist(2),
errDist(minErrDist),
scanner(scan),
errors(err),
t(NULL),
la(NULL)
{
maxT = 13;
if (!errors) { // add in default error handling
errors = new Errors();
@ -274,7 +285,7 @@ wchar_t* Errors::strerror(int n)
case 11: s = coco_string_create(L"\"(\" expected"); break;
case 12: s = coco_string_create(L"\")\" expected"); break;
case 13: s = coco_string_create(L"??? expected"); break;
case 14: s = coco_string_create(L"invalid SimpleCalc"); break;
case 14: s = coco_string_create(L"invalid calcEntry"); break;
case 15: s = coco_string_create(L"invalid Factor"); break;
default:
@ -317,8 +328,12 @@ void Errors::Exception(const wchar_t* msg) {
::exit(1);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // namespace
} // namespace
} // namespace
// ************************************************************************* //

View File

@ -55,11 +55,12 @@ private:
_variable=3,
_number=4,
};
int maxT;
static const int maxT = 13;
static const int minErrDist = 2; //!< min. distance before reporting errors
Token *dummyToken;
bool deleteErrorsDestruct_; //!< delete the 'errors' member in destructor
int minErrDist;
int errDist;
void SynErr(int n); //!< Handle syntax error 'n'
@ -81,9 +82,13 @@ static const int debug = 0;
//! The parent dictionary
mutable dictionary* dict_;
//! Track that parent dictionary was set
bool hasDict_;
//! The calculation result
scalar val;
//! token -> scalar
scalar getScalar() const
{
@ -99,11 +104,11 @@ static const int debug = 0;
return s;
}
//! attach a dictionary
void dict(const dictionary& dict) const
void dict(const dictionary& dict)
{
dict_ = const_cast<dictionary*>(&dict);
hasDict_ = true;
}
@ -112,11 +117,11 @@ static const int debug = 0;
{
scalar dictValue = 0;
if (!dict_)
if (!hasDict_)
{
FatalErrorIn
(
"SimpleCalc::getDictEntry() const"
"calcEntry::getDictEntry() const"
) << "No dictionary attached!"
<< exit(FatalError);
@ -140,13 +145,22 @@ static const int debug = 0;
entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false);
if (entryPtr && !entryPtr->isDict())
{
if (entryPtr->stream().size() != 1)
{
FatalErrorIn
(
"calcEntry::getDictEntry() const"
) << "keyword " << keyword << " has "
<< entryPtr->stream().size() << " values in dictionary "
<< exit(FatalError);
}
entryPtr->stream() >> dictValue;
}
else
{
FatalErrorIn
(
"SimpleCalc::getDictEntry() const"
"calcEntry::getDictEntry() const"
) << "keyword " << keyword << " is undefined in dictionary "
<< exit(FatalError);
}
@ -161,7 +175,7 @@ static const int debug = 0;
}
// * * * * * * * * * * * * * * * CHARACTERS * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*/
@ -174,7 +188,7 @@ static const int debug = 0;
~Parser(); //!< Destructor - cleanup errors and dummyToken
void SemErr(const wchar_t* msg); //!< Handle semantic error
void SimpleCalc();
void calcEntry();
void Expr(scalar& val);
void Term(scalar& val);
void Factor(scalar& val);

View File

@ -1,9 +1,16 @@
#include <memory.h>
#include <string.h>
#include <sstream>
#include "calcEntryScanner.h"
// values for the file stream buffering
#define MIN_BUFFER_LENGTH 1024 // 1KB
#define MAX_BUFFER_LENGTH (64*MIN_BUFFER_LENGTH) // 64KB
// value for the heap management
#define HEAP_BLOCK_SIZE (64*1024) // 64KB
namespace Foam {
namespace functionEntries {
namespace calcEntryInternal {
@ -36,29 +43,6 @@ wchar_t* coco_string_create(const wchar_t* str, int index, int length) {
return dest;
}
wchar_t* coco_string_create_upper(const wchar_t* str) {
if (!str) { return NULL; }
return coco_string_create_upper(str, 0, wcslen(str));
}
wchar_t* coco_string_create_upper(const wchar_t* str, int index, int len) {
if (!str) { return NULL; }
wchar_t* dest = new wchar_t[len + 1];
for (int i = 0; i < len; i++) {
const wchar_t ch = str[index + i];
if ((L'a' <= ch) && (ch <= L'z')) {
dest[i] = ch + (L'A' - L'a');
}
else {
dest[i] = ch;
}
}
dest[len] = L'\0';
return dest;
}
wchar_t* coco_string_create_lower(const wchar_t* str) {
if (!str) { return NULL; }
@ -178,7 +162,7 @@ wchar_t* coco_string_create(const char* str) {
int len = str ? strlen(str) : 0;
wchar_t* dest = new wchar_t[len + 1];
for (int i = 0; i < len; ++i) {
dest[i] = (wchar_t) str[i];
dest[i] = wchar_t(str[i]);
}
dest[len] = 0;
return dest;
@ -188,7 +172,7 @@ wchar_t* coco_string_create(const char* str, int index, int length) {
int len = str ? length : 0;
wchar_t* dest = new wchar_t[len + 1];
for (int i = 0; i < len; ++i) {
dest[i] = (wchar_t) str[index + i];
dest[i] = wchar_t(str[index + i]);
}
dest[len] = 0;
return dest;
@ -200,7 +184,7 @@ char* coco_string_create_char(const wchar_t* str) {
char *dest = new char[len + 1];
for (int i = 0; i < len; ++i)
{
dest[i] = (char) str[i];
dest[i] = char(str[i]);
}
dest[len] = 0;
return dest;
@ -213,7 +197,7 @@ char* coco_string_create_char(const wchar_t* str, int index, int length) {
}
char *dest = new char[len + 1];
for (int i = 0; i < len; ++i) {
dest[i] = (char) str[index + i];
dest[i] = char(str[index + i]);
}
dest[len] = 0;
return dest;
@ -251,27 +235,61 @@ Token::Token()
{}
// Note: this delete may not be correct if the token was actually
// allocated by the internal heap mechanism
Token::~Token() {
coco_string_delete(val);
}
Buffer::Buffer(FILE* s, bool isUserStream) {
// ----------------------------------------------------------------------------
// Buffer Implementation
// ----------------------------------------------------------------------------
Buffer::Buffer(Buffer* b)
:
buf(b->buf),
bufCapacity(b->bufCapacity),
bufLen(b->bufLen),
bufPos(b->bufPos),
bufStart(b->bufStart),
fileLen(b->fileLen),
cStream(b->cStream),
stdStream(b->stdStream),
isUserStream_(b->isUserStream_)
{
// avoid accidental deletion on any of these members
b->buf = NULL;
b->cStream = NULL;
b->stdStream = NULL;
}
Buffer::Buffer(FILE* istr, bool isUserStream)
:
buf(NULL),
bufCapacity(0),
bufLen(0),
bufPos(0),
bufStart(0),
fileLen(0),
cStream(istr),
stdStream(NULL),
isUserStream_(isUserStream)
{
// ensure binary read on windows
#if _MSC_VER >= 1300
_setmode(_fileno(s), _O_BINARY);
_setmode(_fileno(cStream), _O_BINARY);
#endif
stream = s; this->isUserStream = isUserStream;
if (CanSeek()) {
fseek(s, 0, SEEK_END);
fileLen = ftell(s);
fseek(s, 0, SEEK_SET);
fseek(cStream, 0, SEEK_END);
fileLen = ftell(cStream);
fseek(cStream, 0, SEEK_SET);
bufLen = (fileLen < MAX_BUFFER_LENGTH) ? fileLen : MAX_BUFFER_LENGTH;
bufStart = INT_MAX; // nothing in the buffer so far
}
else {
fileLen = bufLen = bufStart = 0;
}
bufCapacity = (bufLen > 0) ? bufLen : MIN_BUFFER_LENGTH;
buf = new unsigned char[bufCapacity];
if (fileLen > 0) SetPos(0); // setup buffer to position 0 (start)
@ -280,45 +298,74 @@ Buffer::Buffer(FILE* s, bool isUserStream) {
}
Buffer::Buffer(Buffer* b) {
buf = b->buf;
bufCapacity = b->bufCapacity;
b->buf = NULL;
bufStart = b->bufStart;
bufLen = b->bufLen;
fileLen = b->fileLen;
bufPos = b->bufPos;
stream = b->stream;
b->stream = NULL;
isUserStream = b->isUserStream;
Buffer::Buffer(std::istream* istr, bool isUserStream)
:
buf(NULL),
bufCapacity(0),
bufLen(0),
bufPos(0),
bufStart(0),
fileLen(0),
cStream(NULL),
stdStream(istr),
isUserStream_(isUserStream)
{
// ensure binary read on windows
#if _MSC_VER >= 1300
// TODO
#endif
}
Buffer::Buffer(const unsigned char* buf, int len) {
this->buf = new unsigned char[len];
memcpy(this->buf, buf, len*sizeof(unsigned char));
bufStart = 0;
bufCapacity = bufLen = len;
fileLen = len;
bufPos = 0;
stream = NULL;
Buffer::Buffer(std::string& str)
:
buf(NULL),
bufCapacity(0),
bufLen(0),
bufPos(0),
bufStart(0),
fileLen(0),
cStream(NULL),
stdStream(new std::istringstream(str)),
isUserStream_(false)
{}
Buffer::Buffer(const unsigned char* chars, int len)
:
buf(new unsigned char[len]),
bufCapacity(len),
bufLen(len),
bufPos(0),
bufStart(0),
fileLen(len),
cStream(NULL),
stdStream(NULL),
isUserStream_(false)
{
memcpy(this->buf, chars, len*sizeof(char));
}
Buffer::Buffer(const char* buf, int len) {
this->buf = new unsigned char[len];
memcpy(this->buf, buf, len*sizeof(unsigned char));
bufStart = 0;
bufCapacity = bufLen = len;
fileLen = len;
bufPos = 0;
stream = NULL;
Buffer::Buffer(const char* chars, int len)
:
buf(new unsigned char[len]),
bufCapacity(len),
bufLen(len),
bufPos(0),
bufStart(0),
fileLen(len),
cStream(NULL),
stdStream(NULL),
isUserStream_(false)
{
memcpy(this->buf, chars, len*sizeof(char));
}
Buffer::~Buffer() {
Close();
if (buf != NULL) {
if (buf) {
delete [] buf;
buf = NULL;
}
@ -326,20 +373,36 @@ Buffer::~Buffer() {
void Buffer::Close() {
if (!isUserStream && stream != NULL) {
fclose(stream);
stream = NULL;
if (!isUserStream_) {
if (cStream) {
fclose(cStream);
cStream = NULL;
}
else if (stdStream) {
delete stdStream;
stdStream = 0;
}
}
}
int Buffer::Read() {
if (stdStream)
{
int ch = stdStream->get();
if (stdStream->eof())
{
return EoF;
}
return ch;
}
if (bufPos < bufLen) {
return buf[bufPos++];
} else if (GetPos() < fileLen) {
SetPos(GetPos()); // shift buffer start to Pos
return buf[bufPos++];
} else if ((stream != NULL) && !CanSeek() && (ReadNextStreamChunk() > 0)) {
} else if (cStream && !CanSeek() && (ReadNextStreamChunk() > 0)) {
return buf[bufPos++];
} else {
return EoF;
@ -347,91 +410,6 @@ int Buffer::Read() {
}
int Buffer::Peek() {
int curPos = GetPos();
int ch = Read();
SetPos(curPos);
return ch;
}
wchar_t* Buffer::GetString(int beg, int end) {
int len = 0;
wchar_t *buf = new wchar_t[end - beg];
int oldPos = GetPos();
SetPos(beg);
while (GetPos() < end) buf[len++] = (wchar_t) Read();
SetPos(oldPos);
wchar_t *res = coco_string_create(buf, 0, len);
coco_string_delete(buf);
return res;
}
int Buffer::GetPos() {
return bufPos + bufStart;
}
void Buffer::SetPos(int value) {
if ((value >= fileLen) && (stream != NULL) && !CanSeek()) {
// Wanted position is after buffer and the stream
// is not seek-able e.g. network or console,
// thus we have to read the stream manually till
// the wanted position is in sight.
while ((value >= fileLen) && (ReadNextStreamChunk() > 0))
{}
}
if ((value < 0) || (value > fileLen)) {
wprintf(L"--- buffer out of bounds access, position: %d\n", value);
::exit(1);
}
if ((value >= bufStart) && (value < (bufStart + bufLen))) { // already in buffer
bufPos = value - bufStart;
} else if (stream != NULL) { // must be swapped in
fseek(stream, value, SEEK_SET);
bufLen = fread(buf, sizeof(unsigned char), bufCapacity, stream);
bufStart = value; bufPos = 0;
} else {
bufPos = fileLen - bufStart; // make Pos return fileLen
}
}
// Read the next chunk of bytes from the stream, increases the buffer
// if needed and updates the fields fileLen and bufLen.
// Returns the number of bytes read.
int Buffer::ReadNextStreamChunk() {
int freeLen = bufCapacity - bufLen;
if (freeLen == 0) {
// in the case of a growing input stream
// we can neither seek in the stream, nor can we
// foresee the maximum length, thus we must adapt
// the buffer size on demand.
bufCapacity = bufLen * 2;
unsigned char *newBuf = new unsigned char[bufCapacity];
memcpy(newBuf, buf, bufLen*sizeof(unsigned char));
delete [] buf;
buf = newBuf;
freeLen = bufLen;
}
int read = fread(buf + bufLen, sizeof(unsigned char), freeLen, stream);
if (read > 0) {
fileLen = bufLen = (bufLen + read);
return read;
}
// end of stream reached
return 0;
}
bool Buffer::CanSeek() {
return (stream != NULL) && (ftell(stream) != -1);
}
int UTF8Buffer::Read() {
int ch;
do {
@ -464,42 +442,143 @@ int UTF8Buffer::Read() {
}
Scanner::Scanner(const unsigned char* buf, int len) {
buffer = new Buffer(buf, len);
int Buffer::Peek() {
int curPos = GetPos();
int ch = Read();
SetPos(curPos);
return ch;
}
int Buffer::GetPos() const {
if (stdStream)
{
return stdStream->tellg();
}
return bufPos + bufStart;
}
void Buffer::SetPos(int value) {
if (stdStream)
{
stdStream->seekg(value, std::ios::beg);
return;
}
if ((value >= fileLen) && cStream && !CanSeek()) {
// Wanted position is after buffer and the stream
// is not seek-able e.g. network or console,
// thus we have to read the stream manually till
// the wanted position is in sight.
while ((value >= fileLen) && (ReadNextStreamChunk() > 0))
{}
}
if ((value < 0) || (value > fileLen)) {
wprintf(L"--- buffer out of bounds access, position: %d\n", value);
::exit(1);
}
if ((value >= bufStart) && (value < (bufStart + bufLen))) { // already in buffer
bufPos = value - bufStart;
} else if (cStream) { // must be swapped in
fseek(cStream, value, SEEK_SET);
bufLen = fread(buf, sizeof(char), bufCapacity, cStream);
bufStart = value; bufPos = 0;
} else {
bufPos = fileLen - bufStart; // make Pos return fileLen
}
}
// Read the next chunk of bytes from the stream, increases the buffer
// if needed and updates the fields fileLen and bufLen.
// Returns the number of bytes read.
int Buffer::ReadNextStreamChunk() {
int freeLen = bufCapacity - bufLen;
if (freeLen == 0) {
// in the case of a growing input stream
// we can neither seek in the stream, nor can we
// foresee the maximum length, thus we must adapt
// the buffer size on demand.
bufCapacity = bufLen * 2;
unsigned char *newBuf = new unsigned char[bufCapacity];
memcpy(newBuf, buf, bufLen*sizeof(char));
delete [] buf;
buf = newBuf;
freeLen = bufLen;
}
int read = fread(buf + bufLen, sizeof(char), freeLen, cStream);
if (read > 0) {
fileLen = bufLen = (bufLen + read);
return read;
}
// end of stream reached
return 0;
}
bool Buffer::CanSeek() const {
return cStream && (ftell(cStream) != -1);
}
// ----------------------------------------------------------------------------
// Scanner Implementation
// ----------------------------------------------------------------------------
Scanner::Scanner(FILE* istr)
:
buffer(new Buffer(istr, true))
{
Init();
}
Scanner::Scanner(const char* buf, int len) {
buffer = new Buffer(buf, len);
Scanner::Scanner(std::istream& istr)
:
buffer(new Buffer(&istr, true))
{
Init();
}
Scanner::Scanner(const wchar_t* fileName) {
FILE* stream;
char *chFileName = coco_string_create_char(fileName);
if ((stream = fopen(chFileName, "rb")) == NULL) {
FILE* istr;
if ((istr = fopen(chFileName, "rb")) == NULL) {
wprintf(L"--- Cannot open file %ls\n", fileName);
::exit(1);
}
coco_string_delete(chFileName);
buffer = new Buffer(stream, false);
buffer = new Buffer(istr, false);
Init();
}
Scanner::Scanner(FILE* s) {
buffer = new Buffer(s, true);
Scanner::Scanner(const unsigned char* buf, int len)
:
buffer(new Buffer(buf, len))
{
Init();
}
Scanner::Scanner(const char* buf, int len)
:
buffer(new Buffer(buf, len))
{
Init();
}
Scanner::~Scanner() {
char* cur = (char*) firstHeap;
char* cur = reinterpret_cast<char*>(firstHeap);
while (cur != NULL) {
cur = *(char**) (cur + HEAP_BLOCK_SIZE);
while (cur) {
cur = *(reinterpret_cast<char**>(cur + HEAP_BLOCK_SIZE));
free(firstHeap);
firstHeap = cur;
}
@ -509,14 +588,11 @@ Scanner::~Scanner() {
void Scanner::Init() {
maxT = 13;
noSym = 13;
int i;
for (i = 65; i <= 90; ++i) start.set(i, 1);
for (i = 97; i <= 122; ++i) start.set(i, 1);
for (i = 36; i <= 36; ++i) start.set(i, 5);
for (int i = 65; i <= 90; ++i) start.set(i, 1);
for (int i = 97; i <= 122; ++i) start.set(i, 1);
for (int i = 36; i <= 36; ++i) start.set(i, 5);
start.set(45, 20);
for (i = 48; i <= 57; ++i) start.set(i, 9);
for (int i = 48; i <= 57; ++i) start.set(i, 9);
start.set(34, 2);
start.set(46, 7);
start.set(123, 14);
@ -526,7 +602,8 @@ void Scanner::Init() {
start.set(47, 17);
start.set(40, 18);
start.set(41, 19);
start.set(Buffer::EoF, -1);
start.set(Buffer::EoF, -1);
tvalLength = 128;
@ -535,7 +612,9 @@ void Scanner::Init() {
// HEAP_BLOCK_SIZE byte heap + pointer to next heap block
heap = malloc(HEAP_BLOCK_SIZE + sizeof(void*));
firstHeap = heap;
heapEnd = (void**) (((char*) heap) + HEAP_BLOCK_SIZE);
heapEnd =
reinterpret_cast<void**>
(reinterpret_cast<char*>(heap) + HEAP_BLOCK_SIZE);
*heapEnd = 0;
heapTop = heap;
if (sizeof(Token) > HEAP_BLOCK_SIZE) {
@ -645,19 +724,25 @@ bool Scanner::Comment1() {
void Scanner::CreateHeapBlock() {
void* newHeap;
char* cur = (char*) firstHeap;
char* cur = reinterpret_cast<char*>(firstHeap);
while (((char*) tokens < cur) || ((char*) tokens > (cur + HEAP_BLOCK_SIZE))) {
cur = *((char**) (cur + HEAP_BLOCK_SIZE));
// release unused blocks
while
(
(reinterpret_cast<char*>(tokens) < cur)
|| (reinterpret_cast<char*>(tokens) > (cur + HEAP_BLOCK_SIZE))
) {
cur = *(reinterpret_cast<char**>(cur + HEAP_BLOCK_SIZE));
free(firstHeap);
firstHeap = cur;
}
// HEAP_BLOCK_SIZE byte heap + pointer to next heap block
newHeap = malloc(HEAP_BLOCK_SIZE + sizeof(void*));
void* newHeap = malloc(HEAP_BLOCK_SIZE + sizeof(void*));
*heapEnd = newHeap;
heapEnd = (void**) (((char*) newHeap) + HEAP_BLOCK_SIZE);
heapEnd =
reinterpret_cast<void**>
(reinterpret_cast<char*>(newHeap) + HEAP_BLOCK_SIZE);
*heapEnd = 0;
heap = newHeap;
heapTop = heap;
@ -665,38 +750,57 @@ void Scanner::CreateHeapBlock() {
Token* Scanner::CreateToken() {
Token *t;
if (((char*) heapTop + (int) sizeof(Token)) >= (char*) heapEnd) {
const int reqMem = sizeof(Token);
if
(
(reinterpret_cast<char*>(heapTop) + reqMem)
>= reinterpret_cast<char*>(heapEnd)
) {
CreateHeapBlock();
}
t = (Token*) heapTop;
heapTop = (void*) ((char*) heapTop + sizeof(Token));
t->val = NULL;
t->next = NULL;
return t;
// token 'occupies' heap starting at heapTop
Token* tok = reinterpret_cast<Token*>(heapTop);
// increment past this part of the heap, which is now used
heapTop =
reinterpret_cast<void*>
(reinterpret_cast<char*>(heapTop) + reqMem);
tok->val = NULL;
tok->next = NULL;
return tok;
}
void Scanner::AppendVal(Token *t) {
int reqMem = (tlen + 1) * sizeof(wchar_t);
if (((char*) heapTop + reqMem) >= (char*) heapEnd) {
void Scanner::AppendVal(Token* tok) {
const int reqMem = (tlen + 1) * sizeof(wchar_t);
if
(
(reinterpret_cast<char*>(heapTop) + reqMem)
>= reinterpret_cast<char*>(heapEnd)
) {
if (reqMem > HEAP_BLOCK_SIZE) {
wprintf(L"--- Too long token value\n");
::exit(1);
}
CreateHeapBlock();
}
t->val = (wchar_t*) heapTop;
heapTop = (void*) ((char*) heapTop + reqMem);
wcsncpy(t->val, tval, tlen);
t->val[tlen] = L'\0';
// add text value from heap
tok->val = reinterpret_cast<wchar_t*>(heapTop);
// increment past this part of the heap, which is now used
heapTop =
reinterpret_cast<void*>
(reinterpret_cast<char*>(heapTop) + reqMem);
// copy the currently parsed tval into the token
wcsncpy(tok->val, tval, tlen);
tok->val[tlen] = L'\0';
}
Token* Scanner::NextToken() {
while (ch == ' ' ||
ch <= 31 || (ch >= 127 && ch <= 65535)
(ch >= 9 && ch <= 10) || ch == 13
) NextCh();
if ((ch == L'/' && Comment0()) || (ch == L'/' && Comment1())) return NextToken();
t = CreateToken();
@ -818,8 +922,11 @@ void Scanner::ResetPeek() {
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // namespace
} // namespace
} // namespace
// ************************************************************************* //

View File

@ -3,11 +3,14 @@
#ifndef COCO_calcEntrySCANNER_H__
#define COCO_calcEntrySCANNER_H__
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cwchar>
#include <string>
#include <fstream>
#include <iostream>
// io.h and fcntl are used to ensure binary read from streams on windows
#if _MSC_VER >= 1300
@ -24,10 +27,8 @@
#define coco_swprintf swprintf
#endif
#define COCO_WCHAR_MAX 65535
#define MIN_BUFFER_LENGTH 1024
#define MAX_BUFFER_LENGTH (64*MIN_BUFFER_LENGTH)
#define HEAP_BLOCK_SIZE (64*1024)
namespace Foam {
@ -48,12 +49,6 @@ wchar_t* coco_string_create(const wchar_t* str);
//! Create a substring of str starting at index and length characters long
wchar_t* coco_string_create(const wchar_t* str, int index, int length);
//! Create an uppercase string from str
wchar_t* coco_string_create_upper(const wchar_t* str);
//! Create an uppercase substring from str starting at index and length characters long
wchar_t* coco_string_create_upper(const wchar_t* str, int index, int length);
//! Create a lowercase string from str
wchar_t* coco_string_create_lower(const wchar_t* str);
@ -138,7 +133,6 @@ float coco_string_toFloat(const char* str);
// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * //
//! Scanner Token
class Token
{
@ -151,7 +145,7 @@ public:
Token *next; //!< Peek tokens are kept in linked list
Token(); //!< Construct null
~Token(); //!< Destructor - cleanup allocated val
~Token(); //!< Destructor - cleanup allocated val??
};
@ -166,30 +160,48 @@ class Buffer {
private:
unsigned char *buf; //!< input buffer
int bufCapacity; //!< capacity of buf
int bufStart; //!< position of first byte in buffer relative to input stream
int bufLen; //!< length of buffer
int fileLen; //!< length of input stream (may change if the stream is no file)
int bufPos; //!< current position in buffer
FILE* stream; //!< input stream (seekable)
bool isUserStream; //!< was the stream opened by the user?
int bufStart; //!< position of first byte in buffer relative to input stream
int fileLen; //!< length of input stream (may change if the stream is no file)
FILE* cStream; //!< input stdio stream (normally seekable)
std::istream* stdStream; //!< STL std stream (seekable)
bool isUserStream_; //!< was the stream opened by the user?
int ReadNextStreamChunk();
bool CanSeek(); //!< true if stream can be seeked otherwise false
bool CanSeek() const; //!< true if stream can be seeked otherwise false
protected:
Buffer(Buffer*); //!< for the UTF8Buffer
public:
static const int EoF = COCO_WCHAR_MAX + 1;
Buffer(FILE*, bool isUserStream);
Buffer(const unsigned char* buf, int len);
Buffer(const char* buf, int len);
Buffer(Buffer*);
//! Attach buffer to a stdio stream.
//! User streams are not closed in the destructor
Buffer(FILE*, bool isUserStream = true);
//! Attach buffer to an STL std stream
//! User streams are not closed in the destructor
explicit Buffer(std::istream*, bool isUserStream = true);
//! Copy buffer contents from constant string
//! Handled internally as an istringstream
explicit Buffer(std::string&);
//! Copy buffer contents from constant character string
Buffer(const unsigned char* chars, int len);
//! Copy buffer contents from constant character string
Buffer(const char* chars, int len);
//! Close stream (but not user streams) and free buf (if any)
virtual ~Buffer();
virtual void Close();
virtual int Read();
virtual int Peek();
virtual wchar_t* GetString(int beg, int end);
virtual int GetPos();
virtual void Close(); //!< Close stream (but not user streams)
virtual int Read(); //!< Get character from stream or buffer
virtual int Peek(); //!< Peek character from stream or buffer
virtual int GetPos() const;
virtual void SetPos(int value);
};
@ -205,31 +217,31 @@ public:
//------------------------------------------------------------------------------
// StartStates
//------------------------------------------------------------------------------
//! maps characters to start states of tokens
//! maps characters (integers) to start states of tokens
class StartStates {
private:
class Elem {
public:
int key, val;
Elem *next;
Elem(int key, int val) {
this->key = key;
this->val = val;
next = NULL;
}
Elem(int k, int v) :
key(k), val(v), next(0)
{}
};
Elem **tab;
public:
StartStates() {
tab = new Elem*[128];
StartStates() :
tab(new Elem*[128])
{
memset(tab, 0, 128 * sizeof(Elem*));
}
virtual ~StartStates() {
for (int i = 0; i < 128; ++i) {
Elem *e = tab[i];
while (e != NULL) {
while (e) {
Elem *next = e->next;
delete e;
e = next;
@ -240,15 +252,15 @@ public:
void set(int key, int val) {
Elem *e = new Elem(key, val);
int k = ((unsigned int) key) % 128;
int k = unsigned(key) % 128;
e->next = tab[k];
tab[k] = e;
}
int state(int key) {
Elem *e = tab[((unsigned int) key) % 128];
while (e != NULL && e->key != key) e = e->next;
return e == NULL ? 0 : e->val;
Elem *e = tab[unsigned(key) % 128];
while (e && e->key != key) e = e->next;
return e ? e->val : 0;
}
};
@ -264,11 +276,9 @@ private:
wchar_t *key;
int val;
Elem *next;
Elem(const wchar_t *key, int val) {
this->key = coco_string_create(key);
this->val = val;
next = NULL;
}
Elem(const wchar_t *k, int v) :
key(coco_string_create(k)), val(v), next(0)
{}
virtual ~Elem() {
coco_string_delete(key);
}
@ -277,14 +287,16 @@ private:
Elem **tab;
public:
KeywordMap() {
tab = new Elem*[128];
KeywordMap() :
tab(new Elem*[128])
{
memset(tab, 0, 128 * sizeof(Elem*));
}
virtual ~KeywordMap() {
for (int i = 0; i < 128; ++i) {
Elem *e = tab[i];
while (e != NULL) {
while (e) {
Elem *next = e->next;
delete e;
e = next;
@ -295,14 +307,15 @@ public:
void set(const wchar_t *key, int val) {
Elem *e = new Elem(key, val);
int k = coco_string_hash(key) % 128;
e->next = tab[k]; tab[k] = e;
const int k = coco_string_hash(key) % 128;
e->next = tab[k];
tab[k] = e;
}
int get(const wchar_t *key, int defaultVal) {
Elem *e = tab[coco_string_hash(key) % 128];
while (e != NULL && !coco_string_equal(e->key, key)) e = e->next;
return e == NULL ? defaultVal : e->val;
while (e && !coco_string_equal(e->key, key)) e = e->next;
return e ? e->val : defaultVal;
}
};
@ -310,24 +323,24 @@ public:
//! A Coco/R Scanner
class Scanner {
private:
static const unsigned char EOL = '\n'; // end-of-line character
static const int eofSym = 0; // end-of-file token id
static const int maxT = 13;
static const int noSym = 13;
void *firstHeap;
void *heap;
void *heapTop;
void **heapEnd;
static const int eofSym = 0; //!< end-of-file token id
static const char EOL = '\n'; //!< end-of-line character
int noSym; //!< noSym gets highest number, set in Parser
int maxT;
int charSetSize; //!< unused?
StartStates start;
KeywordMap keywords;
void *firstHeap; //!< the start of the heap management
void *heap; //!< the currently active block
void *heapTop; //!< the top of the heap
void **heapEnd; //!< the end of the last heap block
StartStates start; //!< A map of start states for particular characters
KeywordMap keywords; //!< A hash of keyword literals to token kind
Token *t; //!< current token
wchar_t *tval; //!< text of current token
int tvalLength; //!< length of text of current token
int tlen; //!< length of current token
int tvalLength; //!< maximum capacity (length) for tval
int tlen; //!< length of tval
Token *tokens; //!< list of tokens already peeked (first token is a dummy)
Token *pt; //!< current peek token
@ -337,36 +350,42 @@ private:
int pos; //!< byte position of current character
int line; //!< line number of current character
int col; //!< column number of current character
int oldEols; //!< EOLs that appeared in a comment;
int oldEols; //!< the number of EOLs that appeared in a comment
void CreateHeapBlock();
Token* CreateToken();
void AppendVal(Token*);
void CreateHeapBlock(); //!< add a heap block, freeing unused ones
Token* CreateToken(); //!< fit token on the heap
void AppendVal(Token* tok); //!< adjust tok->val to point to the heap and copy tval into it
void Init();
void NextCh();
void AddCh();
void Init(); //!< complete the initialization for the constructors
void NextCh(); //!< get the next input character into ch
void AddCh(); //!< append the character ch to tval
bool Comment0();
bool Comment1();
Token* NextToken();
Token* NextToken(); //!< get the next token
public:
//! scanner buffer
//! The scanner buffer
Buffer *buffer;
//! Attach scanner to an existing character buffer
Scanner(const unsigned char* buf, int len);
//! Attach scanner to an existing character buffer
Scanner(const char* buf, int len);
//! Open a file for reading and attach scanner
Scanner(const wchar_t* fileName);
//! Using an existing open file handle for the scanner
Scanner(FILE* s);
~Scanner();
Token* Scan();
Token* Peek();
void ResetPeek();
Scanner(FILE*);
//! Using an existing open STL std stream
explicit Scanner(std::istream&);
//! Open a file for reading and attach scanner
explicit Scanner(const wchar_t* fileName);
//! Attach scanner to an existing character buffer
Scanner(const unsigned char* chars, int len);
//! Attach scanner to an existing character buffer
Scanner(const char* chars, int len);
~Scanner(); //!< free heap and allocated memory
Token* Scan(); //!< get the next token (possibly a token already seen during peeking)
Token* Peek(); //!< peek for the next token, ignore pragmas
void ResetPeek(); //!< ensure that peeking starts at the current scan position
}; // end Scanner

View File

@ -67,7 +67,6 @@ boundaryField
// error #remove self;
x 5;
y 6;
another #calc{x $x; y $y;};
}
// this should have no effect

View File

@ -14,8 +14,11 @@ FoamFile
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
x 10 /* what ever */ 20;
flowRatePerHour 720;
x 10;
y 20;
z t s v;
// z #test{ // this
// 123 - 456
// // comments // are
@ -26,8 +29,18 @@ y 20;
// + 1 /*100 */ 10
// };
p #test{ 1 + 2 + 10 * 15 + $x - $y };
p this calculation #calc{
1 + 2 + 10 * 15 +
$x - $y
// $x + $y
}
is done inplace;
foo 30;
flowRate #calc{ $flowRatePerHour / 3600};
xxx yyy;
foo 30;
bar 15;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -27,12 +27,14 @@ Application
Description
Calculates the inertia tensor and principal axes and moments of a
test face.
test face and tetrahedron.
\*---------------------------------------------------------------------------*/
#include "ListOps.H"
#include "face.H"
#include "tetPointRef.H"
#include "triFaceList.H"
#include "OFstream.H"
#include "meshTools.H"
@ -40,67 +42,310 @@ Description
using namespace Foam;
void massPropertiesSolid
(
const pointField& pts,
const triFaceList triFaces,
scalar density,
scalar& mass,
vector& cM,
tensor& J
)
{
// Reimplemented from: Wm4PolyhedralMassProperties.cpp
// File Version: 4.10.0 (2009/11/18)
// Geometric Tools, LC
// Copyright (c) 1998-2010
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
// Boost Software License - Version 1.0 - August 17th, 2003
// Permission is hereby granted, free of charge, to any person or
// organization obtaining a copy of the software and accompanying
// documentation covered by this license (the "Software") to use,
// reproduce, display, distribute, execute, and transmit the
// Software, and to prepare derivative works of the Software, and
// to permit third-parties to whom the Software is furnished to do
// so, all subject to the following:
// The copyright notices in the Software and this entire
// statement, including the above license grant, this restriction
// and the following disclaimer, must be included in all copies of
// the Software, in whole or in part, and all derivative works of
// the Software, unless such copies or derivative works are solely
// in the form of machine-executable object code generated by a
// source language processor.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
// NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
// ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
// OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
const scalar r6 = 1.0/6.0;
const scalar r24 = 1.0/24.0;
const scalar r60 = 1.0/60.0;
const scalar r120 = 1.0/120.0;
// order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
scalarField integrals(10, 0.0);
forAll(triFaces, i)
{
const triFace& tri(triFaces[i]);
// vertices of triangle i
vector v0 = pts[tri[0]];
vector v1 = pts[tri[1]];
vector v2 = pts[tri[2]];
// cross product of edges
vector eA = v1 - v0;
vector eB = v2 - v0;
vector n = eA ^ eB;
// compute integral terms
scalar tmp0, tmp1, tmp2;
scalar f1x, f2x, f3x, g0x, g1x, g2x;
tmp0 = v0.x() + v1.x();
f1x = tmp0 + v2.x();
tmp1 = v0.x()*v0.x();
tmp2 = tmp1 + v1.x()*tmp0;
f2x = tmp2 + v2.x()*f1x;
f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
g0x = f2x + v0.x()*(f1x + v0.x());
g1x = f2x + v1.x()*(f1x + v1.x());
g2x = f2x + v2.x()*(f1x + v2.x());
scalar f1y, f2y, f3y, g0y, g1y, g2y;
tmp0 = v0.y() + v1.y();
f1y = tmp0 + v2.y();
tmp1 = v0.y()*v0.y();
tmp2 = tmp1 + v1.y()*tmp0;
f2y = tmp2 + v2.y()*f1y;
f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
g0y = f2y + v0.y()*(f1y + v0.y());
g1y = f2y + v1.y()*(f1y + v1.y());
g2y = f2y + v2.y()*(f1y + v2.y());
scalar f1z, f2z, f3z, g0z, g1z, g2z;
tmp0 = v0.z() + v1.z();
f1z = tmp0 + v2.z();
tmp1 = v0.z()*v0.z();
tmp2 = tmp1 + v1.z()*tmp0;
f2z = tmp2 + v2.z()*f1z;
f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
g0z = f2z + v0.z()*(f1z + v0.z());
g1z = f2z + v1.z()*(f1z + v1.z());
g2z = f2z + v2.z()*(f1z + v2.z());
// update integrals
integrals[0] += n.x()*f1x;
integrals[1] += n.x()*f2x;
integrals[2] += n.y()*f2y;
integrals[3] += n.z()*f2z;
integrals[4] += n.x()*f3x;
integrals[5] += n.y()*f3y;
integrals[6] += n.z()*f3z;
integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
}
integrals[0] *= r6;
integrals[1] *= r24;
integrals[2] *= r24;
integrals[3] *= r24;
integrals[4] *= r60;
integrals[5] *= r60;
integrals[6] *= r60;
integrals[7] *= r120;
integrals[8] *= r120;
integrals[9] *= r120;
// mass
mass = integrals[0];
// center of mass
cM = vector(integrals[1], integrals[2], integrals[3])/mass;
// inertia relative to origin
J.xx() = integrals[5] + integrals[6];
J.xy() = -integrals[7];
J.xz() = -integrals[9];
J.yx() = J.xy();
J.yy() = integrals[4] + integrals[6];
J.yz() = -integrals[8];
J.zx() = J.xz();
J.zy() = J.yz();
J.zz() = integrals[4] + integrals[5];
// inertia relative to center of mass
J -= mass*((cM & cM)*I - cM*cM);
// Apply density
mass *= density;
J *= density;
}
int main(int argc, char *argv[])
{
label nPts = 6;
pointField pts(nPts);
pts[0] = point(4.495, 3.717, -4.112);
pts[1] = point(4.421, 3.932, -4.112);
pts[2] = point(4.379, 4.053, -4.112);
pts[3] = point(4.301, 4.026, -4.300);
pts[4] = point(4.294, 4.024, -4.317);
pts[5] = point(4.409, 3.687, -4.317);
scalar density = 1.0;
face f(identity(nPts));
point Cf = f.centre(pts);
tensor J = tensor::zero;
J = f.inertia(pts, Cf, density);
vector eVal = eigenValues(J);
tensor eVec = eigenVectors(J);
Info<< nl << "Inertia tensor of test face " << J << nl
<< "eigenValues (principal moments) " << eVal << nl
<< "eigenVectors (principal axes) " << eVec
<< endl;
OFstream str("momentOfInertiaTest.obj");
Info<< nl << "Writing test face and scaled principal axes to "
<< str.name() << endl;
forAll(pts, ptI)
{
meshTools::writeOBJ(str, pts[ptI]);
label nPts = 6;
pointField pts(nPts);
pts[0] = point(4.495, 3.717, -4.112);
pts[1] = point(4.421, 3.932, -4.112);
pts[2] = point(4.379, 4.053, -4.112);
pts[3] = point(4.301, 4.026, -4.300);
pts[4] = point(4.294, 4.024, -4.317);
pts[5] = point(4.409, 3.687, -4.317);
face f(identity(nPts));
point Cf = f.centre(pts);
tensor J = tensor::zero;
J = f.inertia(pts, Cf, density);
vector eVal = eigenValues(J);
tensor eVec = eigenVectors(J);
Info<< nl << "Inertia tensor of test face " << J << nl
<< "eigenValues (principal moments) " << eVal << nl
<< "eigenVectors (principal axes) " << eVec
<< endl;
OFstream str("momentOfInertiaTestFace.obj");
Info<< nl << "Writing test face and scaled principal axes to "
<< str.name() << endl;
forAll(pts, ptI)
{
meshTools::writeOBJ(str, pts[ptI]);
}
str << "l";
forAll(f, fI)
{
str << ' ' << fI + 1;
}
str << " 1" << endl;
scalar scale = mag(Cf - pts[f[0]])/eVal.component(findMin(eVal));
meshTools::writeOBJ(str, Cf);
meshTools::writeOBJ(str, Cf + scale*eVal.x()*eVec.x());
meshTools::writeOBJ(str, Cf + scale*eVal.y()*eVec.y());
meshTools::writeOBJ(str, Cf + scale*eVal.z()*eVec.z());
for (label i = nPts + 1; i < nPts + 4; i++)
{
str << "l " << nPts + 1 << ' ' << i + 1 << endl;
}
}
str << "l";
forAll(f, fI)
{
str << ' ' << fI + 1;
}
label nPts = 4;
str << " 1" << endl;
pointField pts(nPts);
scalar scale = mag(Cf - pts[f[0]])/eVal.component(findMin(eVal));
pts[0] = point(0, 0, 0);
pts[1] = point(1, 0, 0);
pts[2] = point(0.5, 1, 0);
pts[3] = point(0.5, 0.5, 1);
meshTools::writeOBJ(str, Cf);
meshTools::writeOBJ(str, Cf + scale*eVal.x()*eVec.x());
meshTools::writeOBJ(str, Cf + scale*eVal.y()*eVec.y());
meshTools::writeOBJ(str, Cf + scale*eVal.z()*eVec.z());
tetPointRef tet(pts[0], pts[1], pts[2], pts[3]);
triFaceList tetFaces(4);
tetFaces[0] = triFace(0, 2, 1);
tetFaces[1] = triFace(1, 2, 3);
tetFaces[2] = triFace(0, 3, 2);
tetFaces[3] = triFace(0, 1, 3);
scalar m = 0.0;
vector cM = vector::zero;
tensor J = tensor::zero;
massPropertiesSolid
(
pts,
tetFaces,
density,
m,
cM,
J
);
vector eVal = eigenValues(J);
tensor eVec = eigenVectors(J);
Info<< nl
<< "Mass of tetrahedron " << m << nl
<< "Centre of mass of tetrahedron " << cM << nl
<< "Inertia tensor of tetrahedron " << J << nl
<< "eigenValues (principal moments) " << eVal << nl
<< "eigenVectors (principal axes) " << eVec
<< endl;
OFstream str("momentOfInertiaTestTet.obj");
Info<< nl << "Writing test tetrahedron and scaled principal axes to "
<< str.name() << endl;
forAll(pts, ptI)
{
meshTools::writeOBJ(str, pts[ptI]);
}
forAll(tetFaces, tFI)
{
const triFace& f = tetFaces[tFI];
str << "l";
forAll(f, fI)
{
str << ' ' << f[fI] + 1;
}
str << ' ' << f[0] + 1 << endl;
}
scalar scale = mag(cM - pts[0])/eVal.component(findMin(eVal));
meshTools::writeOBJ(str, cM);
meshTools::writeOBJ(str, cM + scale*eVal.x()*eVec.x());
meshTools::writeOBJ(str, cM + scale*eVal.y()*eVec.y());
meshTools::writeOBJ(str, cM + scale*eVal.z()*eVec.z());
for (label i = nPts + 1; i < nPts + 4; i++)
{
str << "l " << nPts + 1 << ' ' << i + 1 << endl;
}
for (label i = nPts + 1; i < nPts + 4; i++)
{
str << "l " << nPts + 1 << ' ' << i + 1 << endl;
}
Info<< nl << "End" << nl << endl;

View File

@ -0,0 +1,3 @@
surfaceInertia.C
EXE = $(FOAM_APPBIN)/surfaceInertia

View File

@ -0,0 +1,7 @@
EXE_INC = \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/triSurface/lnInclude
EXE_LIBS = \
-lmeshTools \
-ltriSurface

View File

@ -0,0 +1,296 @@
# Wavefront OBJ file
# Regions:
# 0 movingWall
# 1 fixedWalls
# 2 frontAndBack
#
# points : 96
# triangles : 188
#
v 0.1 0.1 0.5
v 0.1 0.1 0.5625
v 0.16 0.1 0.5625
v 0.16 0.1 0.5
v 0.1 0.1 0.625
v 0.16 0.1 0.625
v 0.1 0.1 0.6875
v 0.16 0.1 0.6875
v 0.1 0.1 0.75
v 0.16 0.1 0.75
v 0.22 0.1 0.5625
v 0.22 0.1 0.5
v 0.22 0.1 0.625
v 0.22 0.1 0.6875
v 0.22 0.1 0.75
v 0.28 0.1 0.5625
v 0.28 0.1 0.5
v 0.28 0.1 0.625
v 0.28 0.1 0.6875
v 0.28 0.1 0.75
v 0.34 0.1 0.5625
v 0.34 0.1 0.5
v 0.34 0.1 0.625
v 0.34 0.1 0.6875
v 0.34 0.1 0.75
v 0.4 0.1 0.5625
v 0.4 0.1 0.5
v 0.4 0.1 0.625
v 0.4 0.1 0.6875
v 0.4 0.1 0.75
v 0.1 -0.3 0.5
v 0.1 -0.3 0.5625
v 0.1 -0.166667 0.5625
v 0.1 -0.166667 0.5
v 0.1 -0.0333333 0.5625
v 0.1 -0.0333333 0.5
v 0.1 -0.3 0.625
v 0.1 -0.166667 0.625
v 0.1 -0.0333333 0.625
v 0.1 -0.3 0.6875
v 0.1 -0.166667 0.6875
v 0.1 -0.0333333 0.6875
v 0.1 -0.3 0.75
v 0.1 -0.166667 0.75
v 0.1 -0.0333333 0.75
v 0.4 -0.3 0.5
v 0.4 -0.166667 0.5
v 0.4 -0.166667 0.5625
v 0.4 -0.3 0.5625
v 0.4 -0.0333333 0.5
v 0.4 -0.0333333 0.5625
v 0.4 -0.166667 0.625
v 0.4 -0.3 0.625
v 0.4 -0.0333333 0.625
v 0.4 -0.166667 0.6875
v 0.4 -0.3 0.6875
v 0.4 -0.0333333 0.6875
v 0.4 -0.166667 0.75
v 0.4 -0.3 0.75
v 0.4 -0.0333333 0.75
v 0.16 -0.3 0.5
v 0.16 -0.3 0.5625
v 0.16 -0.3 0.625
v 0.16 -0.3 0.6875
v 0.16 -0.3 0.75
v 0.22 -0.3 0.5
v 0.22 -0.3 0.5625
v 0.22 -0.3 0.625
v 0.22 -0.3 0.6875
v 0.22 -0.3 0.75
v 0.28 -0.3 0.5
v 0.28 -0.3 0.5625
v 0.28 -0.3 0.625
v 0.28 -0.3 0.6875
v 0.28 -0.3 0.75
v 0.34 -0.3 0.5
v 0.34 -0.3 0.5625
v 0.34 -0.3 0.625
v 0.34 -0.3 0.6875
v 0.34 -0.3 0.75
v 0.16 -0.166667 0.5
v 0.16 -0.0333333 0.5
v 0.22 -0.166667 0.5
v 0.22 -0.0333333 0.5
v 0.28 -0.166667 0.5
v 0.28 -0.0333333 0.5
v 0.34 -0.166667 0.5
v 0.34 -0.0333333 0.5
v 0.16 -0.166667 0.75
v 0.16 -0.0333333 0.75
v 0.22 -0.166667 0.75
v 0.22 -0.0333333 0.75
v 0.28 -0.166667 0.75
v 0.28 -0.0333333 0.75
v 0.34 -0.166667 0.75
v 0.34 -0.0333333 0.75
g movingWall
f 1 2 3
f 3 4 1
f 2 5 6
f 6 3 2
f 5 7 8
f 8 6 5
f 7 9 10
f 10 8 7
f 4 3 11
f 11 12 4
f 3 6 13
f 13 11 3
f 6 8 14
f 14 13 6
f 8 10 15
f 15 14 8
f 12 11 16
f 16 17 12
f 11 13 18
f 18 16 11
f 13 14 19
f 19 18 13
f 14 15 20
f 20 19 14
f 17 16 21
f 21 22 17
f 16 18 23
f 23 21 16
f 18 19 24
f 24 23 18
f 19 20 25
f 25 24 19
f 22 21 26
f 26 27 22
f 21 23 28
f 28 26 21
f 23 24 29
f 29 28 23
f 24 25 30
f 30 29 24
g fixedWalls
f 31 32 33
f 33 34 31
f 34 33 35
f 35 36 34
f 36 35 2
f 2 1 36
f 32 37 38
f 38 33 32
f 33 38 39
f 39 35 33
f 35 39 5
f 5 2 35
f 37 40 41
f 41 38 37
f 38 41 42
f 42 39 38
f 39 42 7
f 7 5 39
f 40 43 44
f 44 41 40
f 41 44 45
f 45 42 41
f 42 45 9
f 9 7 42
f 46 47 48
f 48 49 46
f 47 50 51
f 51 48 47
f 50 27 26
f 26 51 50
f 49 48 52
f 52 53 49
f 48 51 54
f 54 52 48
f 51 26 28
f 28 54 51
f 53 52 55
f 55 56 53
f 52 54 57
f 57 55 52
f 54 28 29
f 29 57 54
f 56 55 58
f 58 59 56
f 55 57 60
f 60 58 55
f 57 29 30
f 30 60 57
f 31 61 62
f 62 32 31
f 32 62 63
f 63 37 32
f 37 63 64
f 64 40 37
f 40 64 65
f 65 43 40
f 61 66 67
f 67 62 61
f 62 67 68
f 68 63 62
f 63 68 69
f 69 64 63
f 64 69 70
f 70 65 64
f 66 71 72
f 72 67 66
f 67 72 73
f 73 68 67
f 68 73 74
f 74 69 68
f 69 74 75
f 75 70 69
f 71 76 77
f 77 72 71
f 72 77 78
f 78 73 72
f 73 78 79
f 79 74 73
f 74 79 80
f 80 75 74
f 76 46 49
f 49 77 76
f 77 49 53
f 53 78 77
f 78 53 56
f 56 79 78
f 79 56 59
f 59 80 79
g frontAndBack
f 31 34 81
f 81 61 31
f 34 36 82
f 82 81 34
f 36 1 4
f 4 82 36
f 61 81 83
f 83 66 61
f 81 82 84
f 84 83 81
f 82 4 12
f 12 84 82
f 66 83 85
f 85 71 66
f 83 84 86
f 86 85 83
f 84 12 17
f 17 86 84
f 71 85 87
f 87 76 71
f 85 86 88
f 88 87 85
f 86 17 22
f 22 88 86
f 76 87 47
f 47 46 76
f 87 88 50
f 50 47 87
f 88 22 27
f 27 50 88
f 43 65 89
f 89 44 43
f 44 89 90
f 90 45 44
f 45 90 10
f 10 9 45
f 65 70 91
f 91 89 65
f 89 91 92
f 92 90 89
f 90 92 15
f 15 10 90
f 70 75 93
f 93 91 70
f 91 93 94
f 94 92 91
f 92 94 20
f 20 15 92
f 75 80 95
f 95 93 75
f 93 95 96
f 96 94 93
f 94 96 25
f 25 20 94
f 80 59 58
f 58 95 80
f 95 58 60
f 60 96 95
f 96 60 30
f 30 25 96

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,422 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2009-2009 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Application
momentOfInertiaTest
Description
Calculates the inertia tensor and principal axes and moments of a
command line specified triSurface. Inertia can either be of the
solid body or of a thin shell.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "ListOps.H"
#include "face.H"
#include "tetPointRef.H"
#include "triFaceList.H"
#include "triSurface.H"
#include "OFstream.H"
#include "meshTools.H"
#include "Random.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
using namespace Foam;
void massPropertiesSolid
(
const pointField& pts,
const triFaceList triFaces,
scalar density,
scalar& mass,
vector& cM,
tensor& J
)
{
// Reimplemented from: Wm4PolyhedralMassProperties.cpp
// File Version: 4.10.0 (2009/11/18)
// Geometric Tools, LC
// Copyright (c) 1998-2010
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
// http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
// Boost Software License - Version 1.0 - August 17th, 2003
// Permission is hereby granted, free of charge, to any person or
// organization obtaining a copy of the software and accompanying
// documentation covered by this license (the "Software") to use,
// reproduce, display, distribute, execute, and transmit the
// Software, and to prepare derivative works of the Software, and
// to permit third-parties to whom the Software is furnished to do
// so, all subject to the following:
// The copyright notices in the Software and this entire
// statement, including the above license grant, this restriction
// and the following disclaimer, must be included in all copies of
// the Software, in whole or in part, and all derivative works of
// the Software, unless such copies or derivative works are solely
// in the form of machine-executable object code generated by a
// source language processor.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
// NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
// ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR
// OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
const scalar r6 = 1.0/6.0;
const scalar r24 = 1.0/24.0;
const scalar r60 = 1.0/60.0;
const scalar r120 = 1.0/120.0;
// order: 1, x, y, z, x^2, y^2, z^2, xy, yz, zx
scalarField integrals(10, 0.0);
forAll(triFaces, i)
{
const triFace& tri(triFaces[i]);
// vertices of triangle i
vector v0 = pts[tri[0]];
vector v1 = pts[tri[1]];
vector v2 = pts[tri[2]];
// cross product of edges
vector eA = v1 - v0;
vector eB = v2 - v0;
vector n = eA ^ eB;
// compute integral terms
scalar tmp0, tmp1, tmp2;
scalar f1x, f2x, f3x, g0x, g1x, g2x;
tmp0 = v0.x() + v1.x();
f1x = tmp0 + v2.x();
tmp1 = v0.x()*v0.x();
tmp2 = tmp1 + v1.x()*tmp0;
f2x = tmp2 + v2.x()*f1x;
f3x = v0.x()*tmp1 + v1.x()*tmp2 + v2.x()*f2x;
g0x = f2x + v0.x()*(f1x + v0.x());
g1x = f2x + v1.x()*(f1x + v1.x());
g2x = f2x + v2.x()*(f1x + v2.x());
scalar f1y, f2y, f3y, g0y, g1y, g2y;
tmp0 = v0.y() + v1.y();
f1y = tmp0 + v2.y();
tmp1 = v0.y()*v0.y();
tmp2 = tmp1 + v1.y()*tmp0;
f2y = tmp2 + v2.y()*f1y;
f3y = v0.y()*tmp1 + v1.y()*tmp2 + v2.y()*f2y;
g0y = f2y + v0.y()*(f1y + v0.y());
g1y = f2y + v1.y()*(f1y + v1.y());
g2y = f2y + v2.y()*(f1y + v2.y());
scalar f1z, f2z, f3z, g0z, g1z, g2z;
tmp0 = v0.z() + v1.z();
f1z = tmp0 + v2.z();
tmp1 = v0.z()*v0.z();
tmp2 = tmp1 + v1.z()*tmp0;
f2z = tmp2 + v2.z()*f1z;
f3z = v0.z()*tmp1 + v1.z()*tmp2 + v2.z()*f2z;
g0z = f2z + v0.z()*(f1z + v0.z());
g1z = f2z + v1.z()*(f1z + v1.z());
g2z = f2z + v2.z()*(f1z + v2.z());
// update integrals
integrals[0] += n.x()*f1x;
integrals[1] += n.x()*f2x;
integrals[2] += n.y()*f2y;
integrals[3] += n.z()*f2z;
integrals[4] += n.x()*f3x;
integrals[5] += n.y()*f3y;
integrals[6] += n.z()*f3z;
integrals[7] += n.x()*(v0.y()*g0x + v1.y()*g1x + v2.y()*g2x);
integrals[8] += n.y()*(v0.z()*g0y + v1.z()*g1y + v2.z()*g2y);
integrals[9] += n.z()*(v0.x()*g0z + v1.x()*g1z + v2.x()*g2z);
}
integrals[0] *= r6;
integrals[1] *= r24;
integrals[2] *= r24;
integrals[3] *= r24;
integrals[4] *= r60;
integrals[5] *= r60;
integrals[6] *= r60;
integrals[7] *= r120;
integrals[8] *= r120;
integrals[9] *= r120;
// mass
mass = integrals[0];
// center of mass
cM = vector(integrals[1], integrals[2], integrals[3])/mass;
// inertia relative to origin
J.xx() = integrals[5] + integrals[6];
J.xy() = -integrals[7];
J.xz() = -integrals[9];
J.yx() = J.xy();
J.yy() = integrals[4] + integrals[6];
J.yz() = -integrals[8];
J.zx() = J.xz();
J.zy() = J.yz();
J.zz() = integrals[4] + integrals[5];
// inertia relative to center of mass
J -= mass*((cM & cM)*I - cM*cM);
// Apply density
mass *= density;
J *= density;
}
void massPropertiesShell
(
const pointField& pts,
const triFaceList triFaces,
scalar density,
scalar& mass,
vector& cM,
tensor& J
)
{
// Reset properties for accumulation
mass = 0.0;
cM = vector::zero;
J = tensor::zero;
// Find centre of mass
forAll(triFaces, i)
{
const triFace& tri(triFaces[i]);
triPointRef t
(
pts[tri[0]],
pts[tri[1]],
pts[tri[2]]
);
scalar triMag = t.mag();
cM += triMag*t.centre();
mass += triMag;
}
cM /= mass;
mass *= density;
// Find inertia around centre of mass
forAll(triFaces, i)
{
const triFace& tri(triFaces[i]);
J += triPointRef
(
pts[tri[0]],
pts[tri[1]],
pts[tri[2]]
).inertia(cM, density);
}
}
tensor applyParallelAxisTheorem
(
scalar m,
const vector& cM,
const tensor& J,
const vector& refPt
)
{
// The displacement vector (refPt = cM) is the displacement of the
// new reference point from the centre of mass of the body that
// the inertia tensor applies to.
vector d = (refPt - cM);
return (J + m*((d & d)*I - d*d));
}
int main(int argc, char *argv[])
{
argList::addNote
(
"Calculates the inertia tensor and principal axes and moments "
"of a command line specified triSurface. Inertia can either "
"be of the solid body or of a thin shell."
);
argList::noParallel();
argList::validArgs.append("surface file");
argList::addBoolOption("shellProperties");
argList::addOption
(
"density",
"scalar",
"Specify density,"
"kg/m3 for solid properties, kg/m2 for shell properties"
);
argList::addOption
(
"referencePoint",
"vector",
"Inertia relative to this point, not the centre of mass"
);
argList args(argc, argv);
fileName surfFileName(args.additionalArgs()[0]);
triSurface surf(surfFileName);
scalar density = args.optionLookupOrDefault("density", 1.0);
vector refPt = vector::zero;
bool calcAroundRefPt = args.optionReadIfPresent("referencePoint", refPt);
triFaceList faces(surf.size());
forAll(surf, i)
{
faces[i] = triFace(surf[i]);
}
scalar m = 0.0;
vector cM = vector::zero;
tensor J = tensor::zero;
if (args.optionFound("shellProperties"))
{
massPropertiesShell
(
surf.points(),
faces,
density,
m,
cM,
J
);
}
else
{
massPropertiesSolid
(
surf.points(),
faces,
density,
m,
cM,
J
);
}
vector eVal = eigenValues(J);
tensor eVec = eigenVectors(J);
label pertI = 0;
Random rand(57373);
while ((magSqr(eVal) < VSMALL) && pertI < 10)
{
WarningIn(args.executable() + "::main")
<< "No eigenValues found, shape may have symmetry, "
<< "perturbing inertia tensor diagonal" << endl;
J.xx() *= 1.0 + SMALL*rand.scalar01();
J.yy() *= 1.0 + SMALL*rand.scalar01();
J.zz() *= 1.0 + SMALL*rand.scalar01();
eVal = eigenValues(J);
eVec = eigenVectors(J);
pertI++;
}
Info<< nl
<< "Density = " << density << nl
<< "Mass = " << m << nl
<< "Centre of mass = " << cM << nl
<< "Inertia tensor around centre of mass = " << J << nl
<< "eigenValues (principal moments) = " << eVal << nl
<< "eigenVectors (principal axes) = "
<< eVec.x() << ' ' << eVec.y() << ' ' << eVec.z()
<< endl;
if(calcAroundRefPt)
{
Info << "Inertia tensor relative to " << refPt << " = "
<< applyParallelAxisTheorem(m, cM, J, refPt)
<< endl;
}
OFstream str("axes.obj");
Info<< nl << "Writing scaled principal axes at centre of mass of "
<< surfFileName << " to " << str.name() << endl;
scalar scale = mag(cM - surf.points()[0])/eVal.component(findMin(eVal));
meshTools::writeOBJ(str, cM);
meshTools::writeOBJ(str, cM + scale*eVal.x()*eVec.x());
meshTools::writeOBJ(str, cM + scale*eVal.y()*eVec.y());
meshTools::writeOBJ(str, cM + scale*eVal.z()*eVec.z());
for (label i = 1; i < 4; i++)
{
str << "l " << 1 << ' ' << i + 1 << endl;
}
Info<< nl << "End" << nl << endl;
return 0;
}
// ************************************************************************* //

View File

@ -78,17 +78,6 @@ Foam::IFstreamAllocator::~IFstreamAllocator()
}
std::istream& Foam::IFstreamAllocator::stdStream()
{
if (!ifPtr_)
{
FatalErrorIn("IFstreamAllocator::stdStream()")
<< "No stream allocated" << abort(FatalError);
}
return *ifPtr_;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::IFstream::IFstream
@ -143,6 +132,28 @@ Foam::IFstream::~IFstream()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
std::istream& Foam::IFstream::stdStream()
{
if (!ifPtr_)
{
FatalErrorIn("IFstream::stdStream()")
<< "No stream allocated" << abort(FatalError);
}
return *ifPtr_;
}
const std::istream& Foam::IFstream::stdStream() const
{
if (!ifPtr_)
{
FatalErrorIn("IFstream::stdStream() const")
<< "No stream allocated" << abort(FatalError);
}
return *ifPtr_;
}
void Foam::IFstream::print(Ostream& os) const
{
// Print File data

View File

@ -51,7 +51,7 @@ namespace Foam
class IFstream;
/*---------------------------------------------------------------------------*\
Class IFstreamAllocator Declaration
Class IFstreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- A std::istream with ability to handle compressed files
@ -74,19 +74,11 @@ class IFstreamAllocator
// Destructor
~IFstreamAllocator();
public:
// Member functions
//- Access to underlying std::istream (for e.g. lexer)
istream& stdStream();
};
/*---------------------------------------------------------------------------*\
Class IFstream Declaration
Class IFstream Declaration
\*---------------------------------------------------------------------------*/
class IFstream
@ -136,6 +128,16 @@ public:
return pathname_;
}
// STL stream
//- Access to underlying std::istream
virtual istream& stdStream();
//- Const access to underlying std::istream
virtual const istream& stdStream() const;
// Print
//- Print description of IOstream to Ostream

View File

@ -81,17 +81,6 @@ Foam::OFstreamAllocator::~OFstreamAllocator()
}
std::ostream& Foam::OFstreamAllocator::stdStream()
{
if (!ofPtr_)
{
FatalErrorIn("OFstreamAllocator::stdStream()")
<< "No stream allocated." << abort(FatalError);
}
return *ofPtr_;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::OFstream::OFstream
@ -131,7 +120,7 @@ Foam::OFstream::OFstream
}
// * * * * * * * * * * * * * * * * Destructors * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::OFstream::~OFstream()
{}
@ -139,6 +128,28 @@ Foam::OFstream::~OFstream()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
std::ostream& Foam::OFstream::stdStream()
{
if (!ofPtr_)
{
FatalErrorIn("OFstream::stdStream()")
<< "No stream allocated." << abort(FatalError);
}
return *ofPtr_;
}
const std::ostream& Foam::OFstream::stdStream() const
{
if (!ofPtr_)
{
FatalErrorIn("OFstreamAllocator::stdStream() const")
<< "No stream allocated." << abort(FatalError);
}
return *ofPtr_;
}
void Foam::OFstream::print(Ostream& os) const
{
os << " OFstream: ";

View File

@ -51,7 +51,7 @@ namespace Foam
class OFstream;
/*---------------------------------------------------------------------------*\
Class OFstreamAllocator Declaration
Class OFstreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- A std::ostream with ability to handle compressed files
@ -74,18 +74,11 @@ class OFstreamAllocator
~OFstreamAllocator();
public:
// Member functions
//- Access to underlying std::ostream
ostream& stdStream();
};
/*---------------------------------------------------------------------------*\
Class OFstream Declaration
Class OFstream Declaration
\*---------------------------------------------------------------------------*/
class OFstream
@ -138,6 +131,15 @@ public:
}
// STL stream
//- Access to underlying std::ostream
virtual ostream& stdStream();
//- Const access to underlying std::ostream
virtual const ostream& stdStream() const;
// Print
//- Print description of IOstream to Ostream
@ -146,8 +148,8 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Global predefined null output stream
//- Global predefined null output stream "/dev/null"
extern OFstream Snull;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -551,7 +551,7 @@ Foam::Istream& Foam::ISstream::read(char* buf, std::streamsize count)
Foam::Istream& Foam::ISstream::rewind()
{
stream().rdbuf()->pubseekpos(0);
stdStream().rdbuf()->pubseekpos(0);
return *this;
}

View File

@ -72,23 +72,6 @@ class ISstream
void operator=(const ISstream&);
protected:
// Protected member functions
//- Return the stream reference
istream& stream()
{
return is_;
}
//- Return the const stream reference
const istream& stream() const
{
return is_;
}
public:
// Constructors
@ -185,6 +168,21 @@ public:
virtual ios_base::fmtflags flags(const ios_base::fmtflags flags);
// STL stream
//- Access to underlying std::istream
virtual istream& stdStream()
{
return is_;
}
//- Const access to underlying std::istream
virtual const istream& stdStream() const
{
return is_;
}
// Print
//- Print description of IOstream to Ostream

View File

@ -67,21 +67,6 @@ class OSstream
void operator=(const OSstream&);
protected:
//- Return the stream reference
ostream& stream()
{
return os_;
}
//- Return the const stream reference
const ostream& stream() const
{
return os_;
}
public:
// Constructors
@ -187,6 +172,21 @@ public:
virtual int precision(const int);
// STL stream
//- Access to underlying std::ostream
virtual ostream& stdStream()
{
return os_;
}
//- Const access to underlying std::ostream
virtual const ostream& stdStream() const
{
return os_;
}
// Print
//- Print description of IOstream to Ostream

View File

@ -97,7 +97,7 @@ public:
~IStringStream()
{
delete &dynamic_cast<std::istringstream&>(stream());
delete &dynamic_cast<std::istringstream&>(stdStream());
}
@ -108,7 +108,10 @@ public:
//- Return the string
string str() const
{
return dynamic_cast<const std::istringstream&>(stream()).str();
return dynamic_cast<const std::istringstream&>
(
stdStream()
).str();
}

View File

@ -83,7 +83,7 @@ public:
(
dynamic_cast<const std::ostringstream&>
(
oss.stream()
oss.stdStream()
).str()
)
),
@ -98,7 +98,7 @@ public:
~OStringStream()
{
delete &dynamic_cast<std::ostringstream&>(stream());
delete &dynamic_cast<std::ostringstream&>(stdStream());
}
@ -109,7 +109,10 @@ public:
//- Return the string
string str() const
{
return dynamic_cast<const std::ostringstream&>(stream()).str();
return dynamic_cast<const std::ostringstream&>
(
stdStream()
).str();
}
@ -119,9 +122,9 @@ public:
void rewind()
{
# if __GNUC__ < 4 && __GNUC_MINOR__ < 4
stream().rdbuf()->pubsetbuf(" ", 1);
stdStream().rdbuf()->pubsetbuf(" ", 1);
# else
stream().rdbuf()->pubseekpos(0);
stdStream().rdbuf()->pubseekpos(0);
# endif
}

View File

@ -170,7 +170,7 @@ public:
~OSHA1stream()
{
delete &dynamic_cast<osha1stream&>(stream());
delete &dynamic_cast<osha1stream&>(stdStream());
}
@ -181,7 +181,7 @@ public:
//- Full access to the sha1
Foam::SHA1& sha1()
{
return dynamic_cast<osha1stream&>(stream()).sha1();
return dynamic_cast<osha1stream&>(stdStream()).sha1();
}
//- Return SHA1::Digest for the data processed until now

View File

@ -91,7 +91,7 @@ Foam::Ostream& Foam::ensightFile::write
std::streamsize count
)
{
stream().write(buf, count);
stdStream().write(buf, count);
return *this;
}
@ -126,7 +126,7 @@ Foam::Ostream& Foam::ensightFile::write(const string& value)
}
else
{
stream() << buf;
stdStream() << buf;
}
return *this;
@ -147,8 +147,8 @@ Foam::Ostream& Foam::ensightFile::write(const label value)
}
else
{
stream().width(10);
stream() << value;
stdStream().width(10);
stdStream() << value;
}
return *this;
@ -173,8 +173,8 @@ Foam::Ostream& Foam::ensightFile::write
}
else
{
stream().width(fieldWidth);
stream() << value;
stdStream().width(fieldWidth);
stdStream() << value;
}
return *this;
@ -195,8 +195,8 @@ Foam::Ostream& Foam::ensightFile::write(const scalar value)
}
else
{
stream().width(12);
stream() << value;
stdStream().width(12);
stdStream() << value;
}
return *this;
@ -207,7 +207,7 @@ void Foam::ensightFile::newline()
{
if (format() == IOstream::ASCII)
{
stream() << nl;
stdStream() << nl;
}
}