Merge branch 'feature-expr-improvements' into 'develop'

Updates for expressions to improve robustness and support functions, external context etc.

See merge request Development/openfoam!501
This commit is contained in:
Andrew Heather
2021-11-26 12:16:45 +00:00
55 changed files with 8275 additions and 6030 deletions

View File

@ -1,7 +1,7 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2106 |
| \\ / O peration | Version: v2112 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ 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

@ -21,6 +21,7 @@ Description
#include "uLabel.H"
#include "error.H"
#include "stringList.H"
#include "exprScanToken.H"
using namespace Foam;
@ -71,6 +72,34 @@ int main()
<< getName(expressions::valueTypeCode::type_bool) << nl;
{
expressions::scanToken tok;
expressions::scanToken tok2;
Info<< nl << "sizeof(scanToken): "
<< sizeof(tok) << nl;
Info<< " type:" << int(tok.type_) << nl;
Info<< " ptr:" << Foam::name(tok.name_) << nl;
Info<< " type:" << int(tok2.type_) << nl;
Info<< " ptr:" << Foam::name(tok2.name_) << nl;
tok.setWord("hello");
Info<< " type:" << int(tok.type_) << nl;
Info<< " ptr:" << Foam::name(tok.name_) << nl;
tok2 = tok;
Info<< " type:" << int(tok2.type_) << nl;
Info<< " ptr:" << Foam::name(tok2.name_) << nl;
tok2.destroy();
Info<< " type:" << int(tok2.type_) << nl;
Info<< " ptr:" << Foam::name(tok2.name_) << nl;
}
Info<< nl << "Done" << nl;
return 0;
}

View File

@ -162,11 +162,13 @@ $(expr)/exprResult/exprResultStored.C
$(expr)/exprResult/exprResultStoredStack.C
$(expr)/exprString/exprString.C
$(expr)/exprTools/exprTools.C
$(expr)/scanToken/exprScanToken.C
$(expr)/traits/exprTraits.C
$(expr)/exprDriver/exprDriver.C
$(expr)/exprDriver/exprDriverFields.C
$(expr)/exprDriver/exprDriverFunctions.C
$(expr)/exprDriver/exprDriverIO.C
fieldExpr = $(expr)/fields

View File

@ -98,6 +98,30 @@ static string getEntryString
return exprTools::expressionEntry::evaluate(*eptr);
}
#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
@ -118,6 +142,23 @@ void Foam::expressions::exprDriver::resetTimeReference(const TimeState& ts)
void Foam::expressions::exprDriver::resetDb(const objectRegistry* 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,9 @@ Foam::expressions::exprDriver::exprDriver
result_(),
variableStrings_(),
variables_(16),
scalarFuncs_(0),
vectorFuncs_(0),
contextObjects_(0),
arg1Value_(0),
timeStatePtr_(nullptr),
obrPtr_(nullptr),
@ -162,6 +206,9 @@ Foam::expressions::exprDriver::exprDriver
result_(rhs.result_),
variableStrings_(rhs.variableStrings_),
variables_(rhs.variables_),
scalarFuncs_(0),
vectorFuncs_(0),
contextObjects_(rhs.contextObjects_),
arg1Value_(rhs.arg1Value_),
timeStatePtr_(rhs.timeStatePtr_),
obrPtr_(rhs.obrPtr_),
@ -174,7 +221,16 @@ Foam::expressions::exprDriver::exprDriver
prevIterIsOldTime_(rhs.prevIterIsOldTime_),
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
@ -246,9 +302,9 @@ bool Foam::expressions::exprDriver::readDict
// Regular variables
variableStrings_ = readVariableStrings(dict);
// Other tables?
// readTable("timelines", dict, lines_);
// readTable("lookuptables", dict, lookup_);
// Create Function1s from dictionary content
resetFunctions(dict);
// readTable("lookuptables2D", dict, lookup2D_);
return true;

View File

@ -36,6 +36,8 @@ Description
\table
Property | Description | Required | Default
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
\endtable
@ -47,10 +49,16 @@ Description
debugParser | Add debug for parser | no | false
\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
exprDriverI.H
exprDriverContextI.H
exprDriver.C
exprDriverFields.C
exprDriverFunctions.C
exprDriverIO.C
exprDriverTemplates.C
@ -65,6 +73,9 @@ SourceFiles
#include "pointField.H"
#include "primitiveFields.H"
#include "objectRegistry.H"
#include "HashTable.H"
#include "HashSet.H"
#include "Function1.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -98,6 +109,10 @@ public:
};
//- Externally defined context fields
typedef HashTable<const regIOobject*> contextObjectTableType;
private:
// Private Member Functions
@ -105,6 +120,18 @@ private:
//- Get search/caching controls from dictionary entries
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:
@ -124,6 +151,17 @@ protected:
//- The variables table
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_;
//- Externally defined context fields
contextObjectTableType contextObjects_;
//- Special-purpose scalar reference argument
scalar arg1Value_;
@ -167,30 +205,8 @@ protected:
//- Reset the time-state reference
void resetTimeReference(const TimeState& ts);
//- Lookup field object.
// \return const-ref tmp or invalid if not found
template<class GeoField>
static tmp<GeoField>
cfindFieldObject(const objectRegistry& obr, const word& fldName);
//- Read an interpolation table
template<typename TableType>
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
);
//- Write scalar/vector Function1 entries in dictionary format
void writeFunctions(Ostream& os) const;
// Variables
@ -444,6 +460,59 @@ public:
);
// Context fields (similar to objectRegistry)
//- True if any context fields are defined
inline bool hasContextObjects() const;
//- Find named context field, if it exists
inline const regIOobject* cfindContextIOobject(const word& name) const;
//- Find context field object of specified type
// \return nullptr if not found
template<class ObjType>
const ObjType* cfindContextObject(const word& name) const;
//- Add the object to the context
inline void addContextObject(const word& name, const regIOobject*);
//- Add the object to the context
inline void addContextObject(const regIOobject*);
//- Remove the object from the context
inline void removeContextObject(const word& name);
//- Remove the object from the context
inline void removeContextObject(const regIOobject*);
//- Read access to the object context
inline const contextObjectTableType& contextObjects() const noexcept;
//- Write access to the object context
inline contextObjectTableType& contextObjects() noexcept;
// 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
//- Test existence of a local variable
@ -585,6 +654,7 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "exprDriverI.H"
#include "exprDriverContextI.H"
#ifdef NoRepository
#include "exprDriverTemplates.C"

View File

@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::expressions::exprDriver::hasContextObjects() const
{
return !contextObjects_.empty();
}
inline const Foam::regIOobject*
Foam::expressions::exprDriver::cfindContextIOobject
(
const word& name
) const
{
// Like objectRegistry::cfindIOobject()
return contextObjects_.lookup(name, nullptr);
}
inline void Foam::expressions::exprDriver::addContextObject
(
const word& name,
const regIOobject* objptr
)
{
if (objptr)
{
contextObjects_.set(name, objptr);
}
else
{
contextObjects_.erase(name);
}
}
inline void Foam::expressions::exprDriver::addContextObject
(
const regIOobject* objptr
)
{
if (objptr)
{
addContextObject(objptr->name(), objptr);
}
}
inline void Foam::expressions::exprDriver::removeContextObject
(
const word& name
)
{
contextObjects_.erase(name);
}
inline void Foam::expressions::exprDriver::removeContextObject
(
const regIOobject* objptr
)
{
if (objptr)
{
contextObjects_.erase(objptr->name());
}
}
inline const Foam::HashTable<const Foam::regIOobject*>&
Foam::expressions::exprDriver::contextObjects() const noexcept
{
return contextObjects_;
}
inline Foam::HashTable<const Foam::regIOobject*>&
Foam::expressions::exprDriver::contextObjects() noexcept
{
return contextObjects_;
}
template<class ObjType>
const ObjType*
Foam::expressions::exprDriver::cfindContextObject(const word& name) const
{
// Like objectRegistry::cfindObject()
return dynamic_cast<const ObjType*>(this->cfindContextIOobject(name));
}
// ************************************************************************* //

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

