ENH: Add functionEntry '#calc' to dictionary

- handles basic operations, references to other dictionary entries
  (with '$name' syntax) and assorted mathematical functions:

      pi(), degToRad, radToDeg, asin, acos, atan, sin, cos, tan, log,
      log10, mag, atan2, pow

The basic syntax: #calc{ ... };

NOTE the trailing ';' is required for the primitiveEntry to be
properly defined.
This commit is contained in:
Mark Olesen
2010-02-07 13:58:10 +01:00
parent 03956d46be
commit 00616b72ff
15 changed files with 153 additions and 102 deletions

View File

@ -1,7 +1,3 @@
dictionaryTest.C
calcEntry/calcEntryParser.atg
calcEntry/calcEntryInternal.C
calcEntry/calcEntry.C
EXE = $(FOAM_USER_APPBIN)/dictionaryTest

View File

@ -1 +1 @@
EXE_INC = -IcalcEntry -I$(OBJECTS_DIR)
EXE_INC =

View File

@ -1,98 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2009-2010 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
\*---------------------------------------------------------------------------*/
#include "calcEntry.H"
#include "dictionary.H"
#include "addToMemberFunctionSelectionTable.H"
#include "ISstream.H"
#include "CocoParserErrors.H"
#include "calcEntryParser.h"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace functionEntries
{
defineTypeNameAndDebug(calcEntry, 0);
addToMemberFunctionSelectionTable
(
functionEntry,
calcEntry,
execute,
primitiveEntryIstream
);
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionEntries::calcEntry::execute
(
const dictionary& parentDict,
primitiveEntry& entry,
Istream& is
)
{
std::istream& iss = dynamicCast<ISstream>(is).stdStream();
// define parser error handler
CocoParserErrors<calcEntryInternal::Errors>
myErrorHandler("calcEntryInternal::Parser");
calcEntryInternal::Scanner scanner(iss);
// set the starting line
scanner.Line(is.lineNumber());
calcEntryInternal::Parser parser(&scanner, &myErrorHandler);
// Attach dictionary context
parser.dict(parentDict);
parser.Parse();
// mostly have an extra newline in the lookahead token
// so subtract 1 to keep things vaguely in sync
// (this is still far from perfect)
is.lineNumber() = scanner.Line() - 1;
// a small input list to contain the answer
tokenList tokens(2);
tokens[0] = parser.Result();
tokens[1] = token::END_STATEMENT;
entry.read(parentDict, ITstream("ParserResult", tokens)());
return true;
}
// ************************************************************************* //

View File

@ -1,93 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2009-2010 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
Class
Foam::functionEntries::calcEntry
Description
This dictionary function entry may or may not do anything particularly
useful - depending upon what is currently being used to test.
SourceFiles
calcEntry.C
\*---------------------------------------------------------------------------*/
#ifndef calcEntry_H
#define calcEntry_H
#include "functionEntry.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionEntries
{
/*---------------------------------------------------------------------------*\
Class calcEntry Declaration
\*---------------------------------------------------------------------------*/
class calcEntry
:
public functionEntry
{
// Private Member Functions
//- Disallow default bitwise copy construct
calcEntry(const calcEntry&);
//- Disallow default bitwise assignment
void operator=(const calcEntry&);
public:
//- Runtime type information
ClassName("calc");
// Member Functions
static bool execute
(
const dictionary& parentDict,
primitiveEntry& entry,
Istream& is
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace functionEntries
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,129 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 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
\*---------------------------------------------------------------------------*/
#include "calcEntryInternal.H"
#include "addToGlobalFunctionSelectionTable.H"
#include "unitConversion.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionEntries
{
namespace calcEntryInternal
{
defineGlobalFunctionSelectionTable(dispatch,ParamList);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#define globalConstant0(Name, Constant)\
scalar Name##_0(const UList<scalar>& param) \
{ \
return Constant; \
} \
addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_0,&Name##_0)
#define globalFunction0(Name, Function)\
scalar Name##_0(const UList<scalar>& param) \
{ \
return Function(); \
} \
addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_0,&Name##_0)
#define globalFunction1(Name, Function)\
scalar Name##_1(const UList<scalar>& param) \
{ \
return Function(param[0]); \
} \
addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_1,&Name##_1)
#define globalFunction2(Name, Function)\
scalar Name##_2(const UList<scalar>& param) \
{ \
return Function(param[0], param[1]); \
} \
addNamedToGlobalFunctionSelectionTable(dispatch,ParamList,Name##_2,&Name##_2)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
globalConstant0(pi, constant::mathematical::pi);
globalFunction1(degToRad, degToRad);
globalFunction1(radToDeg, radToDeg);
globalFunction1(asin, Foam::asin);
globalFunction1(acos, Foam::acos);
globalFunction1(atan, Foam::atan);
globalFunction1(sin, Foam::sin);
globalFunction1(cos, Foam::cos);
globalFunction1(tan, Foam::tan);
globalFunction1(log, Foam::log);
globalFunction1(log10, Foam::log10);
globalFunction1(mag, Foam::mag);
globalFunction2(atan2, Foam::atan2);
globalFunction2(pow, Foam::pow);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
scalar dispatch(const word& name, const UList<scalar>& param)
{
// create lookup name with parameter count
const word lookupName = name + '_' + Foam::name(param.size());
dispatchParamListMemberFunctionTable::iterator mfIter =
dispatchParamListMemberFunctionTablePtr_->find(lookupName);
if (mfIter == dispatchParamListMemberFunctionTablePtr_->end())
{
FatalErrorIn
(
"calcEntryInternal::scalarFunctions::dispatch"
"(const word&, const UList<scalar>&) : "
) << "Unknown function " << name << nl << nl
<< "Valid types are :" << endl
<< dispatchParamListMemberFunctionTablePtr_->sortedToc()
<< exit(FatalError);
}
return mfIter()(param);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace calcEntryInternal
} // End namespace functionEntries
} // End namespace Foam
// ************************************************************************* //

View File

@ -1,81 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 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
Namespace
Foam::functionEntries::calcEntryInternal
Description
Contains global functions and classes for the calcEntry.
SourceFiles
calcEntryInternal.C
\*---------------------------------------------------------------------------*/
#ifndef calcEntryInternal_H
#define calcEntryInternal_H
#include "error.H"
#include "scalar.H"
#include "DynamicList.H"
#include "globalFunctionSelectionTables.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace functionEntries
{
namespace calcEntryInternal
{
// Global Function Selectors
declareGlobalFunctionSelectionTable
(
scalar,
dispatch,
ParamList,
(
const UList<scalar>& param
),
(param)
);
//- Dispatch calculation to the named function
scalar dispatch(const word&, const UList<scalar>&);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace calcEntryInternal
} // End namespace functionEntries
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,260 +0,0 @@
[copy]
/*---------------------------------*- C++ -*---------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2010-2010 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
@file calcEntryParser.atg
Description
An attributed Coco/R grammar to parse simple arithmetic expressions
Includes support for dictionary $variables and some scalar functions
(eg, sin, pow, ...)
SourceFiles
generated
\*---------------------------------------------------------------------------*/
[/copy]
/*---------------------------------------------------------------------------*\
compile with:
Coco \
[-single] -frames $WM_THIRD_PARTY_DIR/coco-r \
calcEntryParser.atg
\*---------------------------------------------------------------------------*/
#include "dictionary.H"
#include "wchar.H"
#include "calcEntryInternal.H"
COMPILER calcEntry
// grammar pragmas:
$prefix=calcEntry
$namespace=Foam::functionEntries::calcEntryInternal
$explicitEOF=true // grammar handles eof itself
private:
//- The parent dictionary
dictionary* dict_;
//- The calculation result
scalar val;
//- lookup dictionary entry
scalar getDictLookup() const
{
if (!dict_)
{
FatalErrorIn
(
"calcEntry::getDictEntry() const"
) << "No dictionary attached!"
<< exit(FatalError);
return 0;
}
char* str = coco_string_create_char
(
t->val,
1,
(coco_string_length(t->val) - 1)
);
word keyword(str);
coco_string_delete(str);
scalar dictValue = 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
(
"calcEntry::getDictEntry() const"
) << "keyword " << keyword << " is undefined in dictionary "
<< exit(FatalError);
}
return dictValue;
}
public:
//- attach a dictionary
void dict(const dictionary& dict)
{
dict_ = const_cast<dictionary*>(&dict);
}
//- Return the calculated result
scalar Result() const
{
return val;
}
[initialize]
dict_ = 0;
val = 0;
[/initialize]
/*---------------------------------------------------------------------------*/
CHARACTERS
letter = 'A'..'Z' + 'a'..'z' + '_'.
digit = "0123456789".
alphanum = letter + digit.
sign = '+' + '-'.
cr = '\r'.
lf = '\n'.
tab = '\t'.
stringCh = ANY - '"' - '\\' - cr - lf.
printable = '\u0020' .. '\u007e'.
// * * * * * * * * * * * * * * * * TOKENS * * * * * * * * * * * * * * * * * //
TOKENS
// identifier
ident =
letter { alphanum }.
// string
string =
'"' { stringCh | '\\' printable } '"'.
// dictionary lookup identifier
// starts with '$' and otherwise limited to a normal identifier
variable =
'$' letter { alphanum }.
// floating point and integer numbers
number =
[sign] ('.' digit { digit } ) | ( digit { digit } [ '.' { digit } ])
[ ('E' | 'e') [sign] digit { digit } ].
// * * * * * * * * * * * PRAGMAS / COMMENTS / IGNORE * * * * * * * * * * * //
COMMENTS FROM "/*" TO "*/" NESTED
COMMENTS FROM "//" TO lf
IGNORE cr + lf + tab
// * * * * * * * * * * * * * * * PRODUCTIONS * * * * * * * * * * * * * * * //
PRODUCTIONS
calcEntry (. val = 0; .)
=
'{' Expr<val> '}' (. // reposition to immediately after the closing '}'
scanner->buffer->SetPos(t->pos + 1);
.)
| ( Expr<val> EOF )
.
/*---------------------------------------------------------------------------*/
Expr<scalar& val> (. scalar val2 = 0; .)
=
Term<val>
{
'+' Term<val2> (. val += val2; .)
| '-' Term<val2> (. val -= val2; .)
}
.
/*---------------------------------------------------------------------------*/
Term<scalar& val> (. scalar val2 = 0; .)
=
Factor<val>
{
'*' Factor<val2> (. val *= val2; .)
| '/' Factor<val2> (. val /= val2; .)
}
.
/*---------------------------------------------------------------------------*/
// Note the treatment of the leading signs is fairly generous
// eg, "10 + - 10" is treated like "10 + -10"
//
Factor<scalar& val> (. bool negative = false; .)
=
['+' | '-' (. negative = true; .)
]
(
Func<val> | '(' Expr<val> ')'
| variable (. val = getDictLookup(); .)
| number (. val = coco_string_toDouble(t->val); .)
) (. if (negative) { val = -val; } .)
.
/*---------------------------------------------------------------------------*/
// functions like sin(x) or pow(x, y) etc.
Func<scalar& val>
=
ident (.
char* str = coco_string_create_char(t->val);
word funcName(str);
coco_string_delete(str);
DynamicList<scalar> stack(4);
.)
'('
[ (. scalar x; .)
Expr<x> (. stack.append(x); .)
{ ',' Expr<x> (. stack.append(x); .)
}
]
')' (. val = dispatch(funcName, stack); .)
.
/*---------------------------------------------------------------------------*/
END calcEntry.
// ************************************************************************* //

View File

@ -10,7 +10,7 @@ FoamFile
version 2.0;
format ascii;
class dictionary;
object testDictTest;
object testDictCalc;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -19,28 +19,13 @@ flowRatePerHour 720;
x 10;
y 20;
z t s v;
// z #test{ // this
// 123 - 456
// // comments // are
// /* stripped
// * 10
// * {}
// */
// + 1 /*100 */ 10
// };
p #calc{ 1 + 2 + 10 * 15 + $x - $y };
p this calculation #calc{
1 + 2 + 10 * 15 +
$x - $y
// $x + $y
}
is done inplace;
// this calculation is in-place, but does not work inside a string:
flowRate "The flow rate " #calc{ $flowRatePerHour / 3600 } "kg/s";
// this is also okay
x #calc{ $x * 1E-3 };
flowRate #calc{ $flowRatePerHour / 3600};
xxx yyy;
foo 30;
bar 15;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,46 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: Any |
| \\ / A nd | Web: www.OpenFOAM.org |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object testDictCalcError;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
flowRatePerHour 720;
x 10;
y 20;
z t s v;
// z #test{ // this
// 123 - 456
// // comments // are
// /* stripped
// * 10
// * {}
// */
// + 1 /*100 */ 10
// };
p this calculation #calc{
1xxx1 + 2 + 10 * 15 +
$x - $y
// $x + $y
}
is done inplace;
flowRate #calc{ $flowRatePerHour / 3600};
xxx yyy;
foo 30;
bar 15;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //