ENH: add expression support for scalar/vector expression lookups

- similar idea to swak timelines/lookuptables but combined together
  and based on Function1 for more flexibility.

  Specified as 'functions<scalar>' or 'functions<vector>'.
  For example,

  functions<scalar>
  {
      intakeType table ((0 0) (10 1.2));

      p_inlet
      {
          type        sine;
          frequency   3000;
          scale       50;
          level       101325;
      }
  }

  These can be referenced in the expressions as a nullary function or a
  unary function.

  Within the parser, the names are prefixed with "fn:" (function).
  It is thus possible to define "fn:sin()" that is different than
  the builtin "sin()" function.

     * A nullary call uses time value
       - Eg, fn:p_inlet()

     * A unary call acts as a remapper function.
       - Eg, fn:intakeType(6.25)
This commit is contained in:
Mark Olesen
2021-11-18 18:41:20 +01:00
parent e6697edb52
commit fc6239d96e
19 changed files with 5896 additions and 5086 deletions

View File

@ -1,7 +1,7 @@
/*--------------------------------*- C++ -*----------------------------------*\ /*--------------------------------*- C++ -*----------------------------------*\
| ========= | | | ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2106 | | \\ / O peration | Version: v2112 |
| \\ / A nd | Website: www.openfoam.com | | \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | | | \\/ M anipulation | |
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -138,4 +138,53 @@ cosine6
} }
expr1
{
type expression;
functions<scalar>
{
func1 constant 21;
func2 constant 15;
sin constant -5;
}
functions<vector>
{
vfunc3 constant (1 2 3);
vfunc4 constant (3 2 1);
}
expression
#{
100 * fn:vfunc3() & fn:vfunc4() * (vector::z) .z()
* (fn:sin(arg()) + fn:func1(fn:func2()))
#};
}
expr2
{
type expression;
functions<scalar>
{
func1 constant 21;
func2 constant 15;
sin constant -5;
}
functions<vector>
{
vfunc3 constant (1 2 3);
vfunc4 constant (3 2 1);
}
expression
#{
(fn:vfunc3() & vector::z) * arg()
#};
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -168,6 +168,7 @@ $(expr)/traits/exprTraits.C
$(expr)/exprDriver/exprDriver.C $(expr)/exprDriver/exprDriver.C
$(expr)/exprDriver/exprDriverFields.C $(expr)/exprDriver/exprDriverFields.C
$(expr)/exprDriver/exprDriverFunctions.C
$(expr)/exprDriver/exprDriverIO.C $(expr)/exprDriver/exprDriverIO.C
fieldExpr = $(expr)/fields fieldExpr = $(expr)/fields

View File

@ -98,6 +98,30 @@ static string getEntryString
return exprTools::expressionEntry::evaluate(*eptr); return exprTools::expressionEntry::evaluate(*eptr);
} }
#endif #endif
template<class Type>
static void shallowCloneFunctions
(
HashTable<refPtr<Function1<Type>>>& dest,
const HashTable<refPtr<Function1<Type>>>& rhs
)
{
// Add in shallow copy for other functions
forAllConstIters(rhs, iter)
{
const word& key = iter.key();
if (!dest.found(key))
{
refPtr<Function1<Type>> func;
func.cref(iter.val().shallowClone());
dest.emplace_set(key, std::move(func));
}
}
}
} // End namespace Foam } // End namespace Foam
@ -118,6 +142,23 @@ void Foam::expressions::exprDriver::resetTimeReference(const TimeState& ts)
void Foam::expressions::exprDriver::resetDb(const objectRegistry* obrPtr) void Foam::expressions::exprDriver::resetDb(const objectRegistry* obrPtr)
{ {
obrPtr_ = obrPtr; obrPtr_ = obrPtr;
forAllIters(scalarFuncs_, iter)
{
auto& funcPtr = iter.val();
if (funcPtr && !funcPtr.is_const())
{
(*funcPtr).resetDb(obrPtr_);
}
}
forAllIters(vectorFuncs_, iter)
{
auto& funcPtr = iter.val();
if (funcPtr && !funcPtr.is_const())
{
(*funcPtr).resetDb(obrPtr_);
}
}
} }
@ -139,6 +180,8 @@ Foam::expressions::exprDriver::exprDriver
result_(), result_(),
variableStrings_(), variableStrings_(),
variables_(16), variables_(16),
scalarFuncs_(0),
vectorFuncs_(0),
arg1Value_(0), arg1Value_(0),
timeStatePtr_(nullptr), timeStatePtr_(nullptr),
obrPtr_(nullptr), obrPtr_(nullptr),
@ -162,6 +205,8 @@ Foam::expressions::exprDriver::exprDriver
result_(rhs.result_), result_(rhs.result_),
variableStrings_(rhs.variableStrings_), variableStrings_(rhs.variableStrings_),
variables_(rhs.variables_), variables_(rhs.variables_),
scalarFuncs_(0),
vectorFuncs_(0),
arg1Value_(rhs.arg1Value_), arg1Value_(rhs.arg1Value_),
timeStatePtr_(rhs.timeStatePtr_), timeStatePtr_(rhs.timeStatePtr_),
obrPtr_(rhs.obrPtr_), obrPtr_(rhs.obrPtr_),
@ -174,7 +219,16 @@ Foam::expressions::exprDriver::exprDriver
prevIterIsOldTime_(rhs.prevIterIsOldTime_), prevIterIsOldTime_(rhs.prevIterIsOldTime_),
searchCtrl_(rhs.searchCtrl_) searchCtrl_(rhs.searchCtrl_)
{} {
// Partially like readDict()
// Create Function1s from dictionary content
resetFunctions(dict_);
// Add in shallow copy for other functions
shallowCloneFunctions(scalarFuncs_, rhs.scalarFuncs_);
shallowCloneFunctions(vectorFuncs_, rhs.vectorFuncs_);
}
Foam::expressions::exprDriver::exprDriver Foam::expressions::exprDriver::exprDriver
@ -246,9 +300,9 @@ bool Foam::expressions::exprDriver::readDict
// Regular variables // Regular variables
variableStrings_ = readVariableStrings(dict); variableStrings_ = readVariableStrings(dict);
// Other tables? // Create Function1s from dictionary content
// readTable("timelines", dict, lines_); resetFunctions(dict);
// readTable("lookuptables", dict, lookup_);
// readTable("lookuptables2D", dict, lookup2D_); // readTable("lookuptables2D", dict, lookup2D_);
return true; return true;

View File

@ -36,6 +36,8 @@ Description
\table \table
Property | Description | Required | Default Property | Description | Required | Default
variables | List of variables for expressions | no | () variables | List of variables for expressions | no | ()
lookup\<scalar\> | Dictionary of scalar Function1 | no | {}
lookup\<vector\> | Dictionary of vector Function1 | no | {}
allowShadowing | Allow variables to shadow field names | no | false allowShadowing | Allow variables to shadow field names | no | false
\endtable \endtable
@ -47,10 +49,15 @@ Description
debugParser | Add debug for parser | no | false debugParser | Add debug for parser | no | false
\endtable \endtable
The \c lookup<scalar> and \c lookup<vector> are dictionaries
of Function1 definitions that can either be used to establish
a time-varying quantity, to remap a field of scalar values, or both.
SourceFiles SourceFiles
exprDriverI.H exprDriverI.H
exprDriver.C exprDriver.C
exprDriverFields.C exprDriverFields.C
exprDriverFunctions.C
exprDriverIO.C exprDriverIO.C
exprDriverTemplates.C exprDriverTemplates.C
@ -65,6 +72,9 @@ SourceFiles
#include "pointField.H" #include "pointField.H"
#include "primitiveFields.H" #include "primitiveFields.H"
#include "objectRegistry.H" #include "objectRegistry.H"
#include "HashTable.H"
#include "HashSet.H"
#include "Function1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -105,6 +115,18 @@ private:
//- Get search/caching controls from dictionary entries //- Get search/caching controls from dictionary entries
static int getSearchControls(const dictionary& dict); static int getSearchControls(const dictionary& dict);
//- Read/reset Function1 entries
void resetFunctions(const dictionary& dict);
//- Helper for lookup of Function1 in table
template<class Type>
static const Function1<Type>* getFunction1Ptr
(
const word& name,
const HashTable<refPtr<Function1<Type>>>& tbl,
wordList* listFailure = nullptr
);
protected: protected:
@ -124,6 +146,14 @@ protected:
//- The variables table //- The variables table
HashTable<exprResult> variables_; HashTable<exprResult> variables_;
//- Function1 mappings/timelines (scalar),
//- evaluated at the simulation time or with arbitrary scalars
HashTable<refPtr<Function1<scalar>>> scalarFuncs_;
//- Function1 mappings/timelines (vector),
//- evaluated at the simulation time or with arbitrary scalars
HashTable<refPtr<Function1<vector>>> vectorFuncs_;
//- Special-purpose scalar reference argument //- Special-purpose scalar reference argument
scalar arg1Value_; scalar arg1Value_;
@ -173,24 +203,8 @@ protected:
static tmp<GeoField> static tmp<GeoField>
cfindFieldObject(const objectRegistry& obr, const word& fldName); cfindFieldObject(const objectRegistry& obr, const word& fldName);
//- Read an interpolation table //- Write scalar/vector Function1 entries in dictionary format
template<typename TableType> void writeFunctions(Ostream& os) const;
static bool readTable
(
const word& name,
const dictionary& dict,
HashTable<TableType>& tbl,
bool clear=true
);
//- Write an interpolation table
template<class TableType>
static void writeTable
(
Ostream& os,
const word& name,
const HashTable<TableType>& tbl
);
// Variables // Variables
@ -444,6 +458,27 @@ public:
); );
// Scalar mappings (timelines / lookups)
//- Named mapping with given type exists
template<class Type>
bool isFunction(const word& name) const;
//- Evaluate named mapping for the given time/value.
//- Zero for undefined/unknown
template<class Type>
Type getFunctionValue(const word& name, const scalar x) const;
//- Fill result with values remapped according to the named Function1
template<class Type>
void fillFunctionValues
(
Field<Type>& result,
const word& name,
const scalarField& input
) const;
// Fields // Fields
//- Test existence of a local variable //- Test existence of a local variable

View File

@ -0,0 +1,231 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
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 3 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, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "exprDriver.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Check for acceptable Function1 keywords in the given dictionary,
// with special handling to avoid accidental inclusion of coeffs
// dictionaries etc
static wordHashSet getAcceptableFunctionKeys
(
const dictionary* dictPtr,
const bool acceptPrimitiveEntry,
const bool report = false
)
{
wordHashSet acceptKeys(0);
if (!dictPtr)
{
return acceptKeys;
}
const dictionary& dict = *dictPtr;
acceptKeys.resize(2*dict.size());
wordHashSet rejectKeys(2*dict.size());
for (const entry& dEntry : dict)
{
const keyType& kw = dEntry.keyword();
bool ok = true;
if (kw.isPattern())
{
ok = false;
}
else if (dEntry.isDict())
{
// Dictionary entry - require "type", which should eliminate
// any *Coeffs dictionaries
ok = dEntry.dict().found("type", keyType::LITERAL);
}
else
{
// Primitive entry. Trust that it is okay?
ok = acceptPrimitiveEntry;
}
if (ok)
{
acceptKeys.insert(kw);
}
else
{
rejectKeys.insert(kw);
}
}
if (report && rejectKeys.size())
{
InfoInFunction
<< "Dropped invalid/redundant entries: "
<< flatOutput(rejectKeys.sortedToc()) << nl;
}
return acceptKeys;
}
// Read and reset Function1 for given dictionary.
// Uses getAcceptableFunctionKeys
template<class Type>
static void resetFuncsImpl
(
const word& subDictName,
const dictionary& topDict,
HashTable<refPtr<Function1<Type>>>& tbl,
const objectRegistry* obrPtr
)
{
tbl.clear();
const dictionary* dictPtr =
topDict.findDict(subDictName, keyType::LITERAL);
if (!dictPtr)
{
return;
}
wordHashSet acceptKeys
(
getAcceptableFunctionKeys
(
dictPtr,
true // Accept primitive entries, hope for the best
)
);
const dictionary& dict = *dictPtr;
for (const word& entryName : acceptKeys)
{
// From autoPtr -> refPtr
refPtr<Function1<Type>> func
(
Function1<Type>::New(entryName, dict, obrPtr)
);
if (func)
{
tbl.insert(entryName, std::move(func));
}
}
}
// Write out entries, if they originated from dictionary
template<class Type>
static void writeFuncsImpl
(
Ostream& os,
const word& subDictName,
const dictionary& topDict,
const HashTable<refPtr<Function1<Type>>>& tbl
)
{
const dictionary* dictPtr =
topDict.findDict(subDictName, keyType::LITERAL);
if (!dictPtr || tbl.empty())
{
return;
}
label nwrote = 0;
const dictionary& dict = *dictPtr;
for (const entry& dEntry : dict)
{
const word& entryName = dEntry.keyword();
const auto iter = tbl.cfind(entryName);
if (!iter.found())
{
continue;
}
const auto& funcPtr = iter.val();
if (funcPtr)
{
if (!nwrote++)
{
os.beginBlock(subDictName);
}
os.beginBlock(entryName);
os.writeEntry("type", (*funcPtr).type());
(*funcPtr).writeEntries(os);
os.endBlock();
}
}
if (nwrote)
{
os.endBlock();
}
}
} // End namespace Foam
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::expressions::exprDriver::resetFunctions
(
const dictionary& dict
)
{
resetFuncsImpl<scalar>("functions<scalar>", dict_, scalarFuncs_, obrPtr_);
resetFuncsImpl<vector>("functions<vector>", dict_, vectorFuncs_, obrPtr_);
if (debug)
{
writeFunctions(InfoInFunction);
}
}
void Foam::expressions::exprDriver::writeFunctions(Ostream& os) const
{
writeFuncsImpl<scalar>(os, "functions<scalar>", dict_, scalarFuncs_);
writeFuncsImpl<vector>(os, "functions<vector>", dict_, vectorFuncs_);
}
// ************************************************************************* //

View File

@ -46,63 +46,6 @@ Foam::expressions::exprDriver::cfindFieldObject
} }
template<class TableType>
bool Foam::expressions::exprDriver::readTable
(
const word& name,
const dictionary& dict,
HashTable<TableType>& tbl,
bool clear
)
{
if (clear)
{
tbl.clear();
}
if (!dict.found(name))
{
return false;
}
ITstream& is = dict.lookup(name);
List<dictionary> input(is);
for (const dictionary& d : input)
{
tbl.insert(dict.get<word>("name"), TableType(d));
}
return true;
}
template<class TableType>
void Foam::expressions::exprDriver::writeTable
(
Ostream& os,
const word& name,
const HashTable<TableType>& tbl
)
{
if (tbl.size())
{
os.writeKeyword(name);
os << token::BEGIN_LIST << nl;
forAllConstIters(tbl, iter)
{
os.beginBlock();
os.writeEntry("name", iter.key());
(*iter).write(os);
os.endBlock();
}
os << token::END_LIST
<< token::END_STATEMENT << nl;
}
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type> template<class Type>
@ -180,6 +123,181 @@ Foam::expressions::exprDriver::getResult(bool wantPointData)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
const Foam::Function1<Type>* Foam::expressions::exprDriver::getFunction1Ptr
(
const word& name,
const HashTable<refPtr<Function1<Type>>>& tbl,
wordList* listFailure
)
{
const Function1<Type>* func = nullptr;
const auto iter = tbl.cfind(name);
if (iter.found())
{
func = iter.val().get();
}
if (!func && listFailure)
{
*listFailure = tbl.sortedToc();
}
return func;
}
template<class Type>
bool Foam::expressions::exprDriver::isFunction(const word& name) const
{
// Currently only scalar, vector
#undef doLocalCode
#define doLocalCode(WhichType, MapperMember) \
if (std::is_same<Type, WhichType>::value) \
{ \
return bool \
( \
this->template getFunction1Ptr<WhichType> \
( \
name, MapperMember \
) \
); \
}
doLocalCode(scalar, scalarFuncs_);
doLocalCode(vector, vectorFuncs_);
#undef doLocalCode
return false;
}
template<class Type>
Type Foam::expressions::exprDriver::getFunctionValue
(
const word& name,
const scalar x
) const
{
const Function1<Type>* func = nullptr;
wordList failed;
do
{
// Currently only scalar, vector
#undef doLocalCode
#define doLocalCode(WhichType, MapperMember) \
if (std::is_same<Type, WhichType>::value) \
{ \
const Function1<WhichType>* ptr = \
this->template getFunction1Ptr<WhichType> \
( \
name, MapperMember, &failed \
); \
func = reinterpret_cast<const Function1<Type>*>(ptr); \
break; \
}
doLocalCode(scalar, scalarFuncs_);
doLocalCode(vector, vectorFuncs_);
#undef doLocalCode
}
while (false);
// Error handling
if (!failed.empty())
{
FatalErrorInFunction
<< "No mapping '" << name << " (" << pTraits<Type>::typeName
<< ") found." << nl
<< "Valid entries: "
<< flatOutput(failed) << nl
<< exit(FatalError);
}
if (func)
{
return func->value(x);
}
return pTraits<Type>::zero;
}
template<class Type>
void Foam::expressions::exprDriver::fillFunctionValues
(
Field<Type>& result,
const word& name,
const scalarField& input
) const
{
// #ifdef FULLDEBUG
// checkSize(result, input);
// #endif
const Function1<Type>* func = nullptr;
wordList failed;
do
{
// Currently only scalar, vector
#undef doLocalCode
#define doLocalCode(WhichType, MapperMember) \
if (std::is_same<Type, WhichType>::value) \
{ \
const Function1<WhichType>* ptr = \
this->template getFunction1Ptr<WhichType> \
( \
name, MapperMember, &failed \
); \
func = reinterpret_cast<const Function1<Type>*>(ptr); \
break; \
}
doLocalCode(scalar, scalarFuncs_);
doLocalCode(vector, vectorFuncs_);
#undef doLocalCode
}
while (false);
// Error handling
if (!failed.empty())
{
FatalErrorInFunction
<< "No mapping '" << name << " (" << pTraits<Type>::typeName
<< ") found." << nl
<< "Valid entries: "
<< flatOutput(failed) << nl
<< exit(FatalError);
}
if (func)
{
const label len = min(result.size(), input.size());
for (label i = 0; i < len; ++i)
{
result[i] = func->value(input[i]);
}
// Safety
for (label i = len; i < result.size(); ++i)
{
result[i] = Zero;
}
return;
}
result = Zero;
}
template<class Type> template<class Type>
bool Foam::expressions::exprDriver::isLocalVariable bool Foam::expressions::exprDriver::isLocalVariable
( (

View File

@ -178,7 +178,7 @@ Foam::exprTools::getList
FatalIOErrorInFunction(dict) FatalIOErrorInFunction(dict)
<< " Entry '"<< keyword << " Entry '"<< keyword
<< "' not a string or list of strings" << nl << "' not a string or list of strings" << nl
<< exit(FatalError); << exit(FatalIOError);
return result; return result;
} }

View File

@ -156,8 +156,7 @@ public:
//- Return named field (variable) if available //- Return named field (variable) if available
template<class Type> template<class Type>
tmp<Field<Type>> tmp<Field<Type>> getField(const word& fieldName) const;
getField(const word& fieldName) const;
// Custom Field Functions // Custom Field Functions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd. Copyright (C) 2019-2021 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.

View File

@ -173,8 +173,11 @@ svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN . svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
{ {
driver->reportFatal("Not implemented: " + make_obj(name.name_)); lhs = driver->getFunctionValue<Foam::scalar>
lhs = 0; (
make_obj(name.name_),
driver->timeValue()
);
} }
@ -193,8 +196,12 @@ vvalue (lhs) ::= VECTOR_VALUE (tok) .
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN . vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
{ {
driver->reportFatal("Not implemented: " + make_obj(name.name_)); auto val = driver->getFunctionValue<Foam::vector>
lhs = new Foam::vector(0,0,0); (
make_obj(name.name_),
driver->timeValue()
);
lhs = new Foam::vector(val);
} }
@ -253,8 +260,12 @@ _target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN.
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -283,8 +294,12 @@ rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }

File diff suppressed because it is too large Load Diff

View File

@ -219,12 +219,16 @@ static int driverTokenType
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ; decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ; number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ;
ident = ((alpha|'_') . ((alnum|[._])**)) ; identifier = ((alpha|'_') . ((alnum|[._])**)) ;
dquoted = '"' [^\"]+ '"' ; dquoted = '"' [^\"]+ '"' ;
squoted = "'" [^\']+ "'" ; squoted = "'" [^\']+ "'" ;
## Allow 'fn:' prefix for function identifier
ident = ('fn:')? identifier ;
## ===========
## The scanner ## The scanner
## ===========
main := |* main := |*
space*; space*;
@ -431,6 +435,22 @@ bool Foam::expressions::fieldExpr::scanner::dispatch_ident
do do
{ {
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isFunction<Type>(funcName)) \
{ \
ident = std::move(funcName); \
tokType = TokType; \
break; \
}
#ifdef TOK_SCALAR_FUNCTION_ID
doLocalCode(TOK_SCALAR_FUNCTION_ID, scalar);
#endif
#ifdef TOK_VECTOR_FUNCTION_ID
doLocalCode(TOK_VECTOR_FUNCTION_ID, vector);
#endif
#undef doLocalCode
} }
while (false); while (false);
} }

View File

@ -251,9 +251,8 @@ Foam::Ostream& Foam::expressions::fvExprDriver::writeCommon
os.writeEntry("globalScopes", globalScopes_); os.writeEntry("globalScopes", globalScopes_);
} }
// writeTable(os, "timelines", lines_); // Write "functions<scalar>" ...
// writeTable(os, "lookuptables", lookup_); writeFunctions(os);
// writeTable(os, "lookuptables2D", lookup2D_);
return os; return os;
} }

View File

@ -139,8 +139,11 @@ svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN . svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
{ {
driver->reportFatal("Not implemented: " + make_obj(name.name_)); lhs = driver->getFunctionValue<Foam::scalar>
lhs = 0; (
make_obj(name.name_),
driver->timeValue()
);
} }
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
@ -158,8 +161,12 @@ vvalue (lhs) ::= VECTOR_VALUE (tok) .
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN . vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
{ {
driver->reportFatal("Not implemented: " + make_obj(name.name_)); auto val = driver->getFunctionValue<Foam::vector>
lhs = new Foam::vector(0,0,0); (
make_obj(name.name_),
driver->timeValue()
);
lhs = new Foam::vector(val);
} }
@ -221,8 +228,12 @@ _target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN.
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -253,8 +264,12 @@ rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -397,8 +412,12 @@ rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -425,8 +444,12 @@ rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }

File diff suppressed because it is too large Load Diff

View File

@ -352,12 +352,16 @@ static int driverTokenType
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ; decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ; number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ;
ident = ((alpha|'_') . ((alnum|[._])**)) ; identifier = ((alpha|'_') . ((alnum|[._])**)) ;
dquoted = '"' [^\"]+ '"' ; dquoted = '"' [^\"]+ '"' ;
squoted = "'" [^\']+ "'" ; squoted = "'" [^\']+ "'" ;
## Allow 'fn:' prefix for function identifier
ident = ('fn:')? identifier ;
## ===========
## The scanner ## The scanner
## ===========
main := |* main := |*
space*; space*;
@ -571,6 +575,22 @@ bool Foam::expressions::patchExpr::scanner::dispatch_ident
do do
{ {
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isFunction<Type>(funcName)) \
{ \
ident = std::move(funcName); \
tokType = TokType; \
break; \
}
#ifdef TOK_SCALAR_FUNCTION_ID
doLocalCode(TOK_SCALAR_FUNCTION_ID, scalar);
#endif
#ifdef TOK_VECTOR_FUNCTION_ID
doLocalCode(TOK_VECTOR_FUNCTION_ID, vector);
#endif
#undef doLocalCode
} }
while (false); while (false);
} }

View File

@ -180,8 +180,11 @@ svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN . svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
{ {
driver->reportFatal("Not implemented: " + make_obj(name.name_)); lhs = driver->getFunctionValue<Foam::scalar>
lhs = 0; (
make_obj(name.name_),
driver->timeValue()
);
} }
@ -200,8 +203,12 @@ vvalue (lhs) ::= VECTOR_VALUE (tok) .
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN . vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
{ {
driver->reportFatal("Not implemented: " + make_obj(name.name_)); auto val = driver->getFunctionValue<Foam::vector>
lhs = new Foam::vector(0,0,0); (
make_obj(name.name_),
driver->timeValue()
);
lhs = new Foam::vector(val);
} }
@ -261,8 +268,12 @@ _target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN .
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -291,8 +302,12 @@ rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -420,8 +435,12 @@ rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<_value_typ
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -448,8 +467,12 @@ rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -584,8 +607,12 @@ rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<_value_typ
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
@ -659,8 +686,12 @@ rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN. _target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{ {
lhs = _new_target_; lhs = _new_target_;
(void) make_obj(values); driver->fillFunctionValues<_value_type_>
driver->reportFatal("Not implemented: " + make_obj(name.name_)); (
*lhs,
make_obj(name.name_),
make_obj(values)
);
} }
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\

File diff suppressed because it is too large Load Diff

View File

@ -371,12 +371,16 @@ static int driverTokenType
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ; decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ; number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ;
ident = ((alpha|'_') . ((alnum|[._])**)) ; identifier = ((alpha|'_') . ((alnum|[._])**)) ;
dquoted = '"' [^\"]+ '"' ; dquoted = '"' [^\"]+ '"' ;
squoted = "'" [^\']+ "'" ; squoted = "'" [^\']+ "'" ;
## Allow 'fn:' prefix for function identifier
ident = ('fn:')? identifier ;
## ===========
## The scanner ## The scanner
## ===========
main := |* main := |*
space*; space*;
@ -585,6 +589,22 @@ bool Foam::expressions::volumeExpr::scanner::dispatch_ident
do do
{ {
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isFunction<Type>(funcName)) \
{ \
ident = std::move(funcName); \
tokType = TokType; \
break; \
}
#ifdef TOK_SCALAR_FUNCTION_ID
doLocalCode(TOK_SCALAR_FUNCTION_ID, scalar);
#endif
#ifdef TOK_VECTOR_FUNCTION_ID
doLocalCode(TOK_VECTOR_FUNCTION_ID, vector);
#endif
#undef doLocalCode
} }
while (false); while (false);
} }