@ -28,81 +28,6 @@ License
#include "objectRegistry.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class GeoField>
Foam::tmp<GeoField>
Foam::expressions::exprDriver::cfindFieldObject
(
const objectRegistry& obr,
const word& fldName
)
{
tmp<GeoField> tfld;
tfld.cref(obr.cfindObject<GeoField>(fldName));
return tfld;
}
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 * * * * * * * * * * * //
template<class Type>
@ -180,6 +105,181 @@ Foam::expressions::exprDriver::getResult(bool wantPointData)
// * * * * * * * * * * * * * * * 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>
bool Foam::expressions::exprDriver::isLocalVariable
(

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -47,7 +47,6 @@ namespace fieldExpr
class parser;
class scanner;
class parseDriver;
union scanToken;
//- Static debugging option
extern int debug;

View File

@ -1,93 +1,99 @@
#define TOK_QUESTION 1
#define TOK_COLON 2
#define TOK_LOR 3
#define TOK_LAND 4
#define TOK_BIT_XOR 5
#define TOK_BIT_AND 6
#define TOK_EQUAL 7
#define TOK_NOT_EQUAL 8
#define TOK_LESS_EQ 9
#define TOK_GREATER_EQ 10
#define TOK_LESS 11
#define TOK_GREATER 12
#define TOK_PLUS 13
#define TOK_MINUS 14
#define TOK_TIMES 15
#define TOK_DIVIDE 16
#define TOK_PERCENT 17
#define TOK_NEGATE 18
#define TOK_NOT 19
#define TOK_DOT 20
#define TOK_NUMBER 21
#define TOK_ZERO 22
#define TOK_PI 23
#define TOK_LPAREN 24
#define TOK_RPAREN 25
#define TOK_DEG_TO_RAD 26
#define TOK_RAD_TO_DEG 27
#define TOK_ARG 28
#define TOK_TIME 29
#define TOK_DELTA_T 30
#define TOK_SCALAR_ID 31
#define TOK_MIN 32
#define TOK_COMMA 33
#define TOK_MAX 34
#define TOK_SUM 35
#define TOK_AVERAGE 36
#define TOK_EXP 37
#define TOK_LOG 38
#define TOK_LOG10 39
#define TOK_SQR 40
#define TOK_SQRT 41
#define TOK_CBRT 42
#define TOK_SIN 43
#define TOK_COS 44
#define TOK_TAN 45
#define TOK_ASIN 46
#define TOK_ACOS 47
#define TOK_ATAN 48
#define TOK_SINH 49
#define TOK_COSH 50
#define TOK_TANH 51
#define TOK_POW 52
#define TOK_ATAN2 53
#define TOK_POS 54
#define TOK_NEG 55
#define TOK_POS0 56
#define TOK_NEG0 57
#define TOK_SIGN 58
#define TOK_FLOOR 59
#define TOK_CEIL 60
#define TOK_ROUND 61
#define TOK_HYPOT 62
#define TOK_RAND 63
#define TOK_VECTOR_ID 64
#define TOK_SPH_TENSOR_ID 65
#define TOK_SYM_TENSOR_ID 66
#define TOK_IDENTITY_TENSOR 67
#define TOK_TENSOR_ID 68
#define TOK_LTRUE 69
#define TOK_LFALSE 70
#define TOK_BOOL 71
#define TOK_BOOL_ID 72
#define TOK_MAG 73
#define TOK_MAGSQR 74
#define TOK_VECTOR 75
#define TOK_TENSOR 76
#define TOK_SYM_TENSOR 77
#define TOK_SPH_TENSOR 78
#define TOK_CMPT_X 79
#define TOK_CMPT_Y 80
#define TOK_CMPT_Z 81
#define TOK_CMPT_XX 82
#define TOK_CMPT_XY 83
#define TOK_CMPT_XZ 84
#define TOK_CMPT_YX 85
#define TOK_CMPT_YY 86
#define TOK_CMPT_YZ 87
#define TOK_CMPT_ZX 88
#define TOK_CMPT_ZY 89
#define TOK_CMPT_ZZ 90
#define TOK_CMPT_II 91
#define TOK_TRANSPOSE 92
#define TOK_DIAG 93
#define TOK_LPAREN 1
#define TOK_RPAREN 2
#define TOK_COMMA 3
#define TOK_QUESTION 4
#define TOK_COLON 5
#define TOK_LOR 6
#define TOK_LAND 7
#define TOK_LNOT 8
#define TOK_BIT_OR 9
#define TOK_BIT_XOR 10
#define TOK_BIT_AND 11
#define TOK_BIT_NOT 12
#define TOK_EQUAL 13
#define TOK_NOT_EQUAL 14
#define TOK_LESS 15
#define TOK_LESS_EQ 16
#define TOK_GREATER 17
#define TOK_GREATER_EQ 18
#define TOK_PLUS 19
#define TOK_MINUS 20
#define TOK_TIMES 21
#define TOK_DIVIDE 22
#define TOK_PERCENT 23
#define TOK_NEGATE 24
#define TOK_DOT 25
#define TOK_BOOL 26
#define TOK_LTRUE 27
#define TOK_LFALSE 28
#define TOK_NUMBER 29
#define TOK_ZERO 30
#define TOK_IDENTIFIER 31
#define TOK_PI 32
#define TOK_DEG_TO_RAD 33
#define TOK_RAD_TO_DEG 34
#define TOK_ARG 35
#define TOK_TIME 36
#define TOK_DELTA_T 37
#define TOK_SCALAR_FUNCTION_ID 38
#define TOK_VECTOR_VALUE 39
#define TOK_VECTOR_FUNCTION_ID 40
#define TOK_SCALAR_ID 41
#define TOK_MIN 42
#define TOK_MAX 43
#define TOK_SUM 44
#define TOK_AVERAGE 45
#define TOK_EXP 46
#define TOK_LOG 47
#define TOK_LOG10 48
#define TOK_SQR 49
#define TOK_SQRT 50
#define TOK_CBRT 51
#define TOK_SIN 52
#define TOK_COS 53
#define TOK_TAN 54
#define TOK_ASIN 55
#define TOK_ACOS 56
#define TOK_ATAN 57
#define TOK_SINH 58
#define TOK_COSH 59
#define TOK_TANH 60
#define TOK_POW 61
#define TOK_ATAN2 62
#define TOK_POS 63
#define TOK_NEG 64
#define TOK_POS0 65
#define TOK_NEG0 66
#define TOK_SIGN 67
#define TOK_FLOOR 68
#define TOK_CEIL 69
#define TOK_ROUND 70
#define TOK_HYPOT 71
#define TOK_RAND 72
#define TOK_VECTOR_ID 73
#define TOK_SPH_TENSOR_ID 74
#define TOK_SYM_TENSOR_ID 75
#define TOK_IDENTITY_TENSOR 76
#define TOK_TENSOR_ID 77
#define TOK_BOOL_ID 78
#define TOK_MAG 79
#define TOK_MAGSQR 80
#define TOK_VECTOR 81
#define TOK_TENSOR 82
#define TOK_SYM_TENSOR 83
#define TOK_SPH_TENSOR 84
#define TOK_CMPT_X 85
#define TOK_CMPT_Y 86
#define TOK_CMPT_Z 87
#define TOK_CMPT_XX 88
#define TOK_CMPT_XY 89
#define TOK_CMPT_XZ 90
#define TOK_CMPT_YX 91
#define TOK_CMPT_YY 92
#define TOK_CMPT_YZ 93
#define TOK_CMPT_ZX 94
#define TOK_CMPT_ZY 95
#define TOK_CMPT_ZZ 96
#define TOK_CMPT_II 97
#define TOK_TRANSPOSE 98
#define TOK_DIAG 99

View File

@ -98,6 +98,7 @@ TBD
*/
%include
{
#include "exprScanToken.H"
#include "fieldExprDriver.H"
#include "fieldExprParser.H"
#include "fieldExprScanner.H"
@ -131,11 +132,8 @@ tmp_management()
%token_prefix TOK_
// Terminals
%token_type {Foam::expressions::fieldExpr::scanToken*}
// Non-terminals
%type ivalue { Foam::label }
%type svalue { Foam::scalar }
%type ident { Foam::word* }
%token_type {Foam::expressions::scanToken}
%token_destructor { ($$).destroy(); }
// Fields
declare_field(lfield, Foam::boolField, bool, newField, getField)
@ -150,6 +148,7 @@ declare_field(tfield, Foam::tensorField, Foam::tensor, newField, getField)
// Lemon does not generate a destructor for that.
// So do not use Lemon destructors for anything.
standard_tokens()
operator_precedence()
%start_symbol evaluate
@ -160,7 +159,10 @@ operator_precedence()
* Productions (scalar)
\*---------------------------------------------------------------------------*/
svalue (lhs) ::= NUMBER (a) . { lhs = (a)->svalue; } // From scanToken
%type svalue { Foam::scalar }
svalue (lhs) ::= NUMBER (tok) . { lhs = (tok).scalarValue; } // scanToken
svalue (lhs) ::= ZERO . { lhs = Foam::Zero; }
svalue (lhs) ::= PI LPAREN RPAREN . { lhs = Foam::constant::mathematical::pi; }
svalue (lhs) ::= DEG_TO_RAD LPAREN RPAREN . { lhs = Foam::degToRad(); }
@ -169,6 +171,39 @@ svalue (lhs) ::= ARG LPAREN RPAREN . { lhs = driver->argValue(); }
svalue (lhs) ::= TIME LPAREN RPAREN . { lhs = driver->timeValue(); }
svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
{
lhs = driver->getFunctionValue<Foam::scalar>
(
make_obj(name.name_),
driver->timeValue()
);
}
/*---------------------------------------------------------------------------*\
* Productions (vector)
\*---------------------------------------------------------------------------*/
%type vvalue { Foam::vector* }
%destructor vvalue { delete($$); $$ = nullptr; }
vvalue (lhs) ::= VECTOR_VALUE (tok) .
{
// Take ownership of pointer from scan token
lhs = tok.vectorPtr; tok.vectorPtr = nullptr;
}
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
{
auto val = driver->getFunctionValue<Foam::vector>
(
make_obj(name.name_),
driver->timeValue()
);
lhs = new Foam::vector(val);
}
/* * * * * * * * * * * * * * * * * * Fields * * * * * * * * * * * * * * * * *\
dnl
@ -184,7 +219,9 @@ dnl
/*---------------------------------------------------------------------------*\
* Productions (scalarField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [sfield])dnl
define([_new_target_], [_new_sfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -200,9 +237,9 @@ rules_scalar_operations()
rules_scalar_functions()
// Non-standard but manage via FieldOps::assign
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<_value_type_>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<_value_type_>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<_value_type_>())
// Non-standard but works directly for scalarField
rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
@ -217,20 +254,34 @@ _target_ (lhs) ::= RAND LPAREN RPAREN.
_target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN.
{
lhs = driver->field_rand(std::round((seed)->svalue)).ptr();
lhs = driver->field_rand(std::round((seed).scalarValue)).ptr();
}
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (vectorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [vfield])dnl
define([_new_target_], [_new_vfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, vvalue)
rule_get_field(_target_, VECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
@ -238,11 +289,26 @@ rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
// Other functions
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (sphericalTensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [hfield])dnl
define([_new_target_], [_new_hfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -260,7 +326,9 @@ rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (symmTensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [yfield])dnl
define([_new_target_], [_new_yfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -278,7 +346,9 @@ rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (tensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [tfield])dnl
define([_new_target_], [_new_tfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -300,6 +370,7 @@ rules_tensor_functions()
* Logic field productions (boolField)
dnl
define([_target_], [lfield])dnl
define([_new_target_], [_new_lfield])dnl
define([_value_type_], [bool])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -393,13 +464,15 @@ void Foam::expressions::fieldExpr::parser::start(parseDriver& driver_)
}
void Foam::expressions::fieldExpr::parser::parse
(
int tokenId,
scanToken* tokenVal
)
void Foam::expressions::fieldExpr::parser::parse(int tokenId)
{
Parse(lemon_, tokenId, tokenVal);
Parse(lemon_, tokenId, scanToken::null());
}
void Foam::expressions::fieldExpr::parser::parse(int tokenId, scanToken tok)
{
Parse(lemon_, tokenId, tok);
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,6 +34,7 @@ Description
#ifndef expressions_fieldExprParser_H
#define expressions_fieldExprParser_H
#include "exprScanToken.H"
#include "fieldExprFwd.H"
namespace Foam
@ -97,10 +98,14 @@ public:
//- Stop parsing, freeing the allocated parser
void stop();
//- Push token/value to parser
void parse(int tokenId, scanToken* tokenVal);
//- Push token type to parser with default token
void parse(int tokenId);
//- Push token type/value to parser
void parse(int tokenId, scanToken tok);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace fieldExpr

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -38,7 +38,6 @@ Note
#define expressions_fieldExprScanner_H
#include "fieldExprFwd.H"
#include "scalar.H"
namespace Foam
{
@ -47,21 +46,6 @@ namespace expressions
namespace fieldExpr
{
/*---------------------------------------------------------------------------*\
Class scanToken Declaration
\*---------------------------------------------------------------------------*/
union scanToken
{
Foam::label ivalue;
Foam::scalar svalue;
Foam::word* name;
//- Default construct, bit-wise zero for union content
scanToken() : ivalue(0) {}
};
/*---------------------------------------------------------------------------*\
Class scanner Declaration
\*---------------------------------------------------------------------------*/
@ -83,16 +67,14 @@ class scanner
bool dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident // Receives a copy
) const;
//- Dispatch identifier to parser (if possible) or Fatal
bool dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident // Receives a copy
) const;

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@ Description
\*---------------------------------------------------------------------------*/
#include "exprScanToken.H"
#include "fieldExprScanner.H"
#include "fieldExprDriver.H"
#include "fieldExprLemonParser.h"
@ -42,7 +43,6 @@ Description
#undef DebugInfo
#define DebugInfo if (debug & 0x2) InfoErr
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
@ -55,8 +55,9 @@ namespace Foam
#define TOKEN_PAIR(Name,T) { TOKEN_OF(T), Name }
//- An {int, c_str} enum pairing for field types
#define FIELD_PAIR(Fld,T) { TOKEN_OF(T), Fld::typeName.c_str() }
#define FIELD_PAIR(Fld,T) { TOKEN_OF(T), Fld::typeName.c_str() }
// No known look-back types
#undef HAS_LOOKBEHIND_TOKENS
// Special handling of predefined method types. Eg, .x(), .y(), ...
@ -121,22 +122,27 @@ static int driverTokenType
const word& ident
)
{
#ifdef HAS_LOOKBEHIND_TOKENS
// Get stashed "look-behind" to decide what type of identifier we expect
#endif
// Field variables
#ifdef TOK_SCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(TokType, Type) \
if (driver_.isLocalVariable<Type>(ident, false)) \
{ \
return TokType; \
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isLocalVariable<Type>(ident, false)) \
{ \
return TokType; \
}
checkFieldToken(TOK_SCALAR_ID, scalar);
checkFieldToken(TOK_VECTOR_ID, vector);
checkFieldToken(TOK_SYM_TENSOR_ID, symmTensor);
checkFieldToken(TOK_SPH_TENSOR_ID, sphericalTensor);
checkFieldToken(TOK_TENSOR_ID, tensor);
// Not tested: checkFieldToken(TOK_BOOL_ID, bool);
doLocalCode(TOK_SCALAR_ID, scalar);
doLocalCode(TOK_VECTOR_ID, vector);
doLocalCode(TOK_SYM_TENSOR_ID, symmTensor);
doLocalCode(TOK_SPH_TENSOR_ID, sphericalTensor);
doLocalCode(TOK_TENSOR_ID, tensor);
// Not tested: doLocalCode(TOK_BOOL_ID, bool);
#undef doLocalCode
}
#endif
@ -156,7 +162,15 @@ static int driverTokenType
#define EMIT_TOKEN(T) \
driver_.parsePosition() = (ts-buf); \
DebugInfo<< STRINGIFY(T) << " at " << driver_.parsePosition() << nl; \
parser_->parse(TOKEN_OF(T), nullptr); \
parser_->parse(TOKEN_OF(T)); \
driver_.parsePosition() = (p-buf);
#define EMIT_VECTOR_TOKEN(X, Y, Z) \
driver_.parsePosition() = (ts-buf); \
DebugInfo<< "VECTOR at " << driver_.parsePosition() << nl; \
scanToken scanTok; \
scanTok.setVector(X,Y,Z); \
parser_->parse(TOK_VECTOR_VALUE, scanTok); \
driver_.parsePosition() = (p-buf);
@ -165,15 +179,18 @@ static int driverTokenType
write data;
action emit_number {
// Emit number
driver_.parsePosition() = (ts-buf);
DebugInfo
<< "Number:" << std::string(ts, te-ts).c_str()
<< " at " << driver_.parsePosition() << nl;
if (readScalar(std::string(ts, te-ts), scanTok.svalue))
scanToken scanTok;
scanTok.setScalar(0);
if (readScalar(std::string(ts, te-ts), scanTok.scalarValue))
{
parser_->parse(TOKEN_OF(NUMBER), &scanTok);
parser_->parse(TOKEN_OF(NUMBER), scanTok);
}
else
{
@ -187,33 +204,38 @@ static int driverTokenType
}
action emit_ident {
// Emit identifier
driver_.parsePosition() = (ts-buf);
dispatch_ident(driver_, scanTok, word(ts, te-ts, false));
dispatch_ident(driver_, word(ts, te-ts, false));
driver_.parsePosition() = (p-buf);
}
action emit_method {
// Tokenized ".method" - dispatch '.' and "method" separately
driver_.parsePosition() = (ts-buf);
dispatch_method(driver_, scanTok, word(ts+1, te-ts-1, false));
dispatch_method(driver_, word(ts+1, te-ts-1, false));
driver_.parsePosition() = (p-buf);
}
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ;
ident = ((alpha|'_') . ((alnum|[._])**)) ;
identifier = ((alpha|'_') . ((alnum|[._])**)) ;
dquoted = '"' [^\"]+ '"' ;
squoted = "'" [^\']+ "'" ;
## Allow 'fn:' prefix for function identifier
ident = ('fn:')? identifier ;
## ===========
## The scanner
## ===========
main := |*
space*;
number => emit_number;
## Operators
'!' =>{ EMIT_TOKEN(NOT); };
'!' =>{ EMIT_TOKEN(LNOT); };
'%' =>{ EMIT_TOKEN(PERCENT); };
'(' =>{ EMIT_TOKEN(LPAREN); };
')' =>{ EMIT_TOKEN(RPAREN); };
@ -234,7 +256,7 @@ static int driverTokenType
'&&' =>{ EMIT_TOKEN(LAND); };
'||' =>{ EMIT_TOKEN(LOR); };
'&' =>{ EMIT_TOKEN(BIT_AND); };
## Not needed? '|' =>{ EMIT_TOKEN(BIT_OK); };
## Not needed? '|' =>{ EMIT_TOKEN(BIT_OR); };
'^' =>{ EMIT_TOKEN(BIT_XOR); };
## Some '.method' - Error if unknown
@ -286,13 +308,16 @@ static int driverTokenType
"sphericalTensor" =>{ EMIT_TOKEN(SPH_TENSOR); };
## Single value (constants, etc)
"Zero" =>{ EMIT_TOKEN(ZERO); };
"true" =>{ EMIT_TOKEN(LTRUE); };
"false" =>{ EMIT_TOKEN(LFALSE); };
"Zero" =>{ EMIT_TOKEN(ZERO); };
"vector::x" =>{ EMIT_VECTOR_TOKEN(1,0,0); };
"vector::y" =>{ EMIT_VECTOR_TOKEN(0,1,0); };
"vector::z" =>{ EMIT_VECTOR_TOKEN(0,0,1); };
"tensor::I" =>{ EMIT_TOKEN(IDENTITY_TENSOR); };
"arg" =>{ EMIT_TOKEN(ARG); };
## "time" =>{ EMIT_TOKEN(TIME); };
## "deltaT" =>{ EMIT_TOKEN(DELTA_T); };
"time" =>{ EMIT_TOKEN(TIME); };
"deltaT" =>{ EMIT_TOKEN(DELTA_T); };
## Identifier (field, etc - error if unknown)
## Handle 'bare' names and single/double quoted ones
@ -321,8 +346,7 @@ Foam::expressions::fieldExpr::scanner::~scanner()
bool Foam::expressions::fieldExpr::scanner::dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident
) const
{
if (ident[0] == '.')
@ -339,8 +363,8 @@ bool Foam::expressions::fieldExpr::scanner::dispatch_method
if (methType > 0)
{
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
parser_->parse(TOK_DOT);
parser_->parse(methType);
return true;
}
@ -353,10 +377,11 @@ bool Foam::expressions::fieldExpr::scanner::dispatch_method
bool Foam::expressions::fieldExpr::scanner::dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident
) const
{
// Peek at stashed "look-behind". It may influence decisions
int lookBehindTok = driver_.stashedTokenId();
int tokType = -1;
const bool quoted =
@ -381,12 +406,12 @@ bool Foam::expressions::fieldExpr::scanner::dispatch_ident
<< "Emit:" << ident << " function:"
<< parser_->tokenName(tokType) << nl;
parser_->parse(tokType, nullptr);
parser_->parse(tokType);
return true;
}
#ifdef HAS_LOOKBEHIND_TOKENS
// Specials such "cset" also reset the look-behind
// Specials such "cellSet" etc also reset the look-behind
tokType = lookBehindTokenEnums.lookup(ident, -1);
if (tokType > 0)
@ -396,17 +421,44 @@ bool Foam::expressions::fieldExpr::scanner::dispatch_ident
<< parser_->tokenName(tokType) << nl;
driver_.resetStashedTokenId(tokType);
parser_->parse(tokType, nullptr);
parser_->parse(tokType);
return true;
}
#endif
}
// Functions: scalar, vector, probably don't need others
// - "fn:" prefix to avoid any ambiguities
if (lookBehindTok <= 0 && ident.starts_with("fn:"))
{
word funcName(ident.substr(3)); // strip prefix
// Can also peek at stashed "look-behind"
// const int lookBehind = driver_.stashedTokenId();
do
{
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isFunction<Type>(funcName)) \
{ \
ident = std::move(funcName); \
tokType = TokType; \
break; \
}
tokType = driverTokenType(driver_, ident);
#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);
}
if (tokType <= 0)
{
tokType = driverTokenType(driver_, ident);
}
if (tokType > 0)
{
@ -414,8 +466,9 @@ bool Foam::expressions::fieldExpr::scanner::dispatch_ident
<< "Emit:" << ident << " token:"
<< parser_->tokenName(tokType) << nl;
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
scanToken scanTok;
scanTok.setWord(ident);
parser_->parse(tokType, scanTok);
return true;
}
@ -447,12 +500,13 @@ bool Foam::expressions::fieldExpr::scanner::dispatch_ident
// The field (before the ".")
ident.erase(dot);
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
scanToken scanTok;
scanTok.setWord(ident);
parser_->parse(tokType, scanTok);
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
parser_->parse(TOK_DOT);
parser_->parse(methType);
return true;
}
@ -515,9 +569,6 @@ bool Foam::expressions::fieldExpr::scanner::process
parser_->start(driver_);
// Scan token type
scanToken scanTok;
// Token start/end (Ragel naming)
const char* ts;
const char* te;
@ -547,7 +598,7 @@ bool Foam::expressions::fieldExpr::scanner::process
}
// Terminate parser execution
parser_->parse(0, nullptr);
parser_->parse(0);
parser_->stop();
if (debug & 0x6)

