mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add expression support for scalar/vector expression lookups
- similar idea to swak timelines/lookuptables but combined together
and based on Function1 for more flexibility.
Specified as 'functions<scalar>' or 'functions<vector>'.
For example,
functions<scalar>
{
intakeType table ((0 0) (10 1.2));
p_inlet
{
type sine;
frequency 3000;
scale 50;
level 101325;
}
}
These can be referenced in the expressions as a nullary function or a
unary function.
Within the parser, the names are prefixed with "fn:" (function).
It is thus possible to define "fn:sin()" that is different than
the builtin "sin()" function.
* A nullary call uses time value
- Eg, fn:p_inlet()
* A unary call acts as a remapper function.
- Eg, fn:intakeType(6.25)
This commit is contained in:
@ -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()
|
||||
#};
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -168,6 +168,7 @@ $(expr)/traits/exprTraits.C
|
||||
|
||||
$(expr)/exprDriver/exprDriver.C
|
||||
$(expr)/exprDriver/exprDriverFields.C
|
||||
$(expr)/exprDriver/exprDriverFunctions.C
|
||||
$(expr)/exprDriver/exprDriverIO.C
|
||||
|
||||
fieldExpr = $(expr)/fields
|
||||
|
||||
@ -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,8 @@ Foam::expressions::exprDriver::exprDriver
|
||||
result_(),
|
||||
variableStrings_(),
|
||||
variables_(16),
|
||||
scalarFuncs_(0),
|
||||
vectorFuncs_(0),
|
||||
arg1Value_(0),
|
||||
timeStatePtr_(nullptr),
|
||||
obrPtr_(nullptr),
|
||||
@ -162,6 +205,8 @@ Foam::expressions::exprDriver::exprDriver
|
||||
result_(rhs.result_),
|
||||
variableStrings_(rhs.variableStrings_),
|
||||
variables_(rhs.variables_),
|
||||
scalarFuncs_(0),
|
||||
vectorFuncs_(0),
|
||||
arg1Value_(rhs.arg1Value_),
|
||||
timeStatePtr_(rhs.timeStatePtr_),
|
||||
obrPtr_(rhs.obrPtr_),
|
||||
@ -174,7 +219,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 +300,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;
|
||||
|
||||
@ -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,15 @@ 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
|
||||
exprDriver.C
|
||||
exprDriverFields.C
|
||||
exprDriverFunctions.C
|
||||
exprDriverIO.C
|
||||
exprDriverTemplates.C
|
||||
|
||||
@ -65,6 +72,9 @@ SourceFiles
|
||||
#include "pointField.H"
|
||||
#include "primitiveFields.H"
|
||||
#include "objectRegistry.H"
|
||||
#include "HashTable.H"
|
||||
#include "HashSet.H"
|
||||
#include "Function1.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -105,6 +115,18 @@ private:
|
||||
//- Get search/caching controls from dictionary entries
|
||||
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 +146,14 @@ 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_;
|
||||
|
||||
//- Special-purpose scalar reference argument
|
||||
scalar arg1Value_;
|
||||
|
||||
@ -173,24 +203,8 @@ protected:
|
||||
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 +458,27 @@ public:
|
||||
);
|
||||
|
||||
|
||||
// Scalar mappings (timelines / lookups)
|
||||
|
||||
//- Named mapping with given type exists
|
||||
template<class Type>
|
||||
bool isFunction(const word& name) const;
|
||||
|
||||
//- Evaluate named mapping for the given time/value.
|
||||
//- Zero for undefined/unknown
|
||||
template<class Type>
|
||||
Type getFunctionValue(const word& name, const scalar x) const;
|
||||
|
||||
//- Fill result with values remapped according to the named Function1
|
||||
template<class Type>
|
||||
void fillFunctionValues
|
||||
(
|
||||
Field<Type>& result,
|
||||
const word& name,
|
||||
const scalarField& input
|
||||
) const;
|
||||
|
||||
|
||||
// Fields
|
||||
|
||||
//- Test existence of a local variable
|
||||
|
||||
231
src/OpenFOAM/expressions/exprDriver/exprDriverFunctions.C
Normal file
231
src/OpenFOAM/expressions/exprDriver/exprDriverFunctions.C
Normal 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_);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -46,63 +46,6 @@ Foam::expressions::exprDriver::cfindFieldObject
|
||||
}
|
||||
|
||||
|
||||
template<class TableType>
|
||||
bool Foam::expressions::exprDriver::readTable
|
||||
(
|
||||
const word& name,
|
||||
const dictionary& dict,
|
||||
HashTable<TableType>& tbl,
|
||||
bool clear
|
||||
)
|
||||
{
|
||||
if (clear)
|
||||
{
|
||||
tbl.clear();
|
||||
}
|
||||
|
||||
if (!dict.found(name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ITstream& is = dict.lookup(name);
|
||||
List<dictionary> input(is);
|
||||
|
||||
for (const dictionary& d : input)
|
||||
{
|
||||
tbl.insert(dict.get<word>("name"), TableType(d));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class TableType>
|
||||
void Foam::expressions::exprDriver::writeTable
|
||||
(
|
||||
Ostream& os,
|
||||
const word& name,
|
||||
const HashTable<TableType>& tbl
|
||||
)
|
||||
{
|
||||
if (tbl.size())
|
||||
{
|
||||
os.writeKeyword(name);
|
||||
os << token::BEGIN_LIST << nl;
|
||||
|
||||
forAllConstIters(tbl, iter)
|
||||
{
|
||||
os.beginBlock();
|
||||
os.writeEntry("name", iter.key());
|
||||
(*iter).write(os);
|
||||
os.endBlock();
|
||||
}
|
||||
os << token::END_LIST
|
||||
<< token::END_STATEMENT << nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
@ -180,6 +123,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
|
||||
(
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -173,8 +173,11 @@ svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
|
||||
|
||||
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
|
||||
{
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
lhs = 0;
|
||||
lhs = driver->getFunctionValue<Foam::scalar>
|
||||
(
|
||||
make_obj(name.name_),
|
||||
driver->timeValue()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -193,8 +196,12 @@ vvalue (lhs) ::= VECTOR_VALUE (tok) .
|
||||
|
||||
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
|
||||
{
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
lhs = new Foam::vector(0,0,0);
|
||||
auto val = driver->getFunctionValue<Foam::vector>
|
||||
(
|
||||
make_obj(name.name_),
|
||||
driver->timeValue()
|
||||
);
|
||||
lhs = new Foam::vector(val);
|
||||
}
|
||||
|
||||
|
||||
@ -253,8 +260,12 @@ _target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN.
|
||||
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -283,8 +294,12 @@ rules_vector_functions()
|
||||
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -219,12 +219,16 @@ static int driverTokenType
|
||||
|
||||
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*;
|
||||
|
||||
@ -431,6 +435,22 @@ bool Foam::expressions::fieldExpr::scanner::dispatch_ident
|
||||
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(TokType, Type) \
|
||||
if (driver_.isFunction<Type>(funcName)) \
|
||||
{ \
|
||||
ident = std::move(funcName); \
|
||||
tokType = TokType; \
|
||||
break; \
|
||||
}
|
||||
|
||||
#ifdef TOK_SCALAR_FUNCTION_ID
|
||||
doLocalCode(TOK_SCALAR_FUNCTION_ID, scalar);
|
||||
#endif
|
||||
#ifdef TOK_VECTOR_FUNCTION_ID
|
||||
doLocalCode(TOK_VECTOR_FUNCTION_ID, vector);
|
||||
#endif
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
}
|
||||
|
||||
@ -251,9 +251,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;
|
||||
}
|
||||
|
||||
@ -139,8 +139,11 @@ svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
|
||||
|
||||
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
|
||||
{
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
lhs = 0;
|
||||
lhs = driver->getFunctionValue<Foam::scalar>
|
||||
(
|
||||
make_obj(name.name_),
|
||||
driver->timeValue()
|
||||
);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
@ -158,8 +161,12 @@ vvalue (lhs) ::= VECTOR_VALUE (tok) .
|
||||
|
||||
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
|
||||
{
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
lhs = new Foam::vector(0,0,0);
|
||||
auto val = driver->getFunctionValue<Foam::vector>
|
||||
(
|
||||
make_obj(name.name_),
|
||||
driver->timeValue()
|
||||
);
|
||||
lhs = new Foam::vector(val);
|
||||
}
|
||||
|
||||
|
||||
@ -221,8 +228,12 @@ _target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN.
|
||||
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -253,8 +264,12 @@ rules_vector_functions()
|
||||
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -397,8 +412,12 @@ rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
|
||||
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -425,8 +444,12 @@ rules_vector_functions()
|
||||
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -352,12 +352,16 @@ static int driverTokenType
|
||||
|
||||
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*;
|
||||
|
||||
@ -571,6 +575,22 @@ bool Foam::expressions::patchExpr::scanner::dispatch_ident
|
||||
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(TokType, Type) \
|
||||
if (driver_.isFunction<Type>(funcName)) \
|
||||
{ \
|
||||
ident = std::move(funcName); \
|
||||
tokType = TokType; \
|
||||
break; \
|
||||
}
|
||||
|
||||
#ifdef TOK_SCALAR_FUNCTION_ID
|
||||
doLocalCode(TOK_SCALAR_FUNCTION_ID, scalar);
|
||||
#endif
|
||||
#ifdef TOK_VECTOR_FUNCTION_ID
|
||||
doLocalCode(TOK_VECTOR_FUNCTION_ID, vector);
|
||||
#endif
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
}
|
||||
|
||||
@ -180,8 +180,11 @@ svalue (lhs) ::= DELTA_T LPAREN RPAREN . { lhs = driver->deltaT(); }
|
||||
|
||||
svalue (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN RPAREN .
|
||||
{
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
lhs = 0;
|
||||
lhs = driver->getFunctionValue<Foam::scalar>
|
||||
(
|
||||
make_obj(name.name_),
|
||||
driver->timeValue()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -200,8 +203,12 @@ vvalue (lhs) ::= VECTOR_VALUE (tok) .
|
||||
|
||||
vvalue (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN RPAREN .
|
||||
{
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
lhs = new Foam::vector(0,0,0);
|
||||
auto val = driver->getFunctionValue<Foam::vector>
|
||||
(
|
||||
make_obj(name.name_),
|
||||
driver->timeValue()
|
||||
);
|
||||
lhs = new Foam::vector(val);
|
||||
}
|
||||
|
||||
|
||||
@ -261,8 +268,12 @@ _target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN .
|
||||
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -291,8 +302,12 @@ rules_vector_functions()
|
||||
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -420,8 +435,12 @@ rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<_value_typ
|
||||
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -448,8 +467,12 @@ rules_vector_functions()
|
||||
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -584,8 +607,12 @@ rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<_value_typ
|
||||
_target_ (lhs) ::= SCALAR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -659,8 +686,12 @@ rules_vector_functions()
|
||||
_target_ (lhs) ::= VECTOR_FUNCTION_ID (name) LPAREN _scalar_arg_ (values) RPAREN.
|
||||
{
|
||||
lhs = _new_target_;
|
||||
(void) make_obj(values);
|
||||
driver->reportFatal("Not implemented: " + make_obj(name.name_));
|
||||
driver->fillFunctionValues<_value_type_>
|
||||
(
|
||||
*lhs,
|
||||
make_obj(name.name_),
|
||||
make_obj(values)
|
||||
);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -371,12 +371,16 @@ static int driverTokenType
|
||||
|
||||
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*;
|
||||
|
||||
@ -585,6 +589,22 @@ bool Foam::expressions::volumeExpr::scanner::dispatch_ident
|
||||
|
||||
do
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(TokType, Type) \
|
||||
if (driver_.isFunction<Type>(funcName)) \
|
||||
{ \
|
||||
ident = std::move(funcName); \
|
||||
tokType = TokType; \
|
||||
break; \
|
||||
}
|
||||
|
||||
#ifdef TOK_SCALAR_FUNCTION_ID
|
||||
doLocalCode(TOK_SCALAR_FUNCTION_ID, scalar);
|
||||
#endif
|
||||
#ifdef TOK_VECTOR_FUNCTION_ID
|
||||
doLocalCode(TOK_VECTOR_FUNCTION_ID, vector);
|
||||
#endif
|
||||
#undef doLocalCode
|
||||
}
|
||||
while (false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user