View File

@ -0,0 +1,92 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / 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 "exprScanToken.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::expressions::scanToken Foam::expressions::scanToken::null()
{
scanToken tok;
tok.type_ = LABEL;
tok.labelValue = 0;
return tok;
}
void Foam::expressions::scanToken::destroy()
{
if (type_ == VECTOR)
{
delete vectorPtr;
vectorPtr = nullptr;
}
else if (type_ == WORD)
{
delete wordPtr;
wordPtr = nullptr;
}
}
void Foam::expressions::scanToken::setLabel(label val)
{
type_ = LABEL;
labelValue = val;
}
void Foam::expressions::scanToken::setScalar(scalar val)
{
type_ = SCALAR;
scalarValue = val;
}
void Foam::expressions::scanToken::setVector(scalar x, scalar y, scalar z)
{
type_ = VECTOR;
vectorPtr = new Foam::vector(x, y, z);
}
void Foam::expressions::scanToken::setVector(const vector& val)
{
type_ = VECTOR;
vectorPtr = new Foam::vector(val);
}
void Foam::expressions::scanToken::setWord(const word& val)
{
type_ = WORD;
wordPtr = new Foam::word(val);
}
// ************************************************************************* //

View File

@ -0,0 +1,116 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019-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/>.
Class
Foam::expressions::scanToken
Description
A low-level input/scan token content.
No defined constructors/destructors.
All memory management is manual!
\*---------------------------------------------------------------------------*/
#ifndef expressions_scanToken_H
#define expressions_scanToken_H
#include "scalar.H"
#include "vector.H"
#include "word.H"
namespace Foam
{
namespace expressions
{
/*---------------------------------------------------------------------------*\
Class scanToken Declaration
\*---------------------------------------------------------------------------*/
struct scanToken
{
//- Tagged union types
enum tokenType : unsigned char
{
LABEL = 0,
SCALAR,
VECTOR,
WORD
};
// Data
//- The data content (as a union).
// For memory alignment have this appear as the first member.
union
{
Foam::label labelValue;
Foam::scalar scalarValue;
Foam::vector* vectorPtr;
Foam::word* wordPtr;
Foam::word* name_;
};
//- The token type
tokenType type_;
// Member Functions
//- Return a null token - in lieu of a default constructor
static scanToken null();
//- Assign type/value to be LABEL. Does not call destroy().
void setLabel(label val);
//- Assign type/value to be SCALAR. Does not call destroy().
void setScalar(scalar val);
//- Assign type/value to be VECTOR. Does not call destroy().
void setVector(scalar x, scalar y, scalar z);
//- Assign type/value to be VECTOR. Does not call destroy().
void setVector(const vector& val);
//- Assign type/value to be WORD (name). Does not call destroy().
void setWord(const word& val);
//- Manual deletion of pointer types
void destroy();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -9,8 +9,7 @@ divert(-1)dnl
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Named versions (as m4 macros) of single quoted characters to avoid

View File

@ -6,11 +6,10 @@ divert(-1)dnl
# \\ / A nd | www.openfoam.com
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2019 OpenCFD Ltd.
# Copyright (C) 2019-2021 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# A collection of 'base' setup of m4 macros for lemon, and setup
@ -34,7 +33,7 @@ divert(-1)dnl
# _sphTensor_, _symTensor_, _tensor_
#
# Values for the currently targeted rule
# _target_, _value_type_
# _target_, _value_type_, _scalar_arg_
#
# Note
# The `undefine' occur immediately upon inclusion of this file.
@ -109,18 +108,19 @@ Foam::tmp<T> make_tmp(T* p)
//- Default [make_obj] is pass-through
template<class T>
const T& make_obj(const T& obj)
const T& make_obj(const T& o) noexcept
{
return obj;
return o;
}
//- Move construct an object from a pointer and destroy the pointer
template<class T>
T make_obj(T* p)
T make_obj(T*& p)
{
T obj(std::move(*p));
T o(std::move(*p));
delete p;
return obj;
p = nullptr; // Prevent caller from deleting too
return o;
}]
)
@ -149,6 +149,7 @@ undefine([_tensor_])
undefine([_target_])
undefine([_value_type_])
undefine([_scalar_arg_])
#------------------------------------------------------------------------------
divert(0)dnl

View File

@ -6,11 +6,10 @@ divert(-1)dnl
# \\ / A nd | www.openfoam.com
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2019 OpenCFD Ltd.
# Copyright (C) 2019-2021 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Defines standard operator precedence macro for lemon grammar.
@ -20,18 +19,34 @@ divert(-1)dnl
define([operator_precedence],
[// [https://en.cppreference.com/w/cpp/language/operator_precedence]
%right QUESTION COLON . // 16: right-to-left
%left LOR . // 15:
%left LAND . // 14:
// %left BIT_OR . // 13 (unused)
%left BIT_XOR . // 12
%left BIT_AND . // 11
%left EQUAL NOT_EQUAL . // 10
%left LESS_EQ GREATER_EQ LESS GREATER . // 9
%left PLUS MINUS . // 6
%left TIMES DIVIDE PERCENT . // 5
%right NEGATE NOT . // 3: right-to-left
%left DOT . // 2: (method)]
%right QUESTION COLON . // 13: right-to-left
%left LOR . // 12:
%left LAND . // 11:
%left BIT_OR . // 10 (unused)
%left BIT_XOR . // 9
%left BIT_AND . // 8
%left EQUAL NOT_EQUAL . // 7
%left LESS LESS_EQ GREATER GREATER_EQ . // 6
%left PLUS MINUS . // 4
%left TIMES DIVIDE PERCENT . // 3
%right NEGATE LNOT BIT_NOT . // 2: right-to-left
%left DOT . // 1: (method)]
)
define([standard_tokens],
[// Standard tokens for operators, constants and common types]
%token
LPAREN RPAREN COMMA
QUESTION COLON LOR LAND LNOT
BIT_OR BIT_XOR BIT_AND BIT_NOT
EQUAL NOT_EQUAL
LESS LESS_EQ GREATER GREATER_EQ
PLUS MINUS TIMES DIVIDE PERCENT
NEGATE DOT
BOOL LTRUE LFALSE
NUMBER ZERO IDENTIFIER
.
)
#------------------------------------------------------------------------------

View File

@ -9,8 +9,7 @@ divert(-1)dnl
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Various "boilerplate" parser methods (C++)

View File

@ -9,8 +9,7 @@ divert(-1)dnl
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Collection of VectorSpace `component' functions

View File

@ -9,8 +9,7 @@ divert(-1)dnl
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Rules for vector/tensor `zip' functions, which are used to combine

View File

@ -62,39 +62,20 @@ define([_get_]$1, [driver->$5<$3>($][1).ptr()])dnl
# Example
# rule_get_field(sfield, SCALAR_ID)
#
# sfield (lhs) ::= SCALAR_ID (ident) .
# sfield (lhs) ::= SCALAR_ID (name) .
# {
# lhs = driver->getVolField<Foam::scalar>(make_obj(ident->name)).ptr();
# lhs = driver->getVolField<Foam::scalar>(make_obj(name.name_)).ptr();
# }
#------------------------------------------------------------------------------
define([rule_get_field],
[$1 (lhs) ::= $2 (ident) .
[$1 (lhs) ::= $2 (name) .
{
lhs = _get_$1(make_obj(ident->name));
lhs = _get_$1(make_obj(name.name_));
}]
)
#------------------------------------------------------------------------------
# rule_driver_select(out, tok, method)
#
# Description
# Production rule for driver get cell/face/point selection methods
#
# Example
# rule_driver_select(sfield, CSET, field_cellSet)
#
# sfield (lhs) ::= CSET LPAREN IDENTIFIER (ident) RPAREN .
# {
# lhs = driver->field_cellSet(make_obj(ident->name)).ptr();
# }
#------------------------------------------------------------------------------
define([rule_driver_select],
[rule_driver_unary_named($1, $2, IDENTIFIER, $3)])
#------------------------------------------------------------------------------
# rule_field_from_value(out, in, [prefix])
#
@ -454,19 +435,19 @@ ifelse($5,[],[],[<$5>])dnl # Optional template parameter (value_type)
# Foam::scalar
# )
#
# sfield(lhs) ::= SN_GRAD LPAREN SCALAR_ID (ident) RPAREN .
# sfield(lhs) ::= SN_GRAD LPAREN SCALAR_ID (name) RPAREN .
# {
# lhs = driver->patchNormalField<Foam::scalar>(make_obj(ident->name)).ptr();
# lhs = driver->patchNormalField<Foam::scalar>(make_obj(name.name_)).ptr();
# }
#
#------------------------------------------------------------------------------
define([rule_driver_unary_named],
[$1 (lhs) ::= $2 LPAREN $3 (ident) RPAREN .
[$1 (lhs) ::= $2 LPAREN $3 (name) RPAREN .
{
lhs = driver->$4[]dnl # The method call
ifelse($5,[],[],[<$5>])dnl # Optional template parameter (value_type)
(make_obj(ident->name)).ptr();
(make_obj(name.name_)).ptr();
}]
)

View File

@ -9,8 +9,7 @@ divert(-1)dnl
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Collection of `standard' functions and type-specific ones.

View File

@ -9,8 +9,7 @@ divert(-1)dnl
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Collection of `standard' operations and type-specific ones.

View File

@ -9,8 +9,7 @@ divert(-1)dnl
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Logic rules, using bool or Foam::scalar for its storage.
@ -98,7 +97,7 @@ define([rule_logical_or],
)
define([rule_logical_negate],
[$1 (lhs) ::= NOT $1 (a). _lemon_precedence(NEGATE)
[$1 (lhs) ::= LNOT $1 (a). _lemon_precedence(NEGATE)
{
lhs = a;
Foam::FieldOps::assign

View File

@ -9,8 +9,7 @@ divert(-1)dnl
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, distributed under GNU General Public
# License GPL-3.0 or later <https://www.gnu.org/licenses/gpl-3.0>
# This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
#
# Description
# Collection of common functions that should work on all (non-logical)

View File

@ -471,8 +471,8 @@ public:
//- Return cell/face/point zone/set type or unknown
topoSetSource::sourceType topoSourceType(const word& name) const;
//- Read and return labels associated with the topo set
labelList getTopoSetLabels
//- Get the labels associated with the topo set
refPtr<labelList> getTopoSetLabels
(
const word& name,
enum topoSetSource::sourceType setType

View File

@ -34,13 +34,17 @@ License
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
Foam::refPtr<Foam::labelList>
Foam::expressions::fvExprDriver::getTopoSetLabels
(
const word& name,
enum topoSetSource::sourceType setType
) const
{
// Zones first - they are cheap to handle (no IO)
refPtr<labelList> selected;
// Zones first
// - cheap to handle (no IO) and can simply reference their labels
switch (setType)
{
@ -58,7 +62,7 @@ Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
<< exit(FatalError);
}
return zones[zoneID];
selected.cref(zones[zoneID]);
break;
}
@ -76,7 +80,7 @@ Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
<< exit(FatalError);
}
return zones[zoneID];
selected.cref(zones[zoneID]);
break;
}
@ -94,7 +98,7 @@ Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
<< exit(FatalError);
}
return zones[zoneID];
selected.cref(zones[zoneID]);
break;
}
@ -103,6 +107,12 @@ Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
}
if (selected.valid())
{
return selected;
}
IOobject io(topoSet::findIOobject(mesh(), name));
switch (setType)
@ -121,7 +131,7 @@ Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
}
classType set(io);
return set.sortedToc();
selected.reset(refPtr<labelList>::New(set.sortedToc()));
break;
}
@ -139,7 +149,7 @@ Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
}
classType set(io);
return set.sortedToc();
selected.reset(refPtr<labelList>::New(set.sortedToc()));
break;
}
@ -157,7 +167,7 @@ Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
}
classType set(io);
return set.sortedToc();
selected.reset(refPtr<labelList>::New(set.sortedToc()));
break;
}
@ -171,7 +181,7 @@ Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
}
}
return labelList::null();
return selected;
}
@ -251,9 +261,8 @@ Foam::Ostream& Foam::expressions::fvExprDriver::writeCommon
os.writeEntry("globalScopes", globalScopes_);
}
// writeTable(os, "timelines", lines_);
// writeTable(os, "lookuptables", lookup_);
// writeTable(os, "lookuptables2D", lookup2D_);
// Write "functions<scalar>" ...
writeFunctions(os);
return os;
}

View File

@ -146,31 +146,57 @@ bool Foam::expressions::fvExprDriver::foundField
<< " disk:" << searchFiles() << endl;
}
// if (std::is_void<Type>::value) ...
if (searchRegistry())
for (int checki = 0; checki < 2; ++checki)
{
const regIOobject* ioptr =
this->mesh().cfindObject<regIOobject>(name);
// Check 0: object context (first)
// Check 1: regular objectRegistry
const regIOobject* ioptr = nullptr;
if (this->mesh().foundObject<Type>(name))
if (checki == 0)
{
ioptr = exprDriver::cfindContextIOobject(name);
}
else if (searchRegistry())
{
ioptr = this->mesh().cfindIOobject(name);
}
if (!ioptr) continue;
const Type* fldPtr = dynamic_cast<const Type*>(ioptr);
if (fldPtr)
{
if (debug)
{
Info<< "Found registered: " << name << endl;
if (checki)
{
Info<< "Found registered:";
}
else
{
Info<< "Found context object:";
}
Info<< name << endl;
}
return true;
}
if (debug)
else if (ioptr)
{
Info<< "Registered " << name;
if (ioptr)
if (debug)
{
Info<< " type:" << ioptr->headerClassName();
if (checki)
{
Info<< "Registered:";
}
else
{
Info<< "Context object:";
}
Info<< name << " type:"
<< ioptr->headerClassName() << " != type:"
<< Type::typeName << nl;
}
Info<< ", not type:" << Type::typeName << nl;
}
}
@ -183,14 +209,11 @@ bool Foam::expressions::fvExprDriver::foundField
}
return true;
}
else
{
if (debug)
{
Info<< name << " not found" << endl;
}
}
if (debug)
{
Info<< name << " not found" << endl;
}
return false;
}
@ -236,12 +259,18 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
{
typedef typename GeomField::value_type Type;
tmp<GeomField> tfield;
if (debug)
{
Info<< "fvExprDriver::getOrReadField <" << name
<< "> Type: " << GeomField::typeName << endl;
}
// Handle variables
// ~~~~~~~~~~~~~~~~
refPtr<expressions::exprResult> tvar;
if (hasVariable(name) && variable(name).isType<Type>())
@ -253,9 +282,6 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
tvar.cref(lookupGlobal(name));
}
tmp<GeomField> tfield;
if (tvar.valid())
{
const auto& var = tvar.cref();
@ -327,24 +353,45 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
}
const objectRegistry& obr = meshRef.thisDb();
// Find context or registered field
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
const GeomField* origFldPtr;
const GeomField* origFldPtr = nullptr;
if
(
searchRegistry()
&& (origFldPtr = obr.cfindObject<GeomField>(name)) != nullptr
)
for (int checki = 0; !origFldPtr && checki < 2; ++checki)
{
// Check 0: object context (first)
// Check 1: regular objectRegistry
if (checki == 0)
{
origFldPtr = exprDriver::cfindContextObject<GeomField>(name);
}
else if (searchRegistry())
{
origFldPtr =
meshRef.thisDb().template cfindObject<GeomField>(name);
}
}
if (origFldPtr)
{
// Found from context or registry
if (debug)
{
Info<< "Retrieve registered: " << name << nl;
Info<< "Retrieve context/registered:" << name << nl;
}
const GeomField& origFld = *origFldPtr;
// Avoid shadowing the original object
// Make a deep copy of the data to return. Avoids shadowing
// the original object, but most importantly the backend
// parser (eg, lemon) will be working with combining via plain
// pointers. We thus lose any of the tmp<> shallow copy semantics
// anyhow. Additionally, need to disable dimension checking here or
// elsewhere too.
tfield = GeomField::New(name + "_exprDriverCopy", origFld);
if (getOldTime)
@ -445,9 +492,8 @@ Foam::autoPtr<T> Foam::expressions::fvExprDriver::getTopoSet
if (debug)
{
Info<< "Looking for " << T::typeName << " named " << name;
Info<< " or registered as " << regName << " with mesh "
Info<< "Looking for " << T::typeName << " named " << name
<< " or registered as " << regName << " with mesh "
<< "Caching:" << cacheSets()
<< " Found:" << (mesh.foundObject<T>(name))
<< " Found registered:" << mesh.foundObject<T>(regName)
@ -494,7 +540,7 @@ Foam::autoPtr<T> Foam::expressions::fvExprDriver::getTopoSet
}
else
{
const T* ptr = mesh.thisDb().cfindObject<T>(name);
const T* ptr = mesh.thisDb().template cfindObject<T>(name);
if (ptr)
{

View File

@ -111,6 +111,21 @@ protected:
// Protected Member Functions
//- Cell selections (as logical)
tmp<boolField> field_cellSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const;
//- Face selections (as logical)
tmp<boolField> field_faceSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const;
// No copy copy construct
parseDriver(const parseDriver&) = delete;
@ -281,6 +296,20 @@ public:
//- The patch point locations - (swak = pts)
tmp<vectorField> field_pointField() const;
//- Cell selection (set)
inline tmp<boolField> field_cellSet(const word& name) const;
//- Cell selection (zone)
inline tmp<boolField> field_cellZone(const word& name) const;
//- Face selection (set)
inline tmp<boolField> field_faceSet(const word& name) const;
//- Face selection (zone)
inline tmp<boolField> field_faceZone(const word& name) const;
//- A uniform random field
tmp<scalarField> field_rand(label seed=0, bool gaussian=false) const;

View File

@ -55,6 +55,97 @@ Foam::expressions::patchExpr::parseDriver::getPointField<bool>
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::boolField>
Foam::expressions::patchExpr::parseDriver::field_cellSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const
{
refPtr<labelList> tselected;
switch (setType)
{
case topoSetSource::sourceType::CELLZONE_SOURCE:
case topoSetSource::sourceType::CELLSET_SOURCE:
{
tselected = getTopoSetLabels(name, setType);
break;
}
default:
{
FatalErrorInFunction
<< "Unexpected sourceType: " << int(setType) << nl
<< exit(FatalError);
break;
}
}
// Not particularly efficient...
labelHashSet inSelection(tselected());
const labelList& faceCells = patch_.faceCells();
auto tresult = tmp<boolField>::New(this->size(), false);
auto& result = tresult.ref();
forAll(result, facei)
{
if (inSelection.found(faceCells[facei]))
{
result[facei] = true;
}
}
return tresult;
}
Foam::tmp<Foam::boolField>
Foam::expressions::patchExpr::parseDriver::field_faceSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const
{
refPtr<labelList> tselected;
switch (setType)
{
case topoSetSource::sourceType::FACESET_SOURCE:
case topoSetSource::sourceType::FACEZONE_SOURCE:
{
tselected = getTopoSetLabels(name, setType);
break;
}
default:
{
FatalErrorInFunction
<< "Unexpected sourceType: " << int(setType) << nl
<< exit(FatalError);
break;
}
}
// Not particularly efficient...
labelHashSet inSelection(tselected());
const label patchStart = patch_.start();
auto tresult = tmp<boolField>::New(this->size(), false);
auto& result = tresult.ref();
forAll(result, facei)
{
if (inSelection.found(facei + patchStart))
{
result[facei] = true;
}
}
return tresult;
}
Foam::tmp<Foam::scalarField>
Foam::expressions::patchExpr::parseDriver::field_faceArea() const
{

View File

@ -47,4 +47,60 @@ inline Foam::label Foam::expressions::patchExpr::parseDriver::size
}
inline Foam::tmp<Foam::boolField>
Foam::expressions::patchExpr::parseDriver::parseDriver::field_cellSet
(
const word& name
) const
{
return field_cellSelection
(
name,
topoSetSource::sourceType::CELLSET_SOURCE
);
}
inline Foam::tmp<Foam::boolField>
Foam::expressions::patchExpr::parseDriver::field_cellZone
(
const word& name
) const
{
return field_cellSelection
(
name,
topoSetSource::sourceType::CELLZONE_SOURCE
);
}
inline Foam::tmp<Foam::boolField>
Foam::expressions::patchExpr::parseDriver::field_faceSet
(
const word& name
) const
{
return field_faceSelection
(
name,
topoSetSource::sourceType::FACESET_SOURCE
);
}
inline Foam::tmp<Foam::boolField>
Foam::expressions::patchExpr::parseDriver::field_faceZone
(
const word& name
) const
{
return field_faceSelection
(
name,
topoSetSource::sourceType::FACEZONE_SOURCE
);
}
// ************************************************************************* //

View File

@ -125,28 +125,43 @@ Foam::expressions::patchExpr::parseDriver::getField(const word& name)
typedef GeometricField<Type, pointPatchField, pointMesh> pfieldType;
// Local, temporary storage and/or lookup values
bool findField = true;
bool found = false;
tmp<vfieldType> vfield;
tmp<sfieldType> sfield;
tmp<pfieldType> pfield;
if (findField)
for (int checki = 0; !found && checki < 2; ++checki)
{
vfield = exprDriver::cfindFieldObject<vfieldType>(obr, name);
findField = !vfield.valid();
}
if (findField)
{
sfield = exprDriver::cfindFieldObject<sfieldType>(obr, name);
findField = !sfield.valid();
}
if (findField)
{
pfield = exprDriver::cfindFieldObject<pfieldType>(obr, name);
findField = !pfield.valid();
// Check 0: object context (first)
// Check 1: regular objectRegistry
const regIOobject* ioptr =
(
(checki == 0)
? exprDriver::cfindContextIOobject(name)
: obr.cfindIOobject(name)
);
if (!ioptr) continue;
if (!found)
{
vfield.cref(dynamic_cast<const vfieldType*>(ioptr));
found = vfield.valid();
}
if (!found)
{
sfield.cref(dynamic_cast<const sfieldType*>(ioptr));
found = sfield.valid();
}
if (!found)
{
pfield.cref(dynamic_cast<const pfieldType*>(ioptr));
found = pfield.valid();
}
}
if (findField && searchFiles())
// Finally, search files if necessary (and permitted)
if (!found && searchFiles())
{
const word fldType = this->getTypeOfField(name);
@ -236,22 +251,37 @@ Foam::expressions::patchExpr::parseDriver::patchInternalField
typedef GeometricField<Type, pointPatchField, pointMesh> pfieldType;
// Local, temporary storage and/or lookup values
bool findField = true;
bool found = false;
tmp<vfieldType> vfield;
tmp<pfieldType> pfield;
if (findField)
for (int checki = 0; !found && checki < 2; ++checki)
{
vfield = exprDriver::cfindFieldObject<vfieldType>(obr, name);
findField = !vfield.valid();
}
if (findField)
{
pfield = exprDriver::cfindFieldObject<pfieldType>(obr, name);
findField = !pfield.valid();
// Check 0: object context (first)
// Check 1: regular objectRegistry
const regIOobject* ioptr =
(
(checki == 0)
? exprDriver::cfindContextIOobject(name)
: obr.cfindIOobject(name)
);
if (!ioptr) continue;
if (!found)
{
vfield.cref(dynamic_cast<const vfieldType*>(ioptr));
found = vfield.valid();
}
if (!found)
{
pfield.cref(dynamic_cast<const pfieldType*>(ioptr));
found = pfield.valid();
}
}
if (findField && searchFiles())
// Finally, search files if necessary (and permitted)
if (!found && searchFiles())
{
const word fldType = this->getTypeOfField(name);
@ -322,16 +352,31 @@ Foam::expressions::patchExpr::parseDriver::patchNeighbourField
typedef GeometricField<Type, fvPatchField, volMesh> vfieldType;
// Local, temporary storage and/or lookup values
bool findField = true;
bool found = false;
tmp<vfieldType> vfield;
if (findField)
for (int checki = 0; !found && checki < 2; ++checki)
{
vfield = exprDriver::cfindFieldObject<vfieldType>(obr, name);
findField = !vfield.valid();
// Check 0: object context (first)
// Check 1: regular objectRegistry
const regIOobject* ioptr =
(
(checki == 0)
? exprDriver::cfindContextIOobject(name)
: obr.cfindIOobject(name)
);
if (!ioptr) continue;
if (!found)
{
vfield.cref(dynamic_cast<const vfieldType*>(ioptr));
found = vfield.valid();
}
}
if (findField && searchFiles())
// Finally, search files if necessary (and permitted)
if (!found && searchFiles())
{
const word fldType = this->getTypeOfField(name);
@ -386,16 +431,31 @@ Foam::expressions::patchExpr::parseDriver::patchNormalField
typedef GeometricField<Type, fvPatchField, volMesh> vfieldType;
// Local, temporary storage and/or lookup values
bool found = false;
tmp<vfieldType> vfield;
bool findField = true;
if (findField)
for (int checki = 0; !found && checki < 2; ++checki)
{
vfield = exprDriver::cfindFieldObject<vfieldType>(obr, name);
findField = !vfield.valid();
// Check 0: object context (first)
// Check 1: regular objectRegistry
const regIOobject* ioptr =
(
(checki == 0)
? exprDriver::cfindContextIOobject(name)
: obr.cfindIOobject(name)
);
if (!ioptr) continue;
if (!found)
{
vfield.cref(dynamic_cast<const vfieldType*>(ioptr));
found = vfield.valid();
}
}
if (findField && searchFiles())
// Finally, search files if necessary (and permitted)
if (!found && searchFiles())
{
const word fldType = this->getTypeOfField(name);

View File

@ -47,7 +47,6 @@ namespace patchExpr
class parser;
class scanner;
class parseDriver;
union scanToken;
//- Static debugging option
extern int debug;

View File

@ -1,115 +1,125 @@
#define TOK_QUESTION 1
#define TOK_COLON 2
#define TOK_LOR 3
#define TOK_LAND 4
#define TOK_BIT_XOR 5
#define TOK_BIT_AND 6
#define TOK_EQUAL 7
#define TOK_NOT_EQUAL 8
#define TOK_LESS_EQ 9
#define TOK_GREATER_EQ 10
#define TOK_LESS 11
#define TOK_GREATER 12
#define TOK_PLUS 13
#define TOK_MINUS 14
#define TOK_TIMES 15
#define TOK_DIVIDE 16
#define TOK_PERCENT 17
#define TOK_NEGATE 18
#define TOK_NOT 19
#define TOK_DOT 20
#define TOK_NUMBER 21
#define TOK_ZERO 22
#define TOK_PI 23
#define TOK_LPAREN 24
#define TOK_RPAREN 25
#define TOK_DEG_TO_RAD 26
#define TOK_RAD_TO_DEG 27
#define TOK_ARG 28
#define TOK_TIME 29
#define TOK_DELTA_T 30
#define TOK_SCALAR_ID 31
#define TOK_SSCALAR_ID 32
#define TOK_INTERNAL_FIELD 33
#define TOK_NEIGHBOUR_FIELD 34
#define TOK_SN_GRAD 35
#define TOK_MIN 36
#define TOK_COMMA 37
#define TOK_MAX 38
#define TOK_SUM 39
#define TOK_AVERAGE 40
#define TOK_EXP 41
#define TOK_LOG 42
#define TOK_LOG10 43
#define TOK_SQR 44
#define TOK_SQRT 45
#define TOK_CBRT 46
#define TOK_SIN 47
#define TOK_COS 48
#define TOK_TAN 49
#define TOK_ASIN 50
#define TOK_ACOS 51
#define TOK_ATAN 52
#define TOK_SINH 53
#define TOK_COSH 54
#define TOK_TANH 55
#define TOK_POW 56
#define TOK_ATAN2 57
#define TOK_POS 58
#define TOK_NEG 59
#define TOK_POS0 60
#define TOK_NEG0 61
#define TOK_SIGN 62
#define TOK_FLOOR 63
#define TOK_CEIL 64
#define TOK_ROUND 65
#define TOK_HYPOT 66
#define TOK_RAND 67
#define TOK_VECTOR_ID 68
#define TOK_SVECTOR_ID 69
#define TOK_SPH_TENSOR_ID 70
#define TOK_SSPH_TENSOR_ID 71
#define TOK_SYM_TENSOR_ID 72
#define TOK_SSYM_TENSOR_ID 73
#define TOK_IDENTITY_TENSOR 74
#define TOK_TENSOR_ID 75
#define TOK_STENSOR_ID 76
#define TOK_LTRUE 77
#define TOK_LFALSE 78
#define TOK_BOOL 79
#define TOK_SBOOL_ID 80
#define TOK_FACE_AREA 81
#define TOK_FACE_EXPR 82
#define TOK_WEIGHT_AVERAGE 83
#define TOK_WEIGHT_SUM 84
#define TOK_POINT_EXPR 85
#define TOK_PSCALAR_ID 86
#define TOK_PVECTOR_ID 87
#define TOK_PSPH_TENSOR_ID 88
#define TOK_PSYM_TENSOR_ID 89
#define TOK_PTENSOR_ID 90
#define TOK_PBOOL_ID 91
#define TOK_POINTS 92
#define TOK_MAG 93
#define TOK_MAGSQR 94
#define TOK_VECTOR 95
#define TOK_TENSOR 96
#define TOK_SYM_TENSOR 97
#define TOK_SPH_TENSOR 98
#define TOK_CMPT_X 99
#define TOK_CMPT_Y 100
#define TOK_CMPT_Z 101
#define TOK_CMPT_XX 102
#define TOK_CMPT_XY 103
#define TOK_CMPT_XZ 104
#define TOK_CMPT_YX 105
#define TOK_CMPT_YY 106
#define TOK_CMPT_YZ 107
#define TOK_CMPT_ZX 108
#define TOK_CMPT_ZY 109
#define TOK_CMPT_ZZ 110
#define TOK_CMPT_II 111
#define TOK_TRANSPOSE 112
#define TOK_DIAG 113
#define TOK_POINT_TO_FACE 114
#define TOK_FACE_TO_POINT 115
#define TOK_LPAREN 1
#define TOK_RPAREN 2
#define TOK_COMMA 3
#define TOK_QUESTION 4
#define TOK_COLON 5
#define TOK_LOR 6
#define TOK_LAND 7
#define TOK_LNOT 8
#define TOK_BIT_OR 9
#define TOK_BIT_XOR 10
#define TOK_BIT_AND 11
#define TOK_BIT_NOT 12
#define TOK_EQUAL 13
#define TOK_NOT_EQUAL 14
#define TOK_LESS 15
#define TOK_LESS_EQ 16
#define TOK_GREATER 17
#define TOK_GREATER_EQ 18
#define TOK_PLUS 19
#define TOK_MINUS 20
#define TOK_TIMES 21
#define TOK_DIVIDE 22
#define TOK_PERCENT 23
#define TOK_NEGATE 24
#define TOK_DOT 25
#define TOK_BOOL 26
#define TOK_LTRUE 27
#define TOK_LFALSE 28
#define TOK_NUMBER 29
#define TOK_ZERO 30
#define TOK_IDENTIFIER 31
#define TOK_PI 32
#define TOK_DEG_TO_RAD 33
#define TOK_RAD_TO_DEG 34
#define TOK_ARG 35
#define TOK_TIME 36
#define TOK_DELTA_T 37
#define TOK_SCALAR_FUNCTION_ID 38
#define TOK_VECTOR_VALUE 39
#define TOK_VECTOR_FUNCTION_ID 40
#define TOK_SCALAR_ID 41
#define TOK_SSCALAR_ID 42
#define TOK_INTERNAL_FIELD 43
#define TOK_NEIGHBOUR_FIELD 44
#define TOK_SN_GRAD 45
#define TOK_MIN 46
#define TOK_MAX 47
#define TOK_SUM 48
#define TOK_AVERAGE 49
#define TOK_EXP 50
#define TOK_LOG 51
#define TOK_LOG10 52
#define TOK_SQR 53
#define TOK_SQRT 54
#define TOK_CBRT 55
#define TOK_SIN 56
#define TOK_COS 57
#define TOK_TAN 58
#define TOK_ASIN 59
#define TOK_ACOS 60
#define TOK_ATAN 61
#define TOK_SINH 62
#define TOK_COSH 63
#define TOK_TANH 64
#define TOK_POW 65
#define TOK_ATAN2 66
#define TOK_POS 67
#define TOK_NEG 68
#define TOK_POS0 69
#define TOK_NEG0 70
#define TOK_SIGN 71
#define TOK_FLOOR 72
#define TOK_CEIL 73
#define TOK_ROUND 74
#define TOK_HYPOT 75
#define TOK_RAND 76
#define TOK_VECTOR_ID 77
#define TOK_SVECTOR_ID 78
#define TOK_SPH_TENSOR_ID 79
#define TOK_SSPH_TENSOR_ID 80
#define TOK_SYM_TENSOR_ID 81
#define TOK_SSYM_TENSOR_ID 82
#define TOK_IDENTITY_TENSOR 83
#define TOK_TENSOR_ID 84
#define TOK_STENSOR_ID 85
#define TOK_SBOOL_ID 86
#define TOK_CELL_SET 87
#define TOK_CELL_ZONE 88
#define TOK_FACE_SET 89
#define TOK_FACE_ZONE 90
#define TOK_FACE_AREA 91
#define TOK_FACE_EXPR 92
#define TOK_WEIGHT_AVERAGE 93
#define TOK_WEIGHT_SUM 94
#define TOK_POINT_EXPR 95
#define TOK_PSCALAR_ID 96
#define TOK_PVECTOR_ID 97
#define TOK_PSPH_TENSOR_ID 98
#define TOK_PSYM_TENSOR_ID 99
#define TOK_PTENSOR_ID 100
#define TOK_PBOOL_ID 101
#define TOK_POINTS 102
#define TOK_MAG 103
#define TOK_MAGSQR 104
#define TOK_VECTOR 105
#define TOK_TENSOR 106
#define TOK_SYM_TENSOR 107
#define TOK_SPH_TENSOR 108
#define TOK_CMPT_X 109
#define TOK_CMPT_Y 110
#define TOK_CMPT_Z 111
#define TOK_CMPT_XX 112
#define TOK_CMPT_XY 113
#define TOK_CMPT_XZ 114
#define TOK_CMPT_YX 115
#define TOK_CMPT_YY 116
#define TOK_CMPT_YZ 117
#define TOK_CMPT_ZX 118
#define TOK_CMPT_ZY 119
#define TOK_CMPT_ZZ 120
#define TOK_CMPT_II 121
#define TOK_TRANSPOSE 122
#define TOK_DIAG 123
#define TOK_POINT_TO_FACE 124
#define TOK_FACE_TO_POINT 125

View File

@ -42,6 +42,7 @@ Description
*/
%include
{
#include "exprScanToken.H"
#include "patchExprDriver.H"
#include "patchExprParser.H"
#include "patchExprScanner.H"
@ -77,11 +78,8 @@ tmp_management()
%token_prefix TOK_
// Terminals
%token_type {Foam::expressions::patchExpr::scanToken*}
// Non-terminals
%type ivalue { Foam::label }
%type svalue { Foam::scalar }
%type ident { Foam::word* }
%token_type {Foam::expressions::scanToken}
%token_destructor { ($$).destroy(); }
// Face fields
declare_field(lfield, Foam::boolField, bool, newField, getSurfaceField)
@ -104,17 +102,33 @@ declare_field(ptfield, Foam::tensorField, Foam::tensor, newPointField, getPointF
// Lemon does not generate a destructor for that.
// So do not use Lemon destructors for anything.
standard_tokens()
operator_precedence()
%start_symbol evaluate
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*\
* General Productions
\*---------------------------------------------------------------------------*/
%type identifier { Foam::word* }
%destructor identifier { delete($$); $$ = nullptr; }
identifier (lhs) ::= IDENTIFIER (tok) .
{
// Take ownership of pointer from scan token
lhs = tok.name_; tok.name_ = nullptr;
}
/*---------------------------------------------------------------------------*\
* Productions (scalar)
\*---------------------------------------------------------------------------*/
svalue (lhs) ::= NUMBER (a) . { lhs = (a)->svalue; } // From scanToken
%type svalue { Foam::scalar }
svalue (lhs) ::= NUMBER (tok) . { lhs = (tok).scalarValue; } // scanToken
svalue (lhs) ::= ZERO . { lhs = Foam::Zero; }
svalue (lhs) ::= PI LPAREN RPAREN . { lhs = Foam::constant::mathematical::pi; }
svalue (lhs) ::= DEG_TO_RAD LPAREN RPAREN . { lhs = Foam::degToRad(); }
@ -123,6 +137,38 @@ svalue (lhs) ::= ARG LPAREN RPAREN . { lhs = driver->argValue(); }
svalue (lhs) ::= TIME LPAREN RPAREN . { lhs = driver->timeValue(); }
svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
{
lhs = driver->getFunctionValue<Foam::scalar>
(
make_obj(name.name_),
driver->timeValue()
);
}
/*---------------------------------------------------------------------------*\
* Productions (vector)
\*---------------------------------------------------------------------------*/
%type vvalue { Foam::vector* }
%destructor vvalue { delete($$); $$ = nullptr; }
vvalue (lhs) ::= VECTOR_VALUE (tok) .
{
// Take ownership of pointer from scan token
lhs = tok.vectorPtr; tok.vectorPtr = nullptr;
}
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
{
auto val = driver->getFunctionValue<Foam::vector>
(
make_obj(name.name_),
driver->timeValue()
);
lhs = new Foam::vector(val);
}
/* * * * * * * * * * * * * * * * * Face Fields * * * * * * * * * * * * * * * *\
dnl
@ -138,7 +184,9 @@ dnl
/*---------------------------------------------------------------------------*\
* Productions (scalarField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [sfield])dnl
define([_new_target_], [_new_sfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -156,9 +204,9 @@ rules_scalar_operations()
rules_scalar_functions()
// Non-standard but manage via FieldOps::assign
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<_value_type_>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<_value_type_>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<_value_type_>())
// Non-standard but works directly for scalarField
rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
@ -174,20 +222,34 @@ _target_ (lhs) ::= RAND LPAREN RPAREN.
_target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN.
{
// Call with -ve seed to signal use of time index as seed
lhs = driver->field_rand(std::round(-(seed)->svalue)).ptr();
lhs = driver->field_rand(std::round(-(seed).scalarValue)).ptr();
}
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (vectorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [vfield])dnl
define([_new_target_], [_new_vfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, vvalue)
rule_get_field(_target_, VECTOR_ID)
rule_get_field(_target_, SVECTOR_ID)
rule_get_patchfields(_target_, _value_type_, VECTOR_ID)
@ -197,11 +259,26 @@ rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
// Other functions
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (sphericalTensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [hfield])dnl
define([_new_target_], [_new_hfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -221,7 +298,9 @@ rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (symmTensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [yfield])dnl
define([_new_target_], [_new_yfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -241,7 +320,9 @@ rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (tensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [tfield])dnl
define([_new_target_], [_new_tfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -303,7 +384,9 @@ dnl
/*---------------------------------------------------------------------------*\
* Productions (point scalarField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [psfield])dnl
define([_new_target_], [_new_psfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -319,24 +402,38 @@ rules_scalar_operations()
rules_scalar_functions()
// Non-standard but manage via FieldOps::assign
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<_value_type_>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<_value_type_>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<_value_type_>())
// Non-standard but works directly for scalarField
rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (point vectorField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [pvfield])dnl
define([_new_target_], [_new_pvfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
rule_field_from_value(_target_, vvalue, POINT_EXPR)
rule_get_field(_target_, PVECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
@ -344,10 +441,22 @@ rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (point sphericalTensorField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [phfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
@ -366,6 +475,7 @@ rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (point symmTensorField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [pyfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
@ -384,6 +494,7 @@ rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (point tensorField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [ptfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
@ -544,13 +655,15 @@ void Foam::expressions::patchExpr::parser::start(parseDriver& driver_)
}
void Foam::expressions::patchExpr::parser::parse
(
int tokenId,
scanToken* tokenVal
)
void Foam::expressions::patchExpr::parser::parse(int tokenId)
{
Parse(lemon_, tokenId, tokenVal);
Parse(lemon_, tokenId, scanToken::null());
}
void Foam::expressions::patchExpr::parser::parse(int tokenId, scanToken tok)
{
Parse(lemon_, tokenId, tok);
}

View File

@ -59,6 +59,23 @@ rule_driver_unary_named($1, SN_GRAD, $3, patchNormalField, $2)dnl
define([rules_driver_surface_functions],
[dnl
_logic_ (lhs) ::= CELL_SET LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_cellSet(make_obj(name)).ptr();
}dnl
_logic_ (lhs) ::= CELL_ZONE LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_cellZone(make_obj(name)).ptr();
}dnl
_logic_ (lhs) ::= FACE_SET LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_faceSet(make_obj(name)).ptr();
}dnl
_logic_ (lhs) ::= FACE_ZONE LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_faceZone(make_obj(name)).ptr();
}dnl
dnl
rule_driver_nullary(_scalar_, FACE_AREA, field_faceArea)dnl
rule_driver_nullary(_vector_, POS, field_faceCentre)dnl FACE_CENTRE
rule_driver_nullary(_vector_, FACE_EXPR, field_areaNormal)dnl

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,6 +34,7 @@ Description
#ifndef expressions_patchExprParser_H
#define expressions_patchExprParser_H
#include "exprScanToken.H"
#include "patchExprFwd.H"
namespace Foam
@ -97,8 +98,11 @@ public:
//- Stop parsing, freeing the allocated parser
void stop();
//- Push token/value to parser
void parse(int tokenId, scanToken* tokenVal);
//- Push token type to parser with default token
void parse(int tokenId);
//- Push token type/value to parser
void parse(int tokenId, scanToken tok);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,8 +37,8 @@ Note
#ifndef expressions_patchExprScanner_H
#define expressions_patchExprScanner_H
#include "exprScanToken.H"
#include "patchExprFwd.H"
#include "scalar.H"
namespace Foam
{
@ -47,21 +47,6 @@ namespace expressions
namespace patchExpr
{
/*---------------------------------------------------------------------------*\
Class scanToken Declaration
\*---------------------------------------------------------------------------*/
union scanToken
{
Foam::label ivalue;
Foam::scalar svalue;
Foam::word* name;
//- Default construct, bit-wise zero for union content
scanToken() : ivalue(0) {}
};
/*---------------------------------------------------------------------------*\
Class scanner Declaration
\*---------------------------------------------------------------------------*/
@ -83,16 +68,14 @@ class scanner
bool dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident // Receives a copy
) const;
//- Dispatch identifier to parser (if possible) or Fatal
bool dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident // Receives a copy
) const;

File diff suppressed because it is too large Load Diff

View File

@ -28,6 +28,7 @@ Description
\*---------------------------------------------------------------------------*/
#include "exprScanToken.H"
#include "patchExprScanner.H"
#include "patchExprDriver.H"
#include "patchExprLemonParser.h"
@ -42,7 +43,6 @@ Description
#undef DebugInfo
#define DebugInfo if (debug & 0x2) InfoErr
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
@ -55,9 +55,20 @@ namespace Foam
#define TOKEN_PAIR(Name,T) { TOKEN_OF(T), Name }
//- An {int, c_str} enum pairing for field types
#define FIELD_PAIR(Fld,T) { TOKEN_OF(T), Fld::typeName.c_str() }
#define FIELD_PAIR(Fld,T) { TOKEN_OF(T), Fld::typeName.c_str() }
#define HAS_LOOKBEHIND_TOKENS
// Special handling for these known (stashed) look-back types
static const Enum<int> lookBehindTokenEnums
({
TOKEN_PAIR("cellZone", CELL_ZONE), TOKEN_PAIR("cellSet", CELL_SET),
TOKEN_PAIR("faceZone", FACE_ZONE), TOKEN_PAIR("faceSet", FACE_SET),
#ifdef TOK_POINT_ZONE
TOKEN_PAIR("pointZone", POINT_ZONE), TOKEN_PAIR("pointSet", POINT_SET),
#endif
});
#undef HAS_LOOKBEHIND_TOKENS
// Special handling of predefined method types. Eg, .x(), .y(), ...
static const Enum<int> fieldMethodEnums
@ -176,7 +187,7 @@ static int driverTokenType
const word& ident
)
{
#if 0
#ifdef HAS_LOOKBEHIND_TOKENS
// Get stashed "look-behind" to decide what type of identifier we expect
const int lookBehind = driver_.resetStashedTokenId();
@ -186,12 +197,17 @@ static int driverTokenType
switch (lookBehind)
{
case TOK_CELL_SET : good = driver_.isCellSet(ident); break;
case TOK_FACE_SET : good = driver_.isFaceSet(ident); break;
case TOK_POINT_SET : good = driver_.isPointSet(ident); break;
case TOK_CELL_ZONE : good = driver_.isCellZone(ident); break;
case TOK_CELL_SET : good = driver_.isCellSet(ident); break;
case TOK_FACE_ZONE : good = driver_.isFaceZone(ident); break;
case TOK_FACE_SET : good = driver_.isFaceSet(ident); break;
#ifdef TOK_POINT_ZONE
// Not yet ready or particularly useful it seems
case TOK_POINT_ZONE : good = driver_.isPointZone(ident); break;
case TOK_POINT_SET : good = driver_.isPointSet(ident); break;
#endif
}
if (good)
@ -207,51 +223,49 @@ static int driverTokenType
return -2; // Extra safety
}
#endif
#endif
// Face variables
#ifdef TOK_SSCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(TokType, Type) \
if (driver_.isVariable<Type>(ident, false)) \
{ \
return TokType; \
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isVariable<Type>(ident, false)) \
{ \
return TokType; \
}
checkFieldToken(TOK_SSCALAR_ID, scalar);
checkFieldToken(TOK_SVECTOR_ID, vector);
checkFieldToken(TOK_SSYM_TENSOR_ID, symmTensor);
checkFieldToken(TOK_SSPH_TENSOR_ID, sphericalTensor);
checkFieldToken(TOK_STENSOR_ID, tensor);
// Not tested: checkFieldToken(TOK_SBOOL_ID, bool);
doLocalCode(TOK_SSCALAR_ID, scalar);
doLocalCode(TOK_SVECTOR_ID, vector);
doLocalCode(TOK_SSYM_TENSOR_ID, symmTensor);
doLocalCode(TOK_SSPH_TENSOR_ID, sphericalTensor);
doLocalCode(TOK_STENSOR_ID, tensor);
// Untested: doLocalCode(TOK_SBOOL_ID, bool);
#undef doLocalCode
}
#endif
// Point variables
#ifdef TOK_PSCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(TokType, Type) \
if (driver_.isVariable<Type>(ident, true)) \
{ \
return TokType; \
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isVariable<Type>(ident, true)) \
{ \
return TokType; \
}
checkFieldToken(TOK_PSCALAR_ID, scalar);
checkFieldToken(TOK_PVECTOR_ID, vector);
checkFieldToken(TOK_PTENSOR_ID, tensor);
checkFieldToken(TOK_PTENSOR_ID, tensor);
checkFieldToken(TOK_PSYM_TENSOR_ID, symmTensor);
checkFieldToken(TOK_PSPH_TENSOR_ID, sphericalTensor);
// Not tested: checkFieldToken(TOK_PBOOL_ID, bool);
doLocalCode(TOK_PSCALAR_ID, scalar);
doLocalCode(TOK_PVECTOR_ID, vector);
doLocalCode(TOK_PTENSOR_ID, tensor);
doLocalCode(TOK_PTENSOR_ID, tensor);
doLocalCode(TOK_PSYM_TENSOR_ID, symmTensor);
doLocalCode(TOK_PSPH_TENSOR_ID, sphericalTensor);
// Untested: doLocalCode(TOK_SBOOL_ID, bool);
#undef doLocalCode
}
#endif
#undef checkFieldToken
// Check registered fields and/or disk-files
{
const word fieldType(driver_.getFieldClassName(ident));
@ -267,7 +281,7 @@ static int driverTokenType
return -1;
}
} // End anonymous namespace
} // End namespace Foam
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@ -280,7 +294,15 @@ static int driverTokenType
#define EMIT_TOKEN(T) \
driver_.parsePosition() = (ts-buf); \
DebugInfo<< STRINGIFY(T) << " at " << driver_.parsePosition() << nl; \
parser_->parse(TOKEN_OF(T), nullptr); \
parser_->parse(TOKEN_OF(T)); \
driver_.parsePosition() = (p-buf);
#define EMIT_VECTOR_TOKEN(X, Y, Z) \
driver_.parsePosition() = (ts-buf); \
DebugInfo<< "VECTOR at " << driver_.parsePosition() << nl; \
scanToken scanTok; \
scanTok.setVector(X,Y,Z); \
parser_->parse(TOK_VECTOR_VALUE, scanTok); \
driver_.parsePosition() = (p-buf);
@ -289,15 +311,18 @@ static int driverTokenType
write data;
action emit_number {
// Emit number
driver_.parsePosition() = (ts-buf);
DebugInfo
<< "Number:" << std::string(ts, te-ts).c_str()
<< " at " << driver_.parsePosition() << nl;
if (readScalar(std::string(ts, te-ts), scanTok.svalue))
scanToken scanTok;
scanTok.setScalar(0);
if (readScalar(std::string(ts, te-ts), scanTok.scalarValue))
{
parser_->parse(TOKEN_OF(NUMBER), &scanTok);
parser_->parse(TOKEN_OF(NUMBER), scanTok);
}
else
{
@ -311,33 +336,38 @@ static int driverTokenType
}
action emit_ident {
// Emit identifier
driver_.parsePosition() = (ts-buf);
dispatch_ident(driver_, scanTok, word(ts, te-ts, false));
dispatch_ident(driver_, word(ts, te-ts, false));
driver_.parsePosition() = (p-buf);
}
action emit_method {
// Tokenized ".method" - dispatch '.' and "method" separately
driver_.parsePosition() = (ts-buf);
dispatch_method(driver_, scanTok, word(ts+1, te-ts-1, false));
dispatch_method(driver_, word(ts+1, te-ts-1, false));
driver_.parsePosition() = (p-buf);
}
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ;
ident = ((alpha|'_') . ((alnum|[._])**)) ;
identifier = ((alpha|'_') . ((alnum|[._])**)) ;
dquoted = '"' [^\"]+ '"' ;
squoted = "'" [^\']+ "'" ;
## Allow 'fn:' prefix for function identifier
ident = ('fn:')? identifier ;
## ===========
## The scanner
## ===========
main := |*
space*;
number => emit_number;
## Operators
'!' =>{ EMIT_TOKEN(NOT); };
'!' =>{ EMIT_TOKEN(LNOT); };
'%' =>{ EMIT_TOKEN(PERCENT); };
'(' =>{ EMIT_TOKEN(LPAREN); };
')' =>{ EMIT_TOKEN(RPAREN); };
@ -358,7 +388,7 @@ static int driverTokenType
'&&' =>{ EMIT_TOKEN(LAND); };
'||' =>{ EMIT_TOKEN(LOR); };
'&' =>{ EMIT_TOKEN(BIT_AND); };
## Not needed? '|' =>{ EMIT_TOKEN(BIT_OK); };
## Not needed? '|' =>{ EMIT_TOKEN(BIT_OR); };
'^' =>{ EMIT_TOKEN(BIT_XOR); };
## Some '.method' - Error if unknown
@ -417,9 +447,12 @@ static int driverTokenType
"sphericalTensor" =>{ EMIT_TOKEN(SPH_TENSOR); };
## Single value (constants, etc)
"Zero" =>{ EMIT_TOKEN(ZERO); };
"true" =>{ EMIT_TOKEN(LTRUE); };
"false" =>{ EMIT_TOKEN(LFALSE); };
"Zero" =>{ EMIT_TOKEN(ZERO); };
"vector::x" =>{ EMIT_VECTOR_TOKEN(1,0,0); };
"vector::y" =>{ EMIT_VECTOR_TOKEN(0,1,0); };
"vector::z" =>{ EMIT_VECTOR_TOKEN(0,0,1); };
"tensor::I" =>{ EMIT_TOKEN(IDENTITY_TENSOR); };
"arg" =>{ EMIT_TOKEN(ARG); };
"time" =>{ EMIT_TOKEN(TIME); };
@ -452,8 +485,7 @@ Foam::expressions::patchExpr::scanner::~scanner()
bool Foam::expressions::patchExpr::scanner::dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident
) const
{
if (ident[0] == '.')
@ -470,8 +502,8 @@ bool Foam::expressions::patchExpr::scanner::dispatch_method
if (methType > 0)
{
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
parser_->parse(TOK_DOT);
parser_->parse(methType);
return true;
}
@ -484,10 +516,11 @@ bool Foam::expressions::patchExpr::scanner::dispatch_method
bool Foam::expressions::patchExpr::scanner::dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident
) const
{
// Peek at stashed "look-behind". It may influence decisions
int lookBehindTok = driver_.stashedTokenId();
int tokType = -1;
const bool quoted =
@ -512,12 +545,12 @@ bool Foam::expressions::patchExpr::scanner::dispatch_ident
<< "Emit:" << ident << " function:"
<< parser_->tokenName(tokType) << nl;
parser_->parse(tokType, nullptr);
parser_->parse(tokType);
return true;
}
#ifdef HAS_LOOKBEHIND_TOKENS
// Specials such "cset" also reset the look-behind
// Specials such "cellSet" etc also reset the look-behind
tokType = lookBehindTokenEnums.lookup(ident, -1);
if (tokType > 0)
@ -527,17 +560,44 @@ bool Foam::expressions::patchExpr::scanner::dispatch_ident
<< parser_->tokenName(tokType) << nl;
driver_.resetStashedTokenId(tokType);
parser_->parse(tokType, nullptr);
parser_->parse(tokType);
return true;
}
#endif
}
// Functions: scalar, vector, probably don't need others
// - "fn:" prefix to avoid any ambiguities
if (lookBehindTok <= 0 && ident.starts_with("fn:"))
{
word funcName(ident.substr(3)); // strip prefix
// Can also peek at stashed "look-behind"
// const int lookBehind = driver_.stashedTokenId();
do
{
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isFunction<Type>(funcName)) \
{ \
ident = std::move(funcName); \
tokType = TokType; \
break; \
}
tokType = driverTokenType(driver_, ident);
#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);
}
if (tokType <= 0)
{
tokType = driverTokenType(driver_, ident);
}
if (tokType > 0)
{
@ -545,8 +605,9 @@ bool Foam::expressions::patchExpr::scanner::dispatch_ident
<< "Emit:" << ident << " token:"
<< parser_->tokenName(tokType) << nl;
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
scanToken scanTok;
scanTok.setWord(ident);
parser_->parse(tokType, scanTok);
return true;
}
@ -578,12 +639,13 @@ bool Foam::expressions::patchExpr::scanner::dispatch_ident
// The field (before the ".")
ident.erase(dot);
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
scanToken scanTok;
scanTok.setWord(ident);
parser_->parse(tokType, scanTok);
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
parser_->parse(TOK_DOT);
parser_->parse(methType);
return true;
}
@ -646,9 +708,6 @@ bool Foam::expressions::patchExpr::scanner::process
parser_->start(driver_);
// Scan token type
scanToken scanTok;
// Token start/end (Ragel naming)
const char* ts;
const char* te;
@ -678,7 +737,7 @@ bool Foam::expressions::patchExpr::scanner::process
}
// Terminate parser execution
parser_->parse(0, nullptr);
parser_->parse(0);
parser_->stop();
if (debug & 0x6)

View File

@ -45,13 +45,13 @@ Foam::expressions::volumeExpr::parseDriver::field_cellSelection
dimensionedScalar(Zero)
);
labelList selected;
refPtr<labelList> tselected;
switch (setType)
{
case topoSetSource::sourceType::CELLZONE_SOURCE:
case topoSetSource::sourceType::CELLSET_SOURCE:
{
selected = getTopoSetLabels(name, setType);
tselected = getTopoSetLabels(name, setType);
break;
}
@ -63,6 +63,7 @@ Foam::expressions::volumeExpr::parseDriver::field_cellSelection
break;
}
}
const auto& selected = tselected();
auto& fld = tresult.ref().primitiveFieldRef();
UIndirectList<scalar>(fld, selected) = scalar(1);
@ -85,13 +86,13 @@ Foam::expressions::volumeExpr::parseDriver::field_faceSelection
dimensionedScalar(Zero)
);
labelList selected;
refPtr<labelList> tselected;
switch (setType)
{
case topoSetSource::sourceType::FACESET_SOURCE:
case topoSetSource::sourceType::FACEZONE_SOURCE:
{
selected = getTopoSetLabels(name, setType);
tselected = getTopoSetLabels(name, setType);
break;
}
@ -103,6 +104,7 @@ Foam::expressions::volumeExpr::parseDriver::field_faceSelection
break;
}
}
const auto& selected = tselected();
const auto& bmesh = mesh().boundaryMesh();
@ -160,13 +162,13 @@ Foam::expressions::volumeExpr::parseDriver::field_pointSelection
dimensionedScalar(Zero)
);
labelList selected;
refPtr<labelList> tselected;
switch (setType)
{
case topoSetSource::sourceType::POINTSET_SOURCE:
case topoSetSource::sourceType::POINTZONE_SOURCE:
{
selected = getTopoSetLabels(name, setType);
tselected = getTopoSetLabels(name, setType);
break;
}
@ -178,6 +180,7 @@ Foam::expressions::volumeExpr::parseDriver::field_pointSelection
break;
}
}
const auto& selected = tselected();
auto& fld = tresult.ref().primitiveFieldRef();
UIndirectList<scalar>(fld, selected) = scalar(1);

View File

@ -47,7 +47,6 @@ namespace volumeExpr
class parser;
class scanner;
class parseDriver;
union scanToken;
//- Static debugging option
extern int debug;

View File

@ -1,121 +1,126 @@
#define TOK_QUESTION 1
#define TOK_COLON 2
#define TOK_LOR 3
#define TOK_LAND 4
#define TOK_BIT_XOR 5
#define TOK_BIT_AND 6
#define TOK_EQUAL 7
#define TOK_NOT_EQUAL 8
#define TOK_LESS_EQ 9
#define TOK_GREATER_EQ 10
#define TOK_LESS 11
#define TOK_GREATER 12
#define TOK_PLUS 13
#define TOK_MINUS 14
#define TOK_TIMES 15
#define TOK_DIVIDE 16
#define TOK_PERCENT 17
#define TOK_NEGATE 18
#define TOK_NOT 19
#define TOK_DOT 20
#define TOK_NUMBER 21
#define TOK_ZERO 22
#define TOK_PI 23
#define TOK_LPAREN 24
#define TOK_RPAREN 25
#define TOK_DEG_TO_RAD 26
#define TOK_RAD_TO_DEG 27
#define TOK_ARG 28
#define TOK_TIME 29
#define TOK_DELTA_T 30
#define TOK_SCALAR_ID 31
#define TOK_MIN 32
#define TOK_COMMA 33
#define TOK_MAX 34
#define TOK_SUM 35
#define TOK_AVERAGE 36
#define TOK_EXP 37
#define TOK_LOG 38
#define TOK_LOG10 39
#define TOK_SQR 40
#define TOK_SQRT 41
#define TOK_CBRT 42
#define TOK_SIN 43
#define TOK_COS 44
#define TOK_TAN 45
#define TOK_ASIN 46
#define TOK_ACOS 47
#define TOK_ATAN 48
#define TOK_SINH 49
#define TOK_COSH 50
#define TOK_TANH 51
#define TOK_POW 52
#define TOK_ATAN2 53
#define TOK_POS 54
#define TOK_NEG 55
#define TOK_POS0 56
#define TOK_NEG0 57
#define TOK_SIGN 58
#define TOK_FLOOR 59
#define TOK_CEIL 60
#define TOK_ROUND 61
#define TOK_HYPOT 62
#define TOK_RAND 63
#define TOK_VECTOR_ID 64
#define TOK_SPH_TENSOR_ID 65
#define TOK_SYM_TENSOR_ID 66
#define TOK_IDENTITY_TENSOR 67
#define TOK_TENSOR_ID 68
#define TOK_LTRUE 69
#define TOK_LFALSE 70
#define TOK_BOOL 71
#define TOK_CELL_SET 72
#define TOK_IDENTIFIER 73
#define TOK_CELL_ZONE 74
#define TOK_CELL_VOLUME 75
#define TOK_WEIGHT_AVERAGE 76
#define TOK_WEIGHT_SUM 77
#define TOK_FACE_EXPR 78
#define TOK_SSCALAR_ID 79
#define TOK_SVECTOR_ID 80
#define TOK_SSPH_TENSOR_ID 81
#define TOK_SSYM_TENSOR_ID 82
#define TOK_STENSOR_ID 83
#define TOK_FACE_SET 84
#define TOK_FACE_ZONE 85
#define TOK_FACE_AREA 86
#define TOK_FACE_CENTRE 87
#define TOK_POINT_EXPR 88
#define TOK_PSCALAR_ID 89
#define TOK_PVECTOR_ID 90
#define TOK_PSPH_TENSOR_ID 91
#define TOK_PSYM_TENSOR_ID 92
#define TOK_PTENSOR_ID 93
#define TOK_POINT_SET 94
#define TOK_POINT_ZONE 95
#define TOK_POINTS 96
#define TOK_MAG 97
#define TOK_MAGSQR 98
#define TOK_VECTOR 99
#define TOK_TENSOR 100
#define TOK_SYM_TENSOR 101
#define TOK_SPH_TENSOR 102
#define TOK_CMPT_X 103
#define TOK_CMPT_Y 104
#define TOK_CMPT_Z 105
#define TOK_CMPT_XX 106
#define TOK_CMPT_XY 107
#define TOK_CMPT_XZ 108
#define TOK_CMPT_YX 109
#define TOK_CMPT_YY 110
#define TOK_CMPT_YZ 111
#define TOK_CMPT_ZX 112
#define TOK_CMPT_ZY 113
#define TOK_CMPT_ZZ 114
#define TOK_CMPT_II 115
#define TOK_TRANSPOSE 116
#define TOK_DIAG 117
#define TOK_POINT_TO_CELL 118
#define TOK_RECONSTRUCT 119
#define TOK_CELL_TO_FACE 120
#define TOK_CELL_TO_POINT 121
#define TOK_LPAREN 1
#define TOK_RPAREN 2
#define TOK_COMMA 3
#define TOK_QUESTION 4
#define TOK_COLON 5
#define TOK_LOR 6
#define TOK_LAND 7
#define TOK_LNOT 8
#define TOK_BIT_OR 9
#define TOK_BIT_XOR 10
#define TOK_BIT_AND 11
#define TOK_BIT_NOT 12
#define TOK_EQUAL 13
#define TOK_NOT_EQUAL 14
#define TOK_LESS 15
#define TOK_LESS_EQ 16
#define TOK_GREATER 17
#define TOK_GREATER_EQ 18
#define TOK_PLUS 19
#define TOK_MINUS 20
#define TOK_TIMES 21
#define TOK_DIVIDE 22
#define TOK_PERCENT 23
#define TOK_NEGATE 24
#define TOK_DOT 25
#define TOK_BOOL 26
#define TOK_LTRUE 27
#define TOK_LFALSE 28
#define TOK_NUMBER 29
#define TOK_ZERO 30
#define TOK_IDENTIFIER 31
#define TOK_PI 32
#define TOK_DEG_TO_RAD 33
#define TOK_RAD_TO_DEG 34
#define TOK_ARG 35
#define TOK_TIME 36
#define TOK_DELTA_T 37
#define TOK_SCALAR_FUNCTION_ID 38
#define TOK_VECTOR_VALUE 39
#define TOK_VECTOR_FUNCTION_ID 40
#define TOK_SCALAR_ID 41
#define TOK_MIN 42
#define TOK_MAX 43
#define TOK_SUM 44
#define TOK_AVERAGE 45
#define TOK_EXP 46
#define TOK_LOG 47
#define TOK_LOG10 48
#define TOK_SQR 49
#define TOK_SQRT 50
#define TOK_CBRT 51
#define TOK_SIN 52
#define TOK_COS 53
#define TOK_TAN 54
#define TOK_ASIN 55
#define TOK_ACOS 56
#define TOK_ATAN 57
#define TOK_SINH 58
#define TOK_COSH 59
#define TOK_TANH 60
#define TOK_POW 61
#define TOK_ATAN2 62
#define TOK_POS 63
#define TOK_NEG 64
#define TOK_POS0 65
#define TOK_NEG0 66
#define TOK_SIGN 67
#define TOK_FLOOR 68
#define TOK_CEIL 69
#define TOK_ROUND 70
#define TOK_HYPOT 71
#define TOK_RAND 72
#define TOK_VECTOR_ID 73
#define TOK_SPH_TENSOR_ID 74
#define TOK_SYM_TENSOR_ID 75
#define TOK_IDENTITY_TENSOR 76
#define TOK_TENSOR_ID 77
#define TOK_CELL_SET 78
#define TOK_CELL_ZONE 79
#define TOK_CELL_VOLUME 80
#define TOK_WEIGHT_AVERAGE 81
#define TOK_WEIGHT_SUM 82
#define TOK_FACE_EXPR 83
#define TOK_SSCALAR_ID 84
#define TOK_SVECTOR_ID 85
#define TOK_SSPH_TENSOR_ID 86
#define TOK_SSYM_TENSOR_ID 87
#define TOK_STENSOR_ID 88
#define TOK_FACE_SET 89
#define TOK_FACE_ZONE 90
#define TOK_FACE_AREA 91
#define TOK_FACE_CENTRE 92
#define TOK_POINT_EXPR 93
#define TOK_PSCALAR_ID 94
#define TOK_PVECTOR_ID 95
#define TOK_PSPH_TENSOR_ID 96
#define TOK_PSYM_TENSOR_ID 97
#define TOK_PTENSOR_ID 98
#define TOK_POINT_SET 99
#define TOK_POINT_ZONE 100
#define TOK_POINTS 101
#define TOK_MAG 102
#define TOK_MAGSQR 103
#define TOK_VECTOR 104
#define TOK_TENSOR 105
#define TOK_SYM_TENSOR 106
#define TOK_SPH_TENSOR 107
#define TOK_CMPT_X 108
#define TOK_CMPT_Y 109
#define TOK_CMPT_Z 110
#define TOK_CMPT_XX 111
#define TOK_CMPT_XY 112
#define TOK_CMPT_XZ 113
#define TOK_CMPT_YX 114
#define TOK_CMPT_YY 115
#define TOK_CMPT_YZ 116
#define TOK_CMPT_ZX 117
#define TOK_CMPT_ZY 118
#define TOK_CMPT_ZZ 119
#define TOK_CMPT_II 120
#define TOK_TRANSPOSE 121
#define TOK_DIAG 122
#define TOK_POINT_TO_CELL 123
#define TOK_RECONSTRUCT 124
#define TOK_CELL_TO_FACE 125
#define TOK_CELL_TO_POINT 126

View File

@ -42,6 +42,7 @@ Description
*/
%include
{
#include "exprScanToken.H"
#include "volumeExprDriver.H"
#include "volumeExprParser.H"
#include "volumeExprScanner.H"
@ -110,11 +111,8 @@ dnl
%token_prefix TOK_
// Terminals
%token_type {Foam::expressions::volumeExpr::scanToken*}
// Non-terminals
%type ivalue { Foam::label }
%type svalue { Foam::scalar }
%type ident { Foam::word* }
%token_type {Foam::expressions::scanToken}
%token_destructor { ($$).destroy(); }
// Volume fields
declare_field(lfield, Foam::volScalarField, Foam::scalar, newVolField, getVolField)
@ -144,17 +142,34 @@ declare_field(ptfield, Foam::pointTensorField, Foam::tensor, newPointField, getP
// Lemon does not generate a destructor for that.
// So do not use Lemon destructors for anything.
standard_tokens()
operator_precedence()
%start_symbol evaluate
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*\
* General Productions
\*---------------------------------------------------------------------------*/
%type identifier { Foam::word* }
%destructor identifier { delete($$); $$ = nullptr; }
identifier (lhs) ::= IDENTIFIER (tok) .
{
// Take ownership of pointer from scan token
lhs = tok.name_; tok.name_ = nullptr;
}
/*---------------------------------------------------------------------------*\
* Productions (scalar)
\*---------------------------------------------------------------------------*/
svalue (lhs) ::= NUMBER (a) . { lhs = (a)->svalue; } // From scanToken
%type svalue { Foam::scalar }
svalue (lhs) ::= NUMBER (tok) . { lhs = (tok).scalarValue; } // scanToken
svalue (lhs) ::= ZERO . { lhs = Foam::Zero; }
svalue (lhs) ::= PI LPAREN RPAREN . { lhs = Foam::constant::mathematical::pi; }
svalue (lhs) ::= DEG_TO_RAD LPAREN RPAREN . { lhs = Foam::degToRad(); }
@ -163,6 +178,39 @@ svalue (lhs) ::= ARG LPAREN RPAREN . { lhs = driver->argValue(); }
svalue (lhs) ::= TIME LPAREN RPAREN . { lhs = driver->timeValue(); }
svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
{
lhs = driver->getFunctionValue<Foam::scalar>
(
make_obj(name.name_),
driver->timeValue()
);
}
/*---------------------------------------------------------------------------*\
* Productions (vector)
\*---------------------------------------------------------------------------*/
%type vvalue { Foam::vector* }
%destructor vvalue { delete($$); $$ = nullptr; }
vvalue (lhs) ::= VECTOR_VALUE (tok) .
{
// Take ownership of pointer from scan token
lhs = tok.vectorPtr; tok.vectorPtr = nullptr;
}
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
{
auto val = driver->getFunctionValue<Foam::vector>
(
make_obj(name.name_),
driver->timeValue()
);
lhs = new Foam::vector(val);
}
/* * * * * * * * * * * * * * * * Volume Fields * * * * * * * * * * * * * * * *\
dnl
@ -178,7 +226,9 @@ dnl
/*---------------------------------------------------------------------------*\
* Productions (volScalarField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [sfield])dnl
define([_new_target_], [_new_sfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -194,12 +244,12 @@ rules_scalar_operations()
rules_scalar_functions()
// Non-standard but manage via FieldOps::assign
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<_value_type_>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<_value_type_>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<_value_type_>())
// Non-standard but manage via FieldOps::assign
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<Foam::scalar>())
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<_value_type_>())
// Other functions
@ -212,20 +262,34 @@ _target_ (lhs) ::= RAND LPAREN RPAREN .
_target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN .
{
// Call with -ve seed to signal use of time index as seed
lhs = driver->field_rand(std::round(-(seed)->svalue)).ptr();
lhs = driver->field_rand(std::round(-(seed).scalarValue)).ptr();
}
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (volVectorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [vfield])dnl
define([_new_target_], [_new_vfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, vvalue)
rule_get_field(_target_, VECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
@ -233,9 +297,24 @@ rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
// Other functions
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (volSphericalTensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [hfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
@ -253,6 +332,7 @@ rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (volSymmTensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [yfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
@ -269,6 +349,7 @@ rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (volTensorField)
dnl
define([_scalar_arg_], [sfield])dnl
define([_target_], [tfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
@ -326,7 +407,9 @@ dnl> %ifndef disable_surface_fields
/*---------------------------------------------------------------------------*\
* Productions (surfaceScalarField)
dnl
define([_scalar_arg_], [ssfield])dnl
define([_target_], [ssfield])dnl
define([_new_target_], [_new_ssfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -342,24 +425,38 @@ rules_scalar_operations()
rules_scalar_functions()
// Non-standard but manage via FieldOps::assign
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<_value_type_>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<_value_type_>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<_value_type_>())
// Non-standard but manage via FieldOps::assign
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<Foam::scalar>())
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<_value_type_>())
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (surfaceVectorField)
dnl
define([_scalar_arg_], [ssfield])dnl
define([_target_], [svfield])dnl
define([_new_target_], [_new_svfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, vvalue, FACE_EXPR)
rule_get_field(_target_, SVECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
@ -367,10 +464,22 @@ rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (surfaceSphericalTensorField)
dnl
define([_scalar_arg_], [ssfield])dnl
define([_target_], [shfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
@ -388,6 +497,7 @@ rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (surfaceSymmTensorField)
dnl
define([_scalar_arg_], [ssfield])dnl
define([_target_], [syfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
@ -406,6 +516,7 @@ rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (surfaceTensorField)
dnl
define([_scalar_arg_], [ssfield])dnl
define([_target_], [stfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
@ -470,7 +581,9 @@ dnl> %ifndef disable_point_fields
/*---------------------------------------------------------------------------*\
* Productions (pointScalarField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [psfield])dnl
define([_new_target_], [_new_psfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
@ -484,12 +597,23 @@ rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
// Non-standard but manage via FieldOps::assign
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<Foam::scalar>())
rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<_value_type_>())
rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<_value_type_>())
rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<_value_type_>())
// Non-standard but manage via FieldOps::assign
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<Foam::scalar>())
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<_value_type_>())
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
@ -542,13 +666,16 @@ dnl*/
/*---------------------------------------------------------------------------*\
* Productions (pointVectorField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [pvfield])dnl
define([_new_target_], [_new_pvfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, vvalue, POINT_EXPR)
rule_get_field(_target_, PVECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
@ -556,9 +683,21 @@ rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
{
lhs = _new_target_;
driver->fillFunctionValues<_value_type_>
(
*lhs,
make_obj(name.name_),
make_obj(values)
);
}
/*---------------------------------------------------------------------------*\
* Productions (pointSphericalTensorField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [phfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
@ -577,6 +716,7 @@ rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (pointSymmTensorField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [pyfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
@ -595,6 +735,7 @@ rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (pointTensorField)
dnl
define([_scalar_arg_], [psfield])dnl
define([_target_], [ptfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
@ -802,13 +943,15 @@ void Foam::expressions::volumeExpr::parser::start(parseDriver& driver_)
}
void Foam::expressions::volumeExpr::parser::parse
(
int tokenId,
scanToken* tokenVal
)
void Foam::expressions::volumeExpr::parser::parse(int tokenId)
{
Parse(lemon_, tokenId, tokenVal);
Parse(lemon_, tokenId, scanToken::null());
}
void Foam::expressions::volumeExpr::parser::parse(int tokenId, scanToken tok)
{
Parse(lemon_, tokenId, tok);
}

View File

@ -34,8 +34,14 @@ divert(-1)dnl
define([rules_driver_volume_functions],
[dnl
rule_driver_select(_logic_, CELL_SET, field_cellSet)dnl
rule_driver_select(_logic_, CELL_ZONE, field_cellZone)dnl
_logic_ (lhs) ::= CELL_SET LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_cellSet(make_obj(name)).ptr();dnl
}dnl
_logic_ (lhs) ::= CELL_ZONE LPAREN identifier (name) RPAREN .dnl
{
lhs = driver->field_cellZone(make_obj(name)).ptr();dnl
}dnl
dnl
rule_driver_nullary(_scalar_, CELL_VOLUME, field_cellVolume)dnl
rule_driver_nullary(_vector_, POS, field_cellCentre)dnl CELL_CENTRE
@ -56,8 +62,14 @@ dnl
define([rules_driver_surface_functions],
[dnl
rule_driver_select(_logic_, FACE_SET, field_faceSet)dnl
rule_driver_select(_logic_, FACE_ZONE, field_faceZone)dnl
_logic_ (lhs) ::= FACE_SET LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_faceSet(make_obj(name)).ptr();dnl
}dnl
_logic_ (lhs) ::= FACE_ZONE LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_faceZone(make_obj(name)).ptr();dnl
}dnl
dnl
rule_driver_nullary(_scalar_, FACE_AREA, field_faceArea)dnl
rule_driver_nullary(_vector_, FACE_CENTRE, field_faceCentre)dnl
@ -79,8 +91,14 @@ dnl
define([rules_driver_point_functions],
[dnl
rule_driver_select(_logic_, POINT_SET, field_pointSet)dnl
rule_driver_select(_logic_, POINT_ZONE, field_pointZone)dnl
_logic_ (lhs) ::= POINT_SET LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_pointSet(make_obj(*name)).ptr();dnl
}dnl
_logic_ (lhs) ::= POINT_ZONE LPAREN identifier (name) RPAREN .dnl
{dnl
lhs = driver->field_pointZone(make_obj(*name)).ptr();dnl
}dnl
dnl
rule_driver_nullary(_vector_, POINTS, field_pointField)dnl
dnl

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,6 +34,7 @@ Description
#ifndef expressions_volumeExprParser_H
#define expressions_volumeExprParser_H
#include "exprScanToken.H"
#include "volumeExprFwd.H"
namespace Foam
@ -97,8 +98,11 @@ public:
//- Stop parsing, freeing the allocated parser
void stop();
//- Push token/value to parser
void parse(int tokenId, scanToken* tokenVal);
//- Push token type to parser with default token
void parse(int tokenId);
//- Push token type/value to parser
void parse(int tokenId, scanToken tok);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,8 +37,8 @@ Note
#ifndef expressions_volumeExprScanner_H
#define expressions_volumeExprScanner_H
#include "exprScanToken.H"
#include "volumeExprFwd.H"
#include "scalar.H"
namespace Foam
{
@ -47,21 +47,6 @@ namespace expressions
namespace volumeExpr
{
/*---------------------------------------------------------------------------*\
Class scanToken Declaration
\*---------------------------------------------------------------------------*/
union scanToken
{
Foam::label ivalue;
Foam::scalar svalue;
Foam::word* name;
//- Default construct, bit-wise zero for union content
scanToken() : ivalue(0) {}
};
/*---------------------------------------------------------------------------*\
Class scanner Declaration
\*---------------------------------------------------------------------------*/
@ -83,16 +68,14 @@ class scanner
bool dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident // Receives a copy
) const;
//- Dispatch identifier to parser (if possible) or Fatal
bool dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident // Receives a copy
) const;

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,6 @@ Description
#undef DebugInfo
#define DebugInfo if (debug & 0x2) InfoErr
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
@ -55,22 +54,20 @@ namespace Foam
#define TOKEN_PAIR(Name,T) { TOKEN_OF(T), Name }
//- An {int, c_str} enum pairing for field types
#define FIELD_PAIR(Fld,T) { TOKEN_OF(T), Fld::typeName.c_str() }
#define FIELD_PAIR(Fld,T) { TOKEN_OF(T), Fld::typeName.c_str() }
// Special handling for these known (stashed) look-back types
#define HAS_LOOKBEHIND_TOKENS
static const Enum<int> lookBehindTokenEnums
({
TOKEN_PAIR("cellSet", CELL_SET),
TOKEN_PAIR("faceSet", FACE_SET),
TOKEN_PAIR("pointSet", POINT_SET),
TOKEN_PAIR("cellZone", CELL_ZONE),
TOKEN_PAIR("faceZone", FACE_ZONE),
TOKEN_PAIR("pointZone", POINT_ZONE),
TOKEN_PAIR("cellZone", CELL_ZONE), TOKEN_PAIR("cellSet", CELL_SET),
TOKEN_PAIR("faceZone", FACE_ZONE), TOKEN_PAIR("faceSet", FACE_SET),
#ifdef TOK_POINT_ZONE
TOKEN_PAIR("pointZone", POINT_ZONE), TOKEN_PAIR("pointSet", POINT_SET),
#endif
});
#define HAS_LOOKBEHIND_TOKENS
// Special handling of predefined method types. Eg, .x(), .y(), ...
static const Enum<int> fieldMethodEnums
@ -192,6 +189,7 @@ static int driverTokenType
const word& ident
)
{
#ifdef HAS_LOOKBEHIND_TOKENS
// Get stashed "look-behind" to decide what type of identifier we expect
const int lookBehind = driver_.resetStashedTokenId();
@ -201,12 +199,16 @@ static int driverTokenType
switch (lookBehind)
{
case TOK_CELL_SET : good = driver_.isCellSet(ident); break;
case TOK_FACE_SET : good = driver_.isFaceSet(ident); break;
case TOK_POINT_SET : good = driver_.isPointSet(ident); break;
case TOK_CELL_ZONE : good = driver_.isCellZone(ident); break;
case TOK_CELL_SET : good = driver_.isCellSet(ident); break;
case TOK_FACE_ZONE : good = driver_.isFaceZone(ident); break;
case TOK_FACE_SET : good = driver_.isFaceSet(ident); break;
#ifdef TOK_POINT_ZONE
case TOK_POINT_ZONE : good = driver_.isPointZone(ident); break;
case TOK_POINT_SET : good = driver_.isPointSet(ident); break;
#endif
}
if (good)
@ -222,65 +224,67 @@ static int driverTokenType
return -2; // Extra safety
}
#endif
// Surface variables - distinguish from volume by size
#ifdef TOK_SSCALAR_ID
{
const label len = driver_.mesh().nInternalFaces();
#undef checkFieldToken
#define checkFieldToken(TokType, Type) \
if (driver_.isVariable<Type>(ident, false, len)) \
{ \
return TokType; \
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isVariable<Type>(ident, false, len)) \
{ \
return TokType; \
}
checkFieldToken(TOK_SSCALAR_ID, scalar);
checkFieldToken(TOK_SVECTOR_ID, vector);
checkFieldToken(TOK_SSYM_TENSOR_ID, symmTensor);
checkFieldToken(TOK_SSPH_TENSOR_ID, sphericalTensor);
checkFieldToken(TOK_STENSOR_ID, tensor);
doLocalCode(TOK_SSCALAR_ID, scalar);
doLocalCode(TOK_SVECTOR_ID, vector);
doLocalCode(TOK_SSYM_TENSOR_ID, symmTensor);
doLocalCode(TOK_SSPH_TENSOR_ID, sphericalTensor);
doLocalCode(TOK_STENSOR_ID, tensor);
#undef doLocalCode
}
#endif
// Point variables
#ifdef TOK_PSCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(TokType, Type) \
if (driver_.isVariable<Type>(ident, true)) \
{ \
return TokType; \
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isVariable<Type>(ident, true)) \
{ \
return TokType; \
}
checkFieldToken(TOK_PSCALAR_ID, scalar);
checkFieldToken(TOK_PVECTOR_ID, vector);
checkFieldToken(TOK_PSPH_TENSOR_ID, sphericalTensor);
checkFieldToken(TOK_PSYM_TENSOR_ID, symmTensor);
checkFieldToken(TOK_PTENSOR_ID, tensor);
doLocalCode(TOK_PSCALAR_ID, scalar);
doLocalCode(TOK_PVECTOR_ID, vector);
doLocalCode(TOK_PSPH_TENSOR_ID, sphericalTensor);
doLocalCode(TOK_PSYM_TENSOR_ID, symmTensor);
doLocalCode(TOK_PTENSOR_ID, tensor);
#undef doLocalCode
}
#endif
// Volume variables
#ifdef TOK_SCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(TokType, Type) \
if (driver_.isVariable<Type>(ident, false)) \
{ \
return TokType; \
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isVariable<Type>(ident, false)) \
{ \
return TokType; \
}
checkFieldToken(TOK_SCALAR_ID, scalar);
checkFieldToken(TOK_VECTOR_ID, vector);
checkFieldToken(TOK_SPH_TENSOR_ID, sphericalTensor);
checkFieldToken(TOK_SYM_TENSOR_ID, symmTensor);
checkFieldToken(TOK_TENSOR_ID, tensor);
doLocalCode(TOK_SCALAR_ID, scalar);
doLocalCode(TOK_VECTOR_ID, vector);
doLocalCode(TOK_SPH_TENSOR_ID, sphericalTensor);
doLocalCode(TOK_SYM_TENSOR_ID, symmTensor);
doLocalCode(TOK_TENSOR_ID, tensor);
#undef doLocalCode
}
#endif
#undef checkFieldToken
// Check registered fields and/or disk-files
{
const word fieldType(driver_.getFieldClassName(ident));
@ -296,7 +300,7 @@ static int driverTokenType
return -1;
}
} // End anonymous namespace
} // End namespace Foam
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@ -309,7 +313,16 @@ static int driverTokenType
#define EMIT_TOKEN(T) \
driver_.parsePosition() = (ts-buf); \
DebugInfo<< STRINGIFY(T) << " at " << driver_.parsePosition() << nl; \
parser_->parse(TOKEN_OF(T), nullptr); \
parser_->parse(TOKEN_OF(T)); \
driver_.parsePosition() = (p-buf);
#define EMIT_VECTOR_TOKEN(X, Y, Z) \
driver_.parsePosition() = (ts-buf); \
DebugInfo<< "VECTOR at " << driver_.parsePosition() << nl; \
scanToken scanTok; \
scanTok.setVector(X,Y,Z); \
parser_->parse(TOK_VECTOR_VALUE, scanTok); \
driver_.parsePosition() = (p-buf);
@ -318,15 +331,18 @@ static int driverTokenType
write data;
action emit_number {
// Emit number
driver_.parsePosition() = (ts-buf);
DebugInfo
<< "Number:" << std::string(ts, te-ts).c_str()
<< " at " << driver_.parsePosition() << nl;
if (readScalar(std::string(ts, te-ts), scanTok.svalue))
scanToken scanTok;
scanTok.setScalar(0);
if (readScalar(std::string(ts, te-ts), scanTok.scalarValue))
{
parser_->parse(TOKEN_OF(NUMBER), &scanTok);
parser_->parse(TOKEN_OF(NUMBER), scanTok);
}
else
{
@ -340,33 +356,38 @@ static int driverTokenType
}
action emit_ident {
// Emit identifier
driver_.parsePosition() = (ts-buf);
dispatch_ident(driver_, scanTok, word(ts, te-ts, false));
dispatch_ident(driver_, word(ts, te-ts, false));
driver_.parsePosition() = (p-buf);
}
action emit_method {
// Tokenized ".method" - dispatch '.' and "method" separately
driver_.parsePosition() = (ts-buf);
dispatch_method(driver_, scanTok, word(ts+1, te-ts-1, false));
dispatch_method(driver_, word(ts+1, te-ts-1, false));
driver_.parsePosition() = (p-buf);
}
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ;
ident = ((alpha|'_') . ((alnum|[._])**)) ;
identifier = ((alpha|'_') . ((alnum|[._])**)) ;
dquoted = '"' [^\"]+ '"' ;
squoted = "'" [^\']+ "'" ;
## Allow 'fn:' prefix for function identifier
ident = ('fn:')? identifier ;
## ===========
## The scanner
## ===========
main := |*
space*;
number => emit_number;
## Operators
'!' =>{ EMIT_TOKEN(NOT); };
'!' =>{ EMIT_TOKEN(LNOT); };
'%' =>{ EMIT_TOKEN(PERCENT); };
'(' =>{ EMIT_TOKEN(LPAREN); };
')' =>{ EMIT_TOKEN(RPAREN); };
@ -387,7 +408,7 @@ static int driverTokenType
'&&' =>{ EMIT_TOKEN(LAND); };
'||' =>{ EMIT_TOKEN(LOR); };
'&' =>{ EMIT_TOKEN(BIT_AND); };
## Not needed? '|' =>{ EMIT_TOKEN(BIT_OK); };
## Not needed? '|' =>{ EMIT_TOKEN(BIT_OR); };
'^' =>{ EMIT_TOKEN(BIT_XOR); };
## Some '.method' - Error if unknown
@ -441,9 +462,12 @@ static int driverTokenType
"sphericalTensor" =>{ EMIT_TOKEN(SPH_TENSOR); };
## Single value (constants, etc)
"Zero" =>{ EMIT_TOKEN(ZERO); };
"true" =>{ EMIT_TOKEN(LTRUE); };
"false" =>{ EMIT_TOKEN(LFALSE); };
"Zero" =>{ EMIT_TOKEN(ZERO); };
"vector::x" =>{ EMIT_VECTOR_TOKEN(1,0,0); };
"vector::y" =>{ EMIT_VECTOR_TOKEN(0,1,0); };
"vector::z" =>{ EMIT_VECTOR_TOKEN(0,0,1); };
"tensor::I" =>{ EMIT_TOKEN(IDENTITY_TENSOR); };
"arg" =>{ EMIT_TOKEN(ARG); };
"time" =>{ EMIT_TOKEN(TIME); };
@ -476,8 +500,7 @@ Foam::expressions::volumeExpr::scanner::~scanner()
bool Foam::expressions::volumeExpr::scanner::dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident
) const
{
if (ident[0] == '.')
@ -494,8 +517,8 @@ bool Foam::expressions::volumeExpr::scanner::dispatch_method
if (methType > 0)
{
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
parser_->parse(TOK_DOT);
parser_->parse(methType);
return true;
}
@ -508,10 +531,11 @@ bool Foam::expressions::volumeExpr::scanner::dispatch_method
bool Foam::expressions::volumeExpr::scanner::dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
word ident
) const
{
// Peek at stashed "look-behind". It may influence decisions
int lookBehindTok = driver_.stashedTokenId();
int tokType = -1;
const bool quoted =
@ -536,12 +560,12 @@ bool Foam::expressions::volumeExpr::scanner::dispatch_ident
<< "Emit:" << ident << " function:"
<< parser_->tokenName(tokType) << nl;
parser_->parse(tokType, nullptr);
parser_->parse(tokType);
return true;
}
#ifdef HAS_LOOKBEHIND_TOKENS
// Specials such "cset" also reset the look-behind
// Specials such "cellSet" etc also reset the look-behind
tokType = lookBehindTokenEnums.lookup(ident, -1);
if (tokType > 0)
@ -551,17 +575,44 @@ bool Foam::expressions::volumeExpr::scanner::dispatch_ident
<< parser_->tokenName(tokType) << nl;
driver_.resetStashedTokenId(tokType);
parser_->parse(tokType, nullptr);
parser_->parse(tokType);
return true;
}
#endif
}
// Functions: scalar, vector, probably don't need others
// - "fn:" prefix to avoid any ambiguities
if (lookBehindTok <= 0 && ident.starts_with("fn:"))
{
word funcName(ident.substr(3)); // strip prefix
// Can also peek at stashed "look-behind"
// const int lookBehind = driver_.stashedTokenId();
do
{
#undef doLocalCode
#define doLocalCode(TokType, Type) \
if (driver_.isFunction<Type>(funcName)) \
{ \
ident = std::move(funcName); \
tokType = TokType; \
break; \
}
tokType = driverTokenType(driver_, ident);
#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);
}
if (tokType <= 0)
{
tokType = driverTokenType(driver_, ident);
}
if (tokType > 0)
{
@ -569,8 +620,9 @@ bool Foam::expressions::volumeExpr::scanner::dispatch_ident
<< "Emit:" << ident << " token:"
<< parser_->tokenName(tokType) << nl;
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
scanToken scanTok;
scanTok.setWord(ident);
parser_->parse(tokType, scanTok);
return true;
}
@ -602,12 +654,13 @@ bool Foam::expressions::volumeExpr::scanner::dispatch_ident
// The field (before the ".")
ident.erase(dot);
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
scanToken scanTok;
scanTok.setWord(ident);
parser_->parse(tokType, scanTok);
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
parser_->parse(TOK_DOT);
parser_->parse(methType);
return true;
}
@ -670,9 +723,6 @@ bool Foam::expressions::volumeExpr::scanner::process
parser_->start(driver_);
// Scan token type
scanToken scanTok;
// Token start/end (Ragel naming)
const char* ts;
const char* te;
@ -702,7 +752,7 @@ bool Foam::expressions::volumeExpr::scanner::process
}
// Terminate parser execution
parser_->parse(0, nullptr);
parser_->parse(0);
parser_->stop();
if (debug & 0x6)