Merge branch 'feature-expressions' into 'develop'

Feature expressions

### Summary

This branch represents an implementation of what is considered to be the most useful aspects of swak4Foam ([Swiss-Army-Knife for FOAM](https://openfoamwiki.net/index.php/Contrib/swak4Foam)) from Bernhard Gschaider, namely the ability to use text-based expressions instead of coding in C++ for the following cases:
- expression-based boundary conditions (also known as _groovy_ boundary conditions)
- expression-based setFields (also known as _funky_ set fields)

The idea of what we currently term *expressions* was pioneered by
(Bernhard Gschaider) and is now firmly established in `swak4Foam`.
Among other things, expressions attempt to bridge the gap between
using standard, predefined boundary conditions and writing dedicated,
special-purpose ones. Although part of this gap is now covered within
OpenFOAM by using dynamically compiled user coding (eg, coded boundary
conditions), there remains substantial areas where it can be
significantly more convenient to have a series of predefined functions
and expression sytax with some access to base OpenFOAM field
functionality that enables rapid deployment of boundary conditions, or
custom-defined `setFields` without writing code.
A significant portion of `swak4Foam` expressions has been adapted for
direct integration into OpenFOAM. During the integration and rewrite,
we have tried to pare things down to a smaller subset with the aim of
covering 90% or more of the common cases. The remaining cases are left
to be reassessed for extending the *expressions* functionality in the
future, but they also may be better served with other approaches (eg,
with coded conditions) that were not available when `swak4Foam` was
originally conceived.

To the greatest extent possible, the integrated *expressions* have
been designed to avoid name clashes with `swak` so it should remain
possible to use the most recent versions of `swak` without problem.


### Risks

- New functionality, so low chance of regression.
- The scope of the functionality will be revised in the future

### Naming (for `swak4Foam` users)

The following are the *expressions* correspondences to `swak`:

- The `exprFixedValue` and `exprGradient` boundary conditions are
  roughly equivalent to the _groovy_ boundary conditions.

- The utilities `setExprFields` and `setExprBoundaryFields` are
  roughly equivalent to the _funky_ utilities of similar name.

The naming of the boundary conditions and utilities not only reflects
the slightly different input requirements, but simultaneously seeks to
avoid any potential name-clash with `swak4Foam` in a mixed
environment.

The names for the boundary condition dictionary entries tend be
shorter and slightly different (eg, `valueExpr` vs `valueExpression`)
to serve as a small reminder that the *expressions* syntax is slightly
different than the *groovy* equivalents. It also allows the user to
fashion dictionary entries that are sufficient for **both** boundary
condition variants and quickly toggle between them simply by changing
the boundary condition `type`.

See merge request Development/openfoam!300
This commit is contained in:
Andrew Heather
2019-12-10 12:10:26 +00:00
82 changed files with 21171 additions and 0 deletions

View File

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

View File

@ -0,0 +1,8 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lmeshTools \
-lgenericPatchFields

View File

@ -0,0 +1,262 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Application
setExprFields
Group
grpPreProcessingUtilities
Description
Set boundary values using an expression
Note
Based on funkySetBoundaryFields
Copyright 2006-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "fvMesh.H"
#include "pointMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "surfaceFields.H"
#include "pointFields.H"
#include "patchExprDriver.H"
#include "timeSelector.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noFunctionObjects(true);
// No -constant, no special treatment for 0/
timeSelector::addOptions(false);
argList::addOption
(
"dict",
"file",
"Alternative dictionary for setExprBoundaryFieldsDict"
);
argList::addBoolOption
(
"cache-fields",
"Cache fields between calls",
true // Advanced
);
argList::addBoolOption
(
"backup",
"Preserve sub-entry as .backup",
true // Advanced
);
argList::addBoolOption
(
"dry-run",
"Evaluate but do not write"
);
#include "addRegionOption.H"
#include "setRootCase.H"
const bool dryrun = args.found("dry-run");
const bool backup = args.found("backup");
const bool cacheFields = args.found("cache-fields");
if (cacheFields)
{
Warning
<< "The current cache-fields behaviour (caching disk reads) "
<< "may lead to unexpected behaviour as previous modifications "
<< "will not be visible."
<< endl;
}
const word dictName("setExprBoundaryFieldsDict");
#include "createTime.H"
instantList times = timeSelector::select0(runTime, args);
if (times.size() < 1)
{
FatalErrorInFunction
<< "No times selected." << exit(FatalError);
}
#include "createNamedMesh.H"
#include "setSystemMeshDictionaryIO.H"
IOdictionary setExprDict(dictIO);
forAll(times, timei)
{
runTime.setTime(times[timei], timei);
Info<< "\nTime = " << runTime.timeName() << endl;
mesh.readUpdate();
for (const entry& dEntry : setExprDict)
{
if (!dEntry.isDict())
{
Info<< "Ignoring non-dictionary entry "
<< dEntry.keyword() << nl;
continue;
}
const dictionary& dict = dEntry.dict();
const word fieldName(dict.get<word>("field"));
List<dictionary> exprDicts;
dict.readEntry("expressions", exprDicts);
if (exprDicts.empty())
{
Info<< "No expressions for " << fieldName << nl;
continue;
}
// Read dictionary
// Note: disable class type checking so we can load field
const word oldTypeName = IOdictionary::typeName;
const_cast<word&>(IOdictionary::typeName) = word::null;
IOobject fieldHeader
(
fieldName,
mesh.thisDb().time().timeName(),
mesh.thisDb(),
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE,
false
);
const bool headOk = fieldHeader.typeHeaderOk<IOdictionary>(false);
if (!headOk)
{
// Restore type
const_cast<word&>(IOdictionary::typeName) = oldTypeName;
WarningInFunction
<< "Requested field to change " << fieldName
<< " does not exist in " << fieldHeader.path() << endl;
continue;
}
IOdictionary fieldDict(fieldHeader);
// Restore type
const_cast<word&>(IOdictionary::typeName) = oldTypeName;
// Fake type back to what was in field
const_cast<word&>(fieldDict.type()) = fieldDict.headerClassName();
Info<< "Processing field " << fieldName << nl;
dictionary& boundaryFieldDict = fieldDict.subDict("boundaryField");
for (const dictionary& currDict : exprDicts)
{
const word targetName = currDict.get<word>("target");
const word patchName = currDict.get<word>("patch");
dictionary& patchDict = boundaryFieldDict.subDict(patchName);
expressions::exprString expr
(
currDict.get<string>("expression"),
currDict,
true // strip comments
);
Info<< "Set boundaryField/" << patchName << '/'
<< targetName << nl
<< "with expression" << nl
<< "<<<<" << nl
<< expr.c_str() << nl
<< ">>>>" << nl;
expressions::patchExprDriver driver(currDict, mesh);
// Search on disc
driver.setSearchBehaviour(cacheFields, false, true);
driver.clearVariables();
driver.parse(expr);
// Serializing via Field::writeEntry etc
OStringStream serialize;
driver.result().writeEntry("", serialize);
if (backup && !dryrun)
{
patchDict.changeKeyword
(
targetName,
word(targetName + ".backup"),
true // Overwrite
);
}
patchDict.set(targetName, serialize.str().c_str());
if (dryrun)
{
Info<< "Evaluated:" << nl
<< "<<<<" << nl
<< serialize.str().c_str() // (already includes nl)
<< ">>>>" << nl;
}
}
if (!dryrun)
{
Info<< "Write " << fieldDict.filePath() << nl;
fieldDict.regIOobject::write();
}
}
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,34 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object setExprBoundaryFieldsDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
pattern
{
field T;
expressions
(
{
patch bottom;
target theta0;
expression #{ (pos().x() < 1e-4 ? 60 : 120) #};
}
);
keepPatches true;
}
// ************************************************************************* //

View File

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

View File

@ -0,0 +1,8 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lmeshTools \
-lgenericPatchFields

View File

@ -0,0 +1,915 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Application
setExprFields
Group
grpPreProcessingUtilities
Description
Set values on a selected set of cells/patch-faces via a dictionary.
Note
Based on funkySetFields
Copyright 2006-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "Time.H"
#include "fvMesh.H"
#include "pointMesh.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "surfaceFields.H"
#include "pointFields.H"
#include "exprOps.H"
#include "volumeExprDriver.H"
#include "timeSelector.H"
#include "dlLibraryTable.H"
using namespace Foam;
using FieldAssociation = expressions::volumeExpr::FieldAssociation;
word fieldGeoType(const FieldAssociation geoType)
{
switch (geoType)
{
case FieldAssociation::VOLUME_DATA : return "cells"; break;
case FieldAssociation::SURFACE_DATA : return "faces"; break;
case FieldAssociation::POINT_DATA : return "points"; break;
default: break;
}
return "unknown";
}
//- Simple control structure to with collected switches to simplify passing
struct setExprFieldsControl
{
bool dryRun;
bool debugParsing;
bool cacheVariables;
bool useDimension;
bool createNew;
bool keepPatches;
bool correctPatches;
bool correctBCs;
};
template<class Type>
void doCorrectBoundaryConditions
(
bool correctBCs,
GeometricField<Type, fvPatchField, volMesh>& field
)
{
if (correctBCs)
{
Info<< "Correcting boundary conditions: " << field.name() << nl;
field.correctBoundaryConditions();
}
}
template<class Type>
void doCorrectBoundaryConditions
(
bool correctBCs,
GeometricField<Type, pointPatchField, pointMesh>& field
)
{
if (correctBCs)
{
Info<< "Correcting boundary conditions: " << field.name() << nl;
field.correctBoundaryConditions();
}
}
template<class Type>
void doCorrectBoundaryConditions
(
bool correctBCs,
GeometricField<Type, fvsPatchField, surfaceMesh>& field
)
{}
template<class GeoField, class Mesh>
void setField
(
const word& fieldName,
const Mesh& mesh,
const GeoField& result,
const scalarField& cond,
const dimensionSet& dims,
const wordList& valuePatches,
const setExprFieldsControl& ctrl
)
{
Info<< "setField(" << fieldName << "): "
<< pTraits<GeoField>::typeName << endl;
tmp<GeoField> toutput;
if (ctrl.createNew)
{
// Create with zero
toutput = GeoField::New
(
fieldName,
mesh,
dimensioned<typename GeoField::value_type>(dims)
);
}
else
{
// Read
toutput = tmp<GeoField>::New
(
IOobject
(
fieldName,
mesh.thisDb().time().timeName(),
mesh.thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false // No register
),
mesh
);
}
auto& output = toutput.ref();
label setCells = 0;
if (cond.empty())
{
// No condition
output = result;
setCells = output.size();
}
else
{
forAll(output, celli)
{
if (expressions::boolOp<scalar>()(cond[celli]))
{
output[celli] = result[celli];
++setCells;
}
}
}
const label totalCells = returnReduce(output.size(), plusOp<label>());
reduce(setCells, plusOp<label>());
forAll(result.boundaryField(), patchi)
{
auto& pf = output.boundaryFieldRef()[patchi];
if (pf.patch().coupled())
{
pf == result.boundaryField()[patchi];
}
}
if (setCells == totalCells)
{
Info<< "Set all ";
}
else
{
Info<< "Set " << setCells << " of ";
}
Info<< totalCells << " cells" << endl;
doCorrectBoundaryConditions(ctrl.correctBCs, output);
if (ctrl.useDimension)
{
Info<< "Setting dimension to " << dims << endl;
output.dimensions().reset(dims);
}
if (ctrl.dryRun)
{
Info<< "(dry-run): Writing to " << output.name() << nl;
}
else
{
Info<< "Writing to " << output.name() << nl;
output.write();
}
}
void evaluate
(
const fvMesh& mesh,
const word& fieldName,
const expressions::exprString& expression,
const expressions::exprString& condition,
const dictionary& dict,
const dimensionSet& dims,
const wordList& valuePatches,
const setExprFieldsControl& ctrl
)
{
word oldFieldType;
if (ctrl.createNew)
{
Info<< "Set new field: " << fieldName;
}
else
{
IOobject io
(
fieldName,
mesh.thisDb().time().timeName(),
mesh.thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE
);
io.typeHeaderOk<IOobject>(false);
oldFieldType = io.headerClassName();
if (oldFieldType == IOobject::typeName)
{
FatalErrorInFunction
<< "Field " << fieldName << " is "
<< oldFieldType
<< ". Seems that it does not exist. Use 'create'"
<< nl
<< exit(FatalError);
}
Info<< "Modify field: " << fieldName
<< " (type " << oldFieldType << ')';
}
Info<< " time=" << mesh.thisDb().time().timeName() << nl
<< "Expression:" << nl
<< ">>>>" << nl
<< expression.c_str() << nl
<< "<<<<" << nl
<< "Condition:" << nl
<< ">>>>" << nl
<< condition.c_str() << nl
<< "<<<<" << nl;
if (ctrl.keepPatches)
{
Info<< "Keeping patches unaltered" << endl;
}
else if (!valuePatches.empty())
{
Info<< "Setting patches " << flatOutput(valuePatches)
<< " to fixed value" << endl;
}
Info<< endl;
expressions::volumeExprDriver driver
(
mesh,
ctrl.cacheVariables
);
driver.readDict(dict);
if (ctrl.debugParsing)
{
Info<< "Parsing expression: " << expression << "\nand condition "
<< condition << nl << endl;
driver.setDebugging(true, true);
}
driver.clearVariables();
scalarField conditionField;
bool evaluatedCondition = false;
FieldAssociation conditionDataType(FieldAssociation::VOLUME_DATA);
if (condition.size() && condition != "true")
{
if (ctrl.debugParsing)
{
Info<< "Parsing condition:" << condition << endl;
}
driver.parse(condition);
if (ctrl.debugParsing)
{
Info<< "Parsed condition" << endl;
}
// Process any/all scalar fields. May help with diagnosis
bool goodCond = true;
while (goodCond)
{
// volScalarField
{
const auto* ptr = driver.isResultType<volScalarField>();
if (ptr)
{
conditionField = ptr->internalField();
break;
}
}
// surfaceScalarField
{
const auto* ptr = driver.isResultType<surfaceScalarField>();
if (ptr)
{
conditionField = ptr->internalField();
conditionDataType = FieldAssociation::SURFACE_DATA;
break;
}
}
// pointScalarField
{
const auto* ptr = driver.isResultType<pointScalarField>();
if (ptr)
{
conditionField = ptr->internalField();
conditionDataType = FieldAssociation::POINT_DATA;
break;
}
}
// No matching field types
goodCond = false;
}
// Verify that it also logical
goodCond = goodCond && driver.isLogical();
if (!goodCond)
{
FatalErrorInFunction
<< " condition: " << condition
<< " does not evaluate to a logical expression: "
<< driver.resultType() << nl
#ifdef FULLDEBUG
<< "contents: " << conditionField
#endif
<< exit(FatalError);
}
if (ctrl.debugParsing)
{
Info<< "Condition evaluates to "
<< conditionField << nl;
}
evaluatedCondition = true;
}
if (ctrl.debugParsing)
{
Info<< "Parsing expression:" << expression << endl;
}
driver.parse(expression);
if (ctrl.debugParsing)
{
Info<< "Parsed expression" << endl;
}
if (evaluatedCondition)
{
if (conditionDataType != driver.fieldAssociation())
{
FatalErrorInFunction
<< "Mismatch between condition geometric type ("
<< fieldGeoType(conditionDataType) << ") and" << nl
<< "expression geometric type ("
<< fieldGeoType(driver.fieldAssociation()) << ')' << nl
<< nl
<< "Expression: " << expression << nl
<< "Condition: " << condition << nl
<< nl
<< exit(FatalError);
}
}
if (!ctrl.createNew && driver.resultType() != oldFieldType)
{
FatalErrorInFunction
<< "Inconsistent types: " << fieldName << " is "
<< oldFieldType
<< " but the expression evaluates to "
<< driver.resultType()
<< exit(FatalError);
}
Info<< "Dispatch ... " << driver.resultType() << nl;
#undef setFieldDispatch
#define setFieldDispatch(FieldType) \
{ \
/* FieldType */ \
const auto* ptr = driver.isResultType<FieldType>(); \
if (ptr) \
{ \
/* driver.getResult<FieldType>(correctPatches), */ \
\
setField \
( \
fieldName, \
mesh, \
*ptr, \
conditionField, \
dims, \
valuePatches, \
ctrl \
); \
return; \
} \
} \
setFieldDispatch(volScalarField);
setFieldDispatch(volVectorField);
setFieldDispatch(volTensorField);
setFieldDispatch(volSymmTensorField);
setFieldDispatch(volSphericalTensorField);
setFieldDispatch(surfaceScalarField);
setFieldDispatch(surfaceVectorField);
setFieldDispatch(surfaceTensorField);
setFieldDispatch(surfaceSymmTensorField);
setFieldDispatch(surfaceSphericalTensorField);
#undef setFieldDispatch
#define setFieldDispatch(FieldType) \
{ \
/* FieldType */ \
const auto* ptr = driver.isResultType<FieldType>(); \
\
if (ptr) \
{ \
/* driver.getResult<FieldType>(correctPatches), */ \
\
setField \
( \
fieldName, \
pointMesh::New(mesh), \
*ptr, \
conditionField, \
dims, \
valuePatches, \
ctrl \
); \
return; \
} \
} \
setFieldDispatch(pointScalarField);
setFieldDispatch(pointVectorField);
setFieldDispatch(pointTensorField);
setFieldDispatch(pointSymmTensorField);
setFieldDispatch(pointSphericalTensorField);
#undef setFieldDispatch
// Nothing dispatched?
FatalErrorInFunction
<< "Expression evaluates to an unsupported type: "
<< driver.resultType() << nl << nl
<< "Expression " << expression << nl << endl
<< exit(FatalError);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
argList::noFunctionObjects(true);
// No -constant, no special treatment for 0/
timeSelector::addOptions(false);
argList::addOption
(
"dict",
"file",
"Alternative dictionary for setExprFieldsDict"
);
argList::addBoolOption
(
"dry-run",
"Evaluate but do not write"
);
argList::addBoolOption
(
"verbose",
"Additional verbosity",
true // Advanced option
);
argList::addOption
(
"field",
"name",
"The field to overwrite command-line operation)",
true // Advanced option
);
argList::addOption
(
"expression",
"expr",
"The expression to evaluate (command-line operation)",
true // Advanced option
);
argList::addOption
(
"condition",
"logic",
"The logical condition when to apply the expression"
" (command-line operation)",
true // Advanced option
);
argList::addOption
(
"dimension",
"dims",
"The dimensions to apply for created fields"
" (command-line operation)",
true // Advanced option
);
argList::addBoolOption
(
"debug-parser",
"Additional debugging information",
true // Advanced option
);
argList::addBoolOption
(
"no-variable-cache",
"Disable caching of expression variables",
true // Advanced option
);
argList::addBoolOption
(
"create",
"Create a new field (command-line operation)",
true // Advanced option
);
argList::addBoolOption
(
"keepPatches",
"Leave patches unaltered"
" (command-line operation)",
true // Advanced option
);
argList::addOption
(
"value-patches",
"(patches)",
"A list of patches that receive a fixed value"
" (command-line operation)",
true // Advanced option
);
argList::addBoolOption
(
"dummy-phi",
"(command-line operation)",
true // Advanced option
);
// Future?
#if 0
argList::addBoolOption
(
"noCorrectPatches",
""
);
argList::addBoolOption
(
"correctResultBoundaryFields",
"",
true
);
#endif
#include "addRegionOption.H"
#include "setRootCase.H"
#include "createTime.H"
const bool dryrun = args.found("dry-run");
const bool verbose = args.found("verbose");
const word dictName("setExprFieldsDict");
instantList times = timeSelector::select0(runTime, args);
if (times.size() < 1)
{
FatalErrorInFunction
<< "No times selected." << exit(FatalError);
}
// Disable dimension checking during operation
dimensionSet::debug = false;
#include "createNamedMesh.H"
autoPtr<surfaceScalarField> dummyPhi;
autoPtr<IOdictionary> exprDictPtr;
// Sort out conflicts
const bool useCommandArgs = args.found("field");
if (useCommandArgs)
{
if (args.found("dict"))
{
FatalErrorInFunction
<< "Cannot specify both dictionary and command-line arguments"
<< nl
<< endl;
}
if (args.found("create") && args.found("keepPatches"))
{
FatalErrorInFunction
<< "Cannot specify both 'create' and 'keepPatches'" << nl
<< endl;
}
}
else
{
// Carp about inapplicable options
wordHashSet badOptions
({
"create", "keepPatches", "valuePatches",
"dimension", "condition", "expression"
});
badOptions.retain(args.options());
if (!badOptions.empty())
{
FatalErrorInFunction
<< "Using a dictionary. Cannot specify command options:" << nl
<< nl
<< flatOutput(badOptions.sortedToc()) << nl
<< endl;
}
#include "setSystemMeshDictionaryIO.H"
exprDictPtr.reset(new IOdictionary(dictIO));
}
forAll(times, timei)
{
runTime.setTime(times[timei], timei);
Info<< "\nTime = " << runTime.timeName() << endl;
mesh.readUpdate();
if (args.found("dummy-phi") && !dummyPhi.valid())
{
Info<< "Adding a dummy phi" << endl;
dummyPhi.reset
(
new surfaceScalarField
(
IOobject
(
"phi",
mesh.thisDb().time().constant(),
mesh.thisDb(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh,
dimensionedScalar(Zero)
)
);
}
if (args.found("withFunctionObjects"))
{
runTime.functionObjects().start();
}
if (args.found("field"))
{
const word fieldName(args.get<word>("field"));
Info<< "Using command-line options for "
<< fieldName << nl << endl;
setExprFieldsControl ctrl;
ctrl.dryRun = dryrun;
ctrl.debugParsing = args.found("debug-parser");
ctrl.cacheVariables = !args.found("no-variable-caching");
ctrl.createNew = args.found("create");
ctrl.keepPatches = args.found("keepPatches");
ctrl.correctPatches = !args.found("noCorrectPatches");
ctrl.correctBCs = args.found("correctResultBoundaryFields");
ctrl.useDimension = args.found("dimension");
expressions::exprString
expression
(
args.opt("expression"),
dictionary::null
);
expressions::exprString condition;
if (args.found("condition"))
{
args.readIfPresent("condition", condition);
}
dimensionSet dims;
if (ctrl.useDimension)
{
ITstream is(args.lookup("dimension"));
is >> dims;
}
evaluate
(
mesh,
fieldName,
expression,
condition,
dictionary::null,
dims,
args.getList<word>("valuePatches", false),
ctrl
);
}
else if (exprDictPtr.valid())
{
const dictionary& exprDict = exprDictPtr();
// Read set construct info from dictionary
PtrList<entry> actions(exprDict.lookup("expressions"));
for (const entry& dEntry : actions)
{
if (!dEntry.isDict())
{
Info<< "Ignore non-dictionary entry: "
<< dEntry.keyword() << nl;
continue;
}
const dictionary& dict = dEntry.dict();
setExprFieldsControl ctrl;
ctrl.dryRun = dryrun;
ctrl.debugParsing = args.found("debug-parser");
ctrl.cacheVariables = !args.found("no-variable-caching");
ctrl.createNew = dict.getOrDefault("create", false);
ctrl.keepPatches = dict.getOrDefault("keepPatches", false);
ctrl.correctPatches = !args.found("noCorrectPatches");
ctrl.correctBCs = args.found("correctResultBoundaryFields");
if (ctrl.createNew && ctrl.keepPatches)
{
FatalIOErrorInFunction(dict)
<< "Cannot specify both 'create' and 'keepPatches'"
<< nl << endl
<< exit(FatalIOError);
}
// Local override
dict.readIfPresent
(
"correctResultBoundaryFields",
ctrl.correctBCs
);
const word fieldName(dict.get<word>("field"));
expressions::exprString expression
(
dict.get<string>("expression"),
dict
);
expressions::exprString condition;
if (dict.found("condition"))
{
condition =
expressions::exprString
(
dict.get<string>("condition"),
dict
);
}
ctrl.useDimension = dict.found("dimension");
dimensionSet dims;
if (ctrl.useDimension)
{
dict.lookup("dimension") >> dims;
}
wordList valuePatches;
dict.readIfPresent("valuePatches", valuePatches);
if (verbose && !timei)
{
// Report once
Info<< "Processing" << dict << nl;
}
evaluate
(
mesh,
fieldName,
expression,
condition,
dict,
dims,
valuePatches,
ctrl
);
}
}
else if (exprDictPtr.valid())
{
FatalErrorInFunction
<< "No command-line or dictionary??" << nl << endl
<< exit(FatalError);
}
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object setExprFieldsDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
expressions
(
T
{
field T;
dimensions [0 0 0 1 0 0 0];
constants
{
centre (0.21 0 0.01);
}
variables
(
"radius = 0.1"
);
condition
#{
// Within the radius
(mag(pos() - $[(vector)constants.centre]) < radius)
// but only +ve y!
&& pos((pos() - $[(vector)constants.centre]).y()) > 0
#};
expression
#{
300
+ 200 * (1 - mag(pos() - $[(vector)constants.centre]) / radius)
#};
}
);
// ************************************************************************* //

View File

@ -250,6 +250,35 @@ $(constraintFvsPatchFields)/wedge/wedgeFvsPatchFields.C
fields/volFields/volFields.C
fields/surfaceFields/surfaceFields.C
expr = expressions
$(expr)/base/exprDriverWriter.C
$(expr)/base/fvExprDriver.C
$(expr)/base/fvExprDriverFields.C
$(expr)/base/fvExprDriverIO.C
$(expr)/base/fvExprDriverNew.C
patchExpr = $(expr)/patch
$(patchExpr)/patchExpr.C
$(patchExpr)/patchExprDriver.C
$(patchExpr)/patchExprDriverFields.C
$(patchExpr)/patchExprLemonParser.lyy-m4
$(patchExpr)/patchExprScanner.cc
volumeExpr = $(expr)/volume
$(volumeExpr)/volumeExpr.C
$(volumeExpr)/volumeExprDriver.C
$(volumeExpr)/volumeExprDriverFields.C
$(volumeExpr)/volumeExprLemonParser.lyy-m4
$(volumeExpr)/volumeExprScanner.cc
fieldExpr = $(expr)/fields
$(fieldExpr)/base/patchExprFieldBase.C
$(fieldExpr)/fvPatchFields/exprFixedValueFvPatchFields.C
$(fieldExpr)/fvPatchFields/exprMixedFvPatchFields.C
$(fieldExpr)/pointPatchFields/exprValuePointPatchFields.C
fvMatrices/fvMatrices.C
fvMatrices/fvScalarMatrix/fvScalarMatrix.C
fvMatrices/solvers/MULES/MULES.C

View File

@ -0,0 +1,100 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
Copyright (C) 2019 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 "exprDriverWriter.H"
#include "fvExprDriver.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
defineTypeName(exprDriverWriter);
} // namespace expressions
} // namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::expressions::exprDriverWriter::exprDriverWriter
(
const word& name,
fvExprDriver& driver
)
:
regIOobject
(
IOobject
(
name,
driver.mesh().time().timeName(),
"expressions",
driver.mesh().time(),
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
)
),
driver_(driver)
{
if (headerOk())
{
readData(readStream("exprDriverWriter", true));
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::expressions::exprDriverWriter::readData(Istream& is)
{
dictionary dict(is);
// driver_.readDict(is);
driver_.getData(dict);
return !is.bad();
}
bool Foam::expressions::exprDriverWriter::writeData(Ostream& os) const
{
// driver_.writeDict(os);
dictionary dict;
driver_.prepareData(dict);
dict.write(os, false);
return os.good();
}
// ************************************************************************* //

View File

@ -0,0 +1,109 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
Copyright (C) 2019 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::exprDriverWriter
Description
Registered input/output for an expressions::fvExprDriver
SourceFiles
exprDriverWriter.C
\*---------------------------------------------------------------------------*/
#ifndef expressions_exprDriverWriter_H
#define expressions_exprDriverWriter_H
#include "fvExprDriver.H"
#include "regIOobject.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
/*---------------------------------------------------------------------------*\
Class exprDriverWriter Declaration
\*---------------------------------------------------------------------------*/
class exprDriverWriter
:
public regIOobject
{
// Private Data
//- The driver to read/write
fvExprDriver& driver_;
// Private Member Functions
//- No null constructor
exprDriverWriter() = delete;
//- No copy construct
exprDriverWriter(const exprDriverWriter&) = delete;
//- No copy assignment
void operator=(const exprDriverWriter&) = delete;
public:
//- Runtime type information
TypeNameNoDebug("exprDriverWriter");
// Constructors
//- Construct for named driver
exprDriverWriter(const word& name, fvExprDriver& driver);
//- Destructor
virtual ~exprDriverWriter() = default;
// Member Functions
virtual bool readData(Istream& is);
virtual bool writeData(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,765 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
Copyright (C) 2019 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 "fvExprDriver.H"
#include "exprDriverWriter.H"
#include "expressionEntry.H"
#include "exprResultGlobals.H"
#include "cellSet.H"
#include "faceSet.H"
#include "pointSet.H"
#include "stringOps.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
defineTypeNameAndDebug(fvExprDriver, 0);
defineRunTimeSelectionTable(fvExprDriver, dictionary);
defineRunTimeSelectionTable(fvExprDriver, idName);
} // End namespace expressions
} // End namespace Foam
// Currently not working?
bool Foam::expressions::fvExprDriver::cacheSets_ = true;
const Foam::fvMesh* Foam::expressions::fvExprDriver::defaultMeshPtr_ = nullptr;
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
const Foam::fvMesh& Foam::expressions::fvExprDriver::defaultMesh()
{
if (!defaultMeshPtr_)
{
FatalErrorInFunction
<< "No default mesh set" << nl
<< "Try the 'fvExprDriverFunctionObject' as a workaround"
<< endl
<< abort(FatalError);
}
return *defaultMeshPtr_;
}
const Foam::fvMesh* Foam::expressions::fvExprDriver::resetDefaultMesh
(
const fvMesh& mesh,
const bool force
)
{
const fvMesh* ptr = defaultMeshPtr_;
if (force || (ptr != nullptr))
{
defaultMeshPtr_ = &mesh;
}
return ptr;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::expressions::fvExprDriver::fvExprDriver
(
bool cacheReadFields,
bool searchInMemory,
bool searchFiles,
const dictionary& dict
)
:
expressions::exprDriver
(
cacheReadFields,
searchInMemory,
searchFiles,
dict
),
globalScopes_(),
delayedVariables_(),
storedVariables_(),
specialVariablesIndex_(-1),
otherMeshName_(),
libs_(),
writer_(nullptr)
{}
Foam::expressions::fvExprDriver::fvExprDriver
(
const fvExprDriver& rhs
)
:
expressions::exprDriver(rhs),
globalScopes_(rhs.globalScopes_),
delayedVariables_(rhs.delayedVariables_),
storedVariables_(rhs.storedVariables_),
specialVariablesIndex_(rhs.specialVariablesIndex_),
otherMeshName_(),
libs_(),
writer_(nullptr)
{}
Foam::expressions::fvExprDriver::fvExprDriver
(
const dictionary& dict
)
:
fvExprDriver
(
dict.lookupOrDefault("cacheReadFields", false),
dict.lookupOrDefault("searchInMemory", true),
dict.lookupOrDefault("searchFiles", false),
dict
)
{
readDict(dict);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::expressions::fvExprDriver::~fvExprDriver()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::expressions::fvExprDriver::readDict
(
const dictionary& dict
)
{
expressions::exprDriver::readDict(dict);
// wordList plugins;
// if (dict.readIfPresent("functionPlugins", plugins))
// {
// for (const word& plugin : plugins)
// {
// libs_.open("libswak" + plugin + "FunctionPlugin.so");
// }
// }
dict.readIfPresent("globalScopes", globalScopes_);
const entry* eptr = nullptr;
// Special variables
if
(
// storedVariables
(eptr = dict.findEntry("storedVariables", keyType::LITERAL))
!= nullptr
)
{
ITstream& is = eptr->stream();
if (writer_.valid() && storedVariables_.size())
{
WarningInFunction
// << "Context: " << driverContext_ << nl
<< "The 'storedVariables' was already read."
<< " No update from " << is
<< endl;
}
else
{
storedVariables_ = List<exprResultStored>(is);
// Check for excess tokens
dict.checkITstream(is, "storedVariables");
}
}
if
(
// delayedVariables
(eptr = dict.findEntry("delayedVariables", keyType::LITERAL))
!= nullptr
)
{
ITstream& is = eptr->stream();
if (writer_.valid() && delayedVariables_.size())
{
WarningInFunction
// << "Context: " << driverContext_ << nl
<< "Seems like 'delayedVariables' was already read."
<< " No update from " << is
<< endl;
}
else
{
List<exprResultDelayed> inputs(is);
// Check for excess tokens
dict.checkITstream(is, "delayedVariables");
for (auto& var : inputs)
{
delayedVariables_.insert(var.name(), var);
}
}
}
return true;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::Time& Foam::expressions::fvExprDriver::runTime() const
{
return this->mesh().time();
}
Foam::word Foam::expressions::fvExprDriver::timeName() const
{
return runTime().timeName();
}
Foam::scalar Foam::expressions::fvExprDriver::timeValue() const
{
return runTime().value();
}
void Foam::expressions::fvExprDriver::updateSpecialVariables(bool force)
{
const bool updated = this->update();
const label eventIndex = mesh().time().timeIndex();
const scalar eventTime = mesh().time().value();
DebugInfo
<< "fvExprDriver::updateSpecialVariables(force="
<< force << ") Updated: " << updated << endl;
if (specialVariablesIndex_ < 0)
{
DebugInfo
<< "First update: " << eventIndex << endl;
specialVariablesIndex_ = eventIndex;
for (exprResultStored& v : storedVariables_)
{
DebugInfo
<< v.name() << " = " << v.initialValueExpression()
<< " (has value "
<< v.hasValue() << ")" << endl;
if (!v.hasValue())
{
DebugInfo
<< "First value: " << v.initialValueExpression()
<< " -> " << v.name() << endl;
parse(v.initialValueExpression());
v = result_;
DebugInfo
<< "Parser size: " << this->size() << nl
<< "Calculated: " << result_ << nl
<< "Stored: " << v << nl;
}
}
}
if (force || specialVariablesIndex_ != eventIndex)
{
DebugInfo
<< "Store variables: " << force << ' '
<< specialVariablesIndex_ << ' '
<< eventIndex << endl;
for (exprResultStored& v : storedVariables_)
{
if (variables_.found(v.name()))
{
DebugInfo
<< "Storing variable: " << v.name() << " "
<< variables_[v.name()] << endl;
v = variables_[v.name()];
}
}
specialVariablesIndex_ = eventIndex;
}
forAllIters(delayedVariables_, iter)
{
DebugInfo
<< "Updating delayed variable " << iter().name() << endl;
if (!iter().updateReadValue(eventTime))
{
const exprString& expr = iter().startupValueExpression();
DebugInfo
<< "Evaluate: " << expr << endl;
parse(expr);
iter().setReadValue(result_);
DebugInfo
<< "Value " << iter() << nl
<< "Type " << iter().valueType() << "("
<< result_.valueType() << ")" << endl;
}
else
{
DebugInfo
<< iter().name() << " updated without problem" << endl;
}
}
}
void Foam::expressions::fvExprDriver::clearVariables()
{
DebugInfo
<< "Clearing variables" << endl;
const scalar eventTime = mesh().time().value();
(void)this->update();
updateSpecialVariables();
variables_.clear();
for (exprResultStored& v : storedVariables_)
{
variables_.insert(v.name(), v);
}
addVariables(variableStrings_, false);
forAllIters(delayedVariables_, iter)
{
iter().storeValue(eventTime);
}
}
void Foam::expressions::fvExprDriver::evaluateVariable
(
const word& varName,
const expressions::exprString& expr
)
{
const regIOobject* objPtr = mesh().findObject<regIOobject>(varName);
if (!allowShadowing_ && objPtr)
{
WarningInFunction
// << "Context: " << driverContext_ << nl
<< "Field '" << varName << "' (type " << objPtr->headerClassName()
<< ") is shadowed by a variable of the same name." << nl
<< "This may lead to trouble" << nl
<< "If this is OK set 'allowShadowing'"
<< " in the relevant parser" << nl
<< endl;
}
parse(expr);
result_.testIfSingleValue();
DebugInfo
<< "Evaluating: " << expr << " -> " << varName << endl
<< result_;
// Assign
if (delayedVariables_.found(varName))
{
// Avoid potential conflicts?
variables_.erase(varName);
DebugInfo
<< varName << " is delayed" << endl;
// Copy assignment
delayedVariables_[varName] = result_;
}
else
{
// Overwrite with a copy
variables_.set(varName, exprResult(result_));
}
}
void Foam::expressions::fvExprDriver::evaluateVariableRemote
(
string remote,
const word& varName,
const expressions::exprString& expr
)
{
DebugInfo
<< "Evaluating remote " << remote.c_str()
<< " : " << expr << " -> " << varName << endl;
word driverType("patch"); // default is patch
word identName, regionName;
const auto slashPos = remote.find('/');
if (slashPos != std::string::npos)
{
regionName = word::validate(remote.substr(slashPos+1));
remote.resize(slashPos);
}
const auto quotePos = remote.find('\'');
if (quotePos != std::string::npos)
{
driverType = word::validate(remote.substr(0, quotePos));
identName = word::validate(remote.substr(quotePos+1));
}
else
{
identName = word::validate(remote);
}
if
(
driverType == "patch"
&&
(
identName.empty()
|| identName == "volume"
|| identName == "internalField"
)
)
{
driverType = "internalField";
}
const fvMesh* pRegion = &(this->mesh());
if (!regionName.empty())
{
pRegion = pRegion->time().cfindObject<fvMesh>(regionName);
if (!pRegion)
{
FatalErrorInFunction
<< "Cannot resolve mesh region: " << regionName << nl
<< exit(FatalError);
}
}
DebugInfo
<< "Call other with ("
<< driverType << ", " << identName << ", " << regionName << ")\n";
autoPtr<fvExprDriver> otherDriver =
fvExprDriver::New(driverType, identName, *pRegion);
otherDriver->setSearchBehaviour(*this);
otherDriver->setGlobalScopes(this->globalScopes_);
otherDriver->parse(expr);
exprResult otherResult(this->getRemoteResult(*otherDriver));
// Check / re-check for uniform. Not normally needed
if (!otherResult.isUniform())
{
otherResult.testIfSingleValue();
}
DebugInfo
<< "Remote result: " << otherResult << nl;
// Assign
if (delayedVariables_.found(varName))
{
// Avoid potential conflicts?
variables_.erase(varName);
DebugInfo
<< varName << " is delayed - setting" << nl;
// Move assignment
delayedVariables_[varName] = std::move(otherResult);
}
else
{
// Overwrite with a copy
variables_.set(varName, std::move(otherResult));
}
}
const Foam::fvMesh&
Foam::expressions::fvExprDriver::regionMesh
(
const dictionary& dict,
const fvMesh& mesh,
bool readIfNecessary
)
{
word regionName;
if (!dict.readIfPresent("region", regionName))
{
DebugInFunction << "Using original mesh " << nl;
return mesh;
}
DebugInFunction << "Using mesh " << regionName << endl;
fvMesh* meshPtr = mesh.time().getObjectPtr<fvMesh>(regionName);
if (!meshPtr && readIfNecessary)
{
WarningInFunction
<< "Region " << regionName
<< " not in memory. Loading it" << endl;
meshPtr = new fvMesh
(
IOobject
(
regionName,
mesh.time().constant(),
mesh.time(),
IOobject::MUST_READ
)
);
meshPtr->polyMesh::store();
}
if (!meshPtr)
{
FatalErrorInFunction
<< "No mesh region loaded: " << regionName
<< endl;
}
return *meshPtr;
}
Foam::word Foam::expressions::fvExprDriver::getTypeOfField
(
const word& fieldName
) const
{
return getHeaderClassName(this->mesh(), fieldName);
}
Foam::word Foam::expressions::fvExprDriver::getFieldClassName
(
const word& name
) const
{
if (searchInMemory())
{
const regIOobject* ioptr = this->mesh().findObject<regIOobject>(name);
if (ioptr)
{
return ioptr->type();
}
}
if (searchFiles())
{
return getHeaderClassName(this->mesh(), name);
}
return word::null;
}
Foam::topoSetSource::sourceType
Foam::expressions::fvExprDriver::topoSetType(const word& setName) const
{
IOobject io(topoSet::findIOobject(mesh(), setName));
if (cellSet::typeName == io.headerClassName())
{
return topoSetSource::sourceType::CELLSET_SOURCE;
}
if (faceSet::typeName == io.headerClassName())
{
return topoSetSource::sourceType::FACESET_SOURCE;
}
if (pointSet::typeName == io.headerClassName())
{
return topoSetSource::sourceType::POINTSET_SOURCE;
}
return topoSetSource::sourceType::UNKNOWN_SOURCE;
}
Foam::topoSetSource::sourceType
Foam::expressions::fvExprDriver::topoZoneType(const word& setName) const
{
if (mesh().cellZones().findZoneID(setName) >= 0)
{
return topoSetSource::sourceType::CELLZONE_SOURCE;
}
if (mesh().faceZones().findZoneID(setName) >= 0)
{
return topoSetSource::sourceType::FACEZONE_SOURCE;
}
if (mesh().pointZones().findZoneID(setName) >= 0)
{
return topoSetSource::sourceType::POINTZONE_SOURCE;
}
return topoSetSource::sourceType::UNKNOWN_SOURCE;
}
Foam::topoSetSource::sourceType
Foam::expressions::fvExprDriver::topoSourceType(const word& setName) const
{
auto setType = topoZoneType(setName);
if (topoSetSource::sourceType::UNKNOWN_SOURCE == setType)
{
setType = topoSetType(setName);
}
return setType;
}
bool Foam::expressions::fvExprDriver::isCellSet(const word& setName) const
{
return
(
topoSetSource::sourceType::CELLSET_SOURCE
== topoSetType(setName)
);
}
bool Foam::expressions::fvExprDriver::isFaceSet(const word& setName) const
{
return
(
topoSetSource::sourceType::FACESET_SOURCE
== topoSetType(setName)
);
}
bool Foam::expressions::fvExprDriver::isPointSet(const word& setName) const
{
return
(
topoSetSource::sourceType::POINTSET_SOURCE
== topoSetType(setName)
);
}
bool Foam::expressions::fvExprDriver::isCellZone(const word& name) const
{
return (mesh().cellZones().findZoneID(name) >= 0);
}
bool Foam::expressions::fvExprDriver::isFaceZone(const word& name) const
{
return (mesh().faceZones().findZoneID(name) >= 0);
}
bool Foam::expressions::fvExprDriver::isPointZone(const word& name) const
{
return (mesh().pointZones().findZoneID(name) >= 0);
}
const Foam::expressions::exprResult&
Foam::expressions::fvExprDriver::lookupGlobal
(
const word& name
) const
{
return exprResultGlobals::New(this->mesh()).get(name, globalScopes_);
}
bool Foam::expressions::fvExprDriver::hasDataToWrite() const
{
return (!storedVariables_.empty() || !delayedVariables_.empty());
}
void Foam::expressions::fvExprDriver::getData
(
const dictionary& dict
)
{
dict.readIfPresent("storedVariables", storedVariables_);
}
void Foam::expressions::fvExprDriver::prepareData
(
dictionary& dict
) const
{
auto& driver = const_cast<fvExprDriver&>(*this);
(void)driver.update();
if (storedVariables_.size())
{
driver.updateSpecialVariables(true);
dict.add("storedVariables", storedVariables_);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,646 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2010-2018 Bernhard Gschaider
Copyright (C) 2019 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::fvExprDriver
Description
Base driver for parsing value expressions associated with an fvMesh.
Largely based on code and ideas from swak4foam
Properties
\table
Property | Description | Required | Default
variables | List of variables for expressions | no | ()
delayedVariables | List of delayed variables | no | ()
storedVariables | List of stored variables | no | ()
globalScopes | Scopes for global variables | no | ()
allowShadowing | Allow variables to shadow field names | no | false
\endtable
Debug Properties
\table
Property | Description | Required | Default
debugBaseDriver | Debug level (int) for base driver | no |
debugScanner | Add debug for scanner | no | false
debugParser | Add debug for parser | no | false
\endtable
SourceFiles
fvExprDriverI.H
fvExprDriver.C
fvExprDriverFields.C
fvExprDriverIO.C
fvExprDriverNew.C
fvExprDriverTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef expressions_fvExprDriver_H
#define expressions_fvExprDriver_H
#include "exprDriver.H"
#include "exprResultDelayed.H"
#include "exprResultStored.H"
#include "pointMesh.H"
#include "volFields.H"
#include "topoSetSource.H"
#include "dlLibraryTable.H"
#include "runTimeSelectionTables.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
// Forward Declarations
class exprDriverWriter;
/*---------------------------------------------------------------------------*\
Class fvExprDriver Declaration
\*---------------------------------------------------------------------------*/
class fvExprDriver
:
public expressions::exprDriver
{
// Static Data
//- Pointer to the "default" mesh
static const fvMesh *defaultMeshPtr_;
//- Cache cellSets, faceSets insted of reading from disc each time
static bool cacheSets_;
// Protected Data
// Stored Data
//- The scopes for global variables
List<word> globalScopes_;
//- The (delayed) variables table
HashTable<exprResultDelayed> delayedVariables_;
//- Stored expressions. Read from dictionary and updated as required
List<exprResultStored> storedVariables_;
//- Time index when handling special variables
label specialVariablesIndex_;
//- The name of the other mesh (if it is to be required)
word otherMeshName_;
//- Additional libraries
dlLibraryTable libs_;
//- Writing and restoring
autoPtr<exprDriverWriter> writer_;
// Private Member Functions
//- Read the IOobject and return the headerClassName
static word getHeaderClassName
(
const polyMesh& mesh,
const word& name
);
//- Read the set IOobject and return its headerClassName
static word getSetClassName
(
const polyMesh& mesh,
const word& name
);
//- No copy assignment
void operator=(const fvExprDriver&) = delete;
protected:
// Static Member Functions
//- Determine mesh or region mesh as specified in the dictionary
//- with the keyword "region"
static const fvMesh& regionMesh
(
const dictionary& dict,
const fvMesh& mesh,
bool readIfNecessary
);
//- Default boundary type is calculated
template<class T>
static inline word defaultBoundaryType(const T&)
{
return "calculated";
}
//- Default boundary type for volume fields is zeroGradient
template<class Type>
static inline word defaultBoundaryType
(
const GeometricField<Type, fvPatchField, volMesh>&
)
{
return "zeroGradient";
}
//- Apply correctBoundaryConditions (volume fields only)
template<class T>
static inline void correctField(T&) {}
template<class Type>
static inline void correctField
(
GeometricField<Type, fvPatchField, volMesh>& fld
)
{
fld.correctBoundaryConditions();
}
// Protected Member Functions
// Mesh related
//- The mesh we are attached to
virtual const fvMesh& mesh() const = 0;
// Variables
//- Define scopes for global variables
void setGlobalScopes(const wordUList& scopes)
{
globalScopes_ = scopes;
}
//- Non-const access to the named variable (sub-classes only)
inline virtual exprResult& variable(const word& name);
//- Test existence of a global variable
template<class T>
bool isGlobalVariable
(
const word& name,
bool isPointVal,
label expectedSize = -1
) const;
//- Return the global variable if available or a null result
const exprResult& lookupGlobal(const word& name) const;
// Fields
//- Test for the existence of a mesh field
template<class Type>
bool isField
(
const word& name,
bool isPointVal = false,
label expectSize = -1 //!< ignored
) const;
//- Retrieve field from memory or disk
template<class GeomField>
inline tmp<GeomField> getOrReadField
(
const word& name,
bool mandatory = true,
bool getOldTime = false
);
//- Retrieve point field from memory or disk
template<class GeomField>
inline tmp<GeomField> getOrReadPointField
(
const word& name,
bool mandatory = true,
bool getOldTime = false
);
//- Retrieve field from memory or disk (implementation)
template<class GeomField, class MeshRef>
tmp<GeomField> getOrReadFieldImpl
(
const word& name,
const MeshRef& meshRef,
bool mandatory = true,
bool getOldTime = false
);
//- Helper function for getOrReadField
template<class GeomField, class MeshRef>
inline tmp<GeomField> readAndRegister
(
const word& name,
const MeshRef& meshRef
);
//- Create a random field
//
// \param field the field to populate
// \param seed the seed value. If zero or negative, use as an offset
// to the current timeIndex
// \param gaussian generate a Gaussian distribution
void fill_random
(
scalarField& field,
label seed = 0,
const bool gaussian = false
) const;
// Sets
//- The origin of the topoSet
enum SetOrigin { INVALID = 0, NEW, FILE, MEMORY, CACHE };
//- Get topoSet
template<class T>
autoPtr<T> getTopoSet
(
const fvMesh& mesh,
const word& setName,
SetOrigin& origin
) const;
//- Update topoSet
template<class T>
inline bool updateSet
(
autoPtr<T>& setPtr,
const word& setName,
SetOrigin origin
) const;
// Updating
//- Examine current variable values and update stored variables
virtual void updateSpecialVariables(bool force=false);
//- Do we need a data file to be written
virtual bool hasDataToWrite() const;
//- Prepare/update special variables and add to dictionary,
//- normally via the reader/writer
virtual void prepareData(dictionary& dict) const;
//- Read data from dictionary, normally via the reader/writer
virtual void getData(const dictionary& dict);
public:
// Friends
friend class exprDriverWriter;
// Static Member Functions
//- Get the default mesh, if one is defined
static const fvMesh& defaultMesh();
//- Set the default mesh (if not already set)
static const fvMesh* resetDefaultMesh
(
const fvMesh& mesh,
const bool force = false //!< Force reset, even if already set
);
//- Runtime type information
TypeName("fvExprDriver");
// Run-time selection
declareRunTimeSelectionTable
(
autoPtr,
fvExprDriver,
dictionary,
(
const dictionary& dict,
const fvMesh& mesh
),
(dict,mesh)
);
declareRunTimeSelectionTable
(
autoPtr,
fvExprDriver,
idName,
(
const word& ident,
const fvMesh& mesh
),
(ident, mesh)
);
// Constructors
//- Null constructor, and null construct with search preferences
explicit fvExprDriver
(
bool cacheReadFields = false,
bool searchInMemory = true,
bool searchFiles = false,
const dictionary& dict = dictionary::null
);
//- Copy construct
fvExprDriver(const fvExprDriver&);
//- Construct from a dictionary
explicit fvExprDriver(const dictionary& dict);
//- Return a reference to the selected value driver
static autoPtr<fvExprDriver> New
(
const dictionary& dict,
const fvMesh& mesh
);
//- Return a reference to the selected value driver
static autoPtr<fvExprDriver> New
(
const dictionary& dict
);
//- Return a reference to the selected value driver
static autoPtr<fvExprDriver> New
(
const word& type,
const word& id,
const fvMesh& mesh
);
//- Clone
virtual autoPtr<fvExprDriver> clone() const = 0;
//- Destructor
virtual ~fvExprDriver();
// Public Member Functions
//- The underlying field size for the expression
virtual label size() const = 0;
//- The underlying point field size for the expression
virtual label pointSize() const = 0;
// Mesh Related
//- The Time associated with the mesh
const Time& runTime() const;
//- The current time name
virtual word timeName() const;
//- The current time value
virtual scalar timeValue() const;
// General Controls
//- Status of cache-sets (static variable)
bool cacheSets() const { return cacheSets_; }
// Variables
//- Clear temporary variables and resets from expression strings
virtual void clearVariables();
//- True if named variable exists
inline virtual bool hasVariable(const word& name) const;
//- Return const-access to the named variable
inline virtual const exprResult& variable(const word& name) const;
//- Test for existence of a local/global variable or a field
template<class Type>
inline bool isVariableOrField
(
const word& name,
bool isPointVal = false,
label expectSize = -1
) const;
//- Retrieve local/global variable as a tmp field
//
// \param name The name of the local/global field
// \param expectSize The size check on the variable, -1 to ignore
// \param mandatory A missing variable is Fatal, or return
// an invalid tmp
template<class Type>
tmp<Field<Type>> getVariable
(
const word& name,
label expectSize,
const bool mandatory = true
) const;
//- Lookup the field class name (memory or read from disk)
//
// Return empty if the name cannot be resolved.
word getFieldClassName(const word& name) const;
// Types
//- Return cell/face/point set type or unknown
topoSetSource::sourceType topoSetType(const word& name) const;
//- Return cell/face/point zone type or unknown
topoSetSource::sourceType topoZoneType(const word& name) const;
//- 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
(
const word& name,
enum topoSetSource::sourceType setType
) const;
//- Test if name is a known cellZone
bool isCellZone(const word& name) const;
//- Test if name is a known faceZone
bool isFaceZone(const word& name) const;
//- Test if name is a known pointZone
bool isPointZone(const word& name) const;
//- Test if name is a known cellSet
bool isCellSet(const word& name) const;
//- Test if name is a known faceSet
bool isFaceSet(const word& name) const;
//- Test if name is a known pointSet
bool isPointSet(const word& name) const;
// Evaluation
//- Evaluate the expression
//- and save as the specified named variable
virtual void evaluateVariable
(
const word& varName,
const expressions::exprString& expr
);
//- Evaluate an expression on a remote
//- and save as the specified named variable
//
// The fully qualified form of the remote is given as follows
// \verbatim
// type'name/region
// \endverbatim
//
// If not specified, the default type is "patch", which means the
// following are equivalent
// \verbatim
// patch'name/region
// name/region
// \endverbatim
//
// If region is identical to the current region, it can be omitted:
// \verbatim
// patch'name
// name (default is patch)
// \endverbatim
virtual void evaluateVariableRemote
(
string remote,
const word& varName,
const expressions::exprString& expr
);
// Fields
//- Test existence of a local/global variable
template<class Type>
inline bool isVariable
(
const word& name,
bool isPointVal = false,
label expectSize = -1
) const;
//- Test if specified field can be found in memory or disk
template<class Type>
bool foundField(const word& name) const;
//- Read the IOobject for fieldName and return its headerClassName
// Empty if the field could not be found.
word getTypeOfField(const word& fieldName) const;
// Handling remote data (future)
// //- Access the other mesh name (future)
// const word& otherMeshName() const { return otherMeshName_; }
//
// //- Access the other mesh name (future)
// word& otherMeshName() { return otherMeshName_; }
// Reading
//- Read variables, tables etc.
// Also usable for objects not constructed from a dictionary.
virtual bool readDict(const dictionary& dict);
// Writing
//- Write "variables", "storedVariables", "delayedVariables",
//- "globalScopes" if they are present.
Ostream& writeCommon(Ostream& os, bool debug=false) const;
//- Create a writer for this object
void createWriterAndRead(const word& name);
//- Write data if apropriate
//- Should enable exact restarts
void tryWrite() const;
// Plugins (future)
/// //- Tests for a plugin-function
/// virtual bool hasPlugin(const word& name) = 0;
///
/// //- Return a new plugin-function
/// virtual autoPtr<CommonPluginFunction>
/// getPlugin(const word& name) = 0;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "fvExprDriverI.H"
#ifdef NoRepository
#include "fvExprDriverTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,49 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
Copyright (C) 2019 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 "fvExprDriver.H"
#include "Time.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::expressions::fvExprDriver::fill_random
(
scalarField& field,
label seed,
const bool gaussian
) const
{
exprDriver::fill_random
(
field, (seed <= 0 ? (runTime().timeIndex() - seed) : seed),
gaussian
);
}
// ************************************************************************* //

View File

@ -0,0 +1,179 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
Copyright (C) 2019 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 "Time.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::expressions::fvExprDriver::hasVariable
(
const word& name
) const
{
return delayedVariables_.found(name) || variables_.found(name);
}
inline const Foam::expressions::exprResult&
Foam::expressions::fvExprDriver::variable
(
const word& name
) const
{
if (delayedVariables_.found(name))
{
return delayedVariables_[name];
}
return variables_[name];
}
inline Foam::expressions::exprResult&
Foam::expressions::fvExprDriver::variable
(
const word& name
)
{
if (delayedVariables_.found(name))
{
return delayedVariables_[name];
}
return variables_[name];
}
template<class Type>
inline bool Foam::expressions::fvExprDriver::isVariable
(
const word& name,
bool isPointVal,
label expectedSize
) const
{
return
(
this->isLocalVariable<Type>(name, isPointVal, expectedSize)
|| this->isGlobalVariable<Type>(name, isPointVal, expectedSize)
);
}
template<class Type>
inline bool Foam::expressions::fvExprDriver::isVariableOrField
(
const word& name,
bool isPointVal,
label expectedSize
)
const
{
return
(
this->isVariable<Type>(name, isPointVal, expectedSize)
|| this->isField<Type>(name, isPointVal)
);
}
template<class GeomField>
inline Foam::tmp<GeomField>
Foam::expressions::fvExprDriver::getOrReadField
(
const word& name,
bool mandatory,
bool getOldTime
)
{
return this->getOrReadFieldImpl<GeomField>
(
name,
this->mesh(),
mandatory,
getOldTime
);
}
template<class GeomField>
inline Foam::tmp<GeomField>
Foam::expressions::fvExprDriver::getOrReadPointField
(
const word& name,
bool mandatory,
bool getOldTime
)
{
return this->getOrReadFieldImpl<GeomField>
(
name,
pointMesh::New(this->mesh()),
mandatory,
getOldTime
);
}
template<class GeomField, class Mesh>
inline Foam::tmp<GeomField>
Foam::expressions::fvExprDriver::readAndRegister
(
const word& name,
const Mesh& meshRef
)
{
GeomField* ptr = new GeomField
(
IOobject
(
name,
meshRef.thisDb().time().timeName(),
meshRef.thisDb(),
IOobject::MUST_READ,
IOobject::NO_WRITE,
false // Unregistered
),
meshRef
);
if (cacheReadFields())
{
DebugInfo
<< "Registering a copy of " << name << " with mesh" << nl;
// This is clunky
ptr->checkIn();
return tmp<GeomField>(regIOobject::store(ptr));
}
return tmp<GeomField>(ptr);
}
// ************************************************************************* //

View File

@ -0,0 +1,280 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
Copyright (C) 2019 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 "fvExprDriver.H"
#include "exprDriverWriter.H"
#include "cellSet.H"
#include "faceSet.H"
#include "pointSet.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels
(
const word& name,
enum topoSetSource::sourceType setType
) const
{
// Zones first - they are cheap to handle (no IO)
switch (setType)
{
case topoSetSource::sourceType::CELLZONE_SOURCE:
{
const auto& zones = mesh().cellZones();
const word& zoneTypeName = cellZone::typeName;
const label zoneID = zones.findZoneID(name);
if (zoneID < 0)
{
FatalErrorInFunction
<< "No " << zoneTypeName << " named "
<< name << "found. Has zones: " << zones.names() << endl
<< exit(FatalError);
}
return zones[zoneID];
break;
}
case topoSetSource::sourceType::FACEZONE_SOURCE:
{
const auto& zones = mesh().faceZones();
const word& zoneTypeName = faceZone::typeName;
const label zoneID = zones.findZoneID(name);
if (zoneID < 0)
{
FatalErrorInFunction
<< "No " << zoneTypeName << " named "
<< name << "found. Has zones: " << zones.names() << endl
<< exit(FatalError);
}
return zones[zoneID];
break;
}
case topoSetSource::sourceType::POINTZONE_SOURCE:
{
const auto& zones = mesh().pointZones();
const word& zoneTypeName = pointZone::typeName;
const label zoneID = zones.findZoneID(name);
if (zoneID < 0)
{
FatalErrorInFunction
<< "No " << zoneTypeName << " named "
<< name << "found. Has zones: " << zones.names() << endl
<< exit(FatalError);
}
return zones[zoneID];
break;
}
default:
break;
}
IOobject io(topoSet::findIOobject(mesh(), name));
switch (setType)
{
case topoSetSource::sourceType::CELLSET_SOURCE:
{
typedef cellSet classType;
if (classType::typeName != io.headerClassName())
{
FatalErrorInFunction
<< "Error reading " << classType::typeName
<< " <" << name << "> : found "
<< io.headerClassName() << nl
<< exit(FatalError);
}
classType set(io);
return set.sortedToc();
break;
}
case topoSetSource::sourceType::FACESET_SOURCE:
{
typedef faceSet classType;
if (classType::typeName != io.headerClassName())
{
FatalErrorInFunction
<< "Error reading " << classType::typeName
<< " <" << name << "> : found "
<< io.headerClassName() << nl
<< exit(FatalError);
}
classType set(io);
return set.sortedToc();
break;
}
case topoSetSource::sourceType::POINTSET_SOURCE:
{
typedef pointSet classType;
if (classType::typeName != io.headerClassName())
{
FatalErrorInFunction
<< "Error reading " << classType::typeName
<< " <" << name << "> : found "
<< io.headerClassName() << nl
<< exit(FatalError);
}
classType set(io);
return set.sortedToc();
break;
}
default:
{
FatalErrorInFunction
<< "Unexpected sourceType: " << int(setType) << nl
<< " for set <" << name << ">" << nl
<< exit(FatalError);
break;
}
}
return labelList::null();
}
Foam::word Foam::expressions::fvExprDriver::getHeaderClassName
(
const polyMesh& mesh,
const word& name
)
{
IOobject io
(
name,
mesh.time().timeName(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
io.typeHeaderOk<IOobject>(false);
DebugInfo
<< "Registry: " << mesh.path()
<< " Name: " << name
<< " Time: " << mesh.time().timeName()
<< " Path: " << io.localFilePath(io.headerClassName())
<< " Class: " << io.headerClassName() << endl;
return io.headerClassName();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::Ostream& Foam::expressions::fvExprDriver::writeCommon
(
Ostream& os,
bool debug
) const
{
// Write "variables", even if empty
writeVariableStrings(os, "variables");
if (debug)
{
os.writeEntry("variableValues", variables_);
}
if (!storedVariables_.empty() || !delayedVariables_.empty())
{
const_cast<fvExprDriver&>
(
*this
).updateSpecialVariables(true);
}
if (!storedVariables_.empty())
{
os.writeEntry("storedVariables", storedVariables_);
}
if (!delayedVariables_.empty())
{
List<exprResultDelayed> list(delayedVariables_.size());
auto outIter = list.begin();
forAllConstIters(delayedVariables_, iter)
{
*outIter = *iter;
++outIter;
}
os.writeEntry("delayedVariables", list);
}
if (!globalScopes_.empty())
{
os.writeEntry("globalScopes", globalScopes_);
}
// writeTable(os, "timelines", lines_);
// writeTable(os, "lookuptables", lookup_);
// writeTable(os, "lookuptables2D", lookup2D_);
return os;
}
void Foam::expressions::fvExprDriver::createWriterAndRead(const word& name)
{
if (hasDataToWrite() && !writer_.valid())
{
writer_.set(new exprDriverWriter(name + "_" + this->type(), *this));
}
}
void Foam::expressions::fvExprDriver::tryWrite() const
{
if (writer_.valid() && mesh().time().outputTime())
{
writer_->write();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,105 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
Copyright (C) 2019 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 "fvExprDriver.H"
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::expressions::fvExprDriver>
Foam::expressions::fvExprDriver::New
(
const dictionary& dict
)
{
return fvExprDriver::New
(
dict,
defaultMesh()
);
}
Foam::autoPtr<Foam::expressions::fvExprDriver>
Foam::expressions::fvExprDriver::New
(
const dictionary& dict,
const fvMesh& mesh
)
{
const word driverType(dict.get<word>("valueType"));
auto cstrIter = dictionaryConstructorTablePtr_->cfind(driverType);
if (!cstrIter.found())
{
FatalIOErrorInLookup
(
dict,
"valueType",
driverType,
*dictionaryConstructorTablePtr_
) << exit(FatalIOError);
}
DebugInFunction << "Creating driver of type " << driverType << endl;
resetDefaultMesh(mesh, false); // lazy
return autoPtr<fvExprDriver>(cstrIter()(dict, mesh));
}
Foam::autoPtr<Foam::expressions::fvExprDriver>
Foam::expressions::fvExprDriver::New
(
const word& driverType,
const word& id,
const fvMesh& mesh
)
{
auto cstrIter = idNameConstructorTablePtr_->cfind(driverType);
if (!cstrIter.found())
{
FatalErrorInLookup
(
"valueType",
driverType,
*idNameConstructorTablePtr_
) << exit(FatalError);
}
DebugInFunction << "Creating driver of type " << driverType << endl;
resetDefaultMesh(mesh, false); // lazy
return autoPtr<fvExprDriver>(cstrIter()(id, mesh));
}
// ************************************************************************* //

View File

@ -0,0 +1,626 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com>
Copyright (C) 2019 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 "surfaceMesh.H"
#include "fvsPatchField.H"
#include "pointPatchField.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
bool Foam::expressions::fvExprDriver::isGlobalVariable
(
const word& name,
bool isPointVal,
label expectedSize
) const
{
DebugInfo
<< "Looking for global" << (isPointVal ? " point" : "")
<< " field name:" << name;
const exprResult& result = lookupGlobal(name);
DebugInfo
<< " - found (" << result.valueType() << ' ' << result.isPointValue() << ')';
bool good = (result.isType<Type>() && result.isPointValue(isPointVal));
// Do size checking if requested
if (good && expectedSize >= 0)
{
good = (result.size() == expectedSize);
reduce(good, andOp<bool>());
if (debug && !good)
{
Info<< " size is";
}
}
DebugInfo << (good ? " good" : " bad") << endl;
return good;
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::fvExprDriver::getVariable
(
const word& name,
label expectedSize,
const bool mandatory
) const
{
tmp<Field<Type>> tresult;
bool isSingleValue = false;
if (hasVariable(name) && variable(name).isType<Type>())
{
isSingleValue = variable(name).isUniform();
tresult = variable(name).cref<Type>().clone();
}
else if (isGlobalVariable<Type>(name, false))
{
const exprResult& var = lookupGlobal(name);
isSingleValue = var.isUniform();
tresult = var.cref<Type>().clone();
}
if (tresult.valid())
{
if
(
expectedSize < 0
|| returnReduce((tresult->size() == expectedSize), andOp<bool>())
)
{
return tresult;
}
if (!isSingleValue)
{
WarningInFunction
<< "Variable " << name
<< " is not a single value and does not fit the size "
<< expectedSize << ". Using average" << endl;
}
return tmp<Field<Type>>::New(expectedSize, gAverage(tresult()));
}
if (mandatory)
{
FatalErrorInFunction
<< "Variable (" << name << ") not found." << nl
<< exit(FatalError);
}
return nullptr;
}
template<class Type>
bool Foam::expressions::fvExprDriver::foundField
(
const word& name
) const
{
if (debug)
{
Info<< "fvExprDriver::foundField. Name: " << name
<< " Type: " << Type::typeName
<< " registry:" << searchInMemory()
<< " disk:" << searchFiles() << endl;
}
// if (std::is_void<Type>::value) ...
if (searchInMemory())
{
const regIOobject* ioptr =
this->mesh().findObject<regIOobject>(name);
if (this->mesh().foundObject<Type>(name))
{
if (debug)
{
Info<< "Found registered: " << name << endl;
}
return true;
}
if (debug)
{
Info<< "Registered " << name;
if (ioptr)
{
Info<< " type:" << ioptr->headerClassName();
}
Info<< ", not type:" << Type::typeName << nl;
}
}
if (searchFiles() && getTypeOfField(name) == Type::typeName)
{
if (debug)
{
Info<< "Found file: " << name << nl;
}
return true;
}
else
{
if (debug)
{
Info<< name << " not found" << endl;
}
}
return false;
}
template<class Type>
bool Foam::expressions::fvExprDriver::isField
(
const word& name,
bool isPointVal,
label
) const
{
if (debug)
{
Info<< "fvExprDriver::isField <" << name << '>' << endl;
}
typedef GeometricField<Type, fvPatchField, volMesh> vfieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> sfieldType;
typedef GeometricField<Type, pointPatchField, pointMesh> pfieldType;
return
(
isPointVal
? this->foundField<pfieldType>(name)
:
(
this->foundField<vfieldType>(name)
|| this->foundField<sfieldType>(name)
)
);
}
template<class GeomField, class Mesh>
Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
(
const word& name,
const Mesh& meshRef,
bool mandatory,
bool getOldTime
)
{
typedef typename GeomField::value_type Type;
if (debug)
{
Info<< "fvExprDriver::getOrReadField <" << name
<< "> Type: " << GeomField::typeName << endl;
}
tmp<GeomField> tfield;
if
(
(hasVariable(name) && variable(name).isType<Type>())
|| isGlobalVariable<Type>(name, false)
)
{
if (debug)
{
Info<< "Getting " << name << " from variables" << endl;
}
if (debug)
{
Info<< "Creating field " << name << " of type "
<< GeomField::typeName << nl;
}
tfield.reset
(
GeomField::New(name, meshRef, dimensioned<Type>(Zero))
);
GeomField& fld = tfield.ref();
if (debug)
{
Info<< "New field: " << name << " ownedByRegistry"
<< fld.ownedByRegistry() << endl;
}
Field<Type> vals;
if (hasVariable(name) && variable(name).isType<Type>())
{
vals = variable(name).cref<Type>();
}
else
{
vals = lookupGlobal(name).cref<Type>();
}
if (debug)
{
Pout<< "sizes: " << vals.size() << ' ' << fld.size() << endl;
}
if (returnReduce((vals.size() == fld.size()), andOp<bool>()))
{
fld.primitiveFieldRef() = vals;
}
else
{
Type avg = gAverage(vals);
bool noWarn = false;
if (!noWarn)
{
MinMax<Type> range = gMinMax(vals);
if (range.mag() > SMALL)
{
WarningInFunction
<< "The min/max ranges differ " << range
<< " - using average " << avg << nl;
}
}
fld.primitiveFieldRef() = avg;
}
correctField(fld);
return tfield;
}
const objectRegistry& obr = meshRef.thisDb();
if (searchInMemory() && obr.foundObject<GeomField>(name))
{
if (debug)
{
Info<< "Retrieve registered: " << name << nl;
}
const GeomField& origFld = obr.lookupObject<GeomField>(name);
// Avoid shadowing the original object
tfield.reset
(
GeomField::New(name + "_exprDriverCopy", origFld)
);
if (getOldTime)
{
if (debug)
{
Info<< "Getting oldTime of " << name << " has "
<< origFld.nOldTimes() << endl;
}
if (!origFld.nOldTimes() && this->prevIterIsOldTime())
{
if (debug)
{
Info<< "No oldTime, using previous iteration" << endl;
}
tfield.ref().oldTime() = origFld.prevIter();
}
}
}
else if (searchFiles() && getTypeOfField(name) == GeomField::typeName)
{
if (debug)
{
Info<< "Reading " << name << " from disc" << endl;
}
tfield.reset
(
this->readAndRegister<GeomField>(name, meshRef)
);
// oldTime automatically read
}
if (debug)
{
Info<< "field: valid()=" << tfield.valid() << endl;
}
if (tfield.valid())
{
GeomField& fld = tfield.ref();
if (debug)
{
Info<< "Valid " << name << " found. Removing dimensions" << nl;
}
fld.dimensions().clear();
if (fld.nOldTimes())
{
if (debug)
{
Info<< "Removing dimensions of oldTime of " << name
<< " has " << fld.nOldTimes() << nl;
}
// Switch dimension checking off
const int oldDebug = dimensionSet::debug;
dimensionSet::debug = 0;
// go through ALL old times
GeomField* fp = &(fld);
while (fp->nOldTimes())
{
fp = &(fp->oldTime());
fp->dimensions().clear();
}
// Restore old value of dimension checking
dimensionSet::debug = oldDebug;
}
}
else if (mandatory)
{
FatalErrorInFunction
<< "Could not find field " << name
<< " in registry or on file-system" << nl
<< exit(FatalError);
}
return tfield;
}
template<class T>
Foam::autoPtr<T> Foam::expressions::fvExprDriver::getTopoSet
(
const fvMesh& mesh,
const word& name,
SetOrigin& origin
) const
{
// Avoid possible name clashes
const word regName = name + "RegisteredNameFor" + T::typeName;
if (debug)
{
Info<< "Looking for " << T::typeName << " named " << name;
Info<< " or registered as " << regName << " with mesh "
<< "Caching:" << cacheSets()
<< " Found:" << (mesh.foundObject<T>(name))
<< " Found registered:" << mesh.foundObject<T>(regName)
<< endl;
}
origin = SetOrigin::INVALID;
autoPtr<T> setPtr;
if
(
!cacheSets()
||
(
!mesh.thisDb().foundObject<T>(regName)
&& !mesh.thisDb().foundObject<T>(name)
)
)
{
if (debug)
{
Info<< "Constructing new " << T::typeName << ' ' << name << nl;
if (debug > 1)
{
Pout<< mesh.thisDb().names();
}
}
origin = SetOrigin::FILE;
setPtr.reset(new T(mesh, name, IOobject::MUST_READ));
if (cacheSets())
{
if (debug)
{
Info<< "Registering a copy of " << name << " with mesh" << nl;
}
autoPtr<T> toCache(new T(mesh, regName, *setPtr));
toCache->store(toCache);
}
}
else
{
const T* ptr = mesh.thisDb().findObject<T>(name);
if (ptr)
{
if (debug)
{
Info<< "Getting existing " << name << endl;
}
origin = SetOrigin::MEMORY;
setPtr.reset(new T(mesh, name, *ptr));
}
else
{
if (debug)
{
Info<< "Getting existing " << regName << endl;
}
origin = SetOrigin::CACHE;
setPtr.reset(new T(mesh, name, mesh.lookupObject<T>(regName)));
}
}
return setPtr;
}
template<class T>
bool Foam::expressions::fvExprDriver::updateSet
(
autoPtr<T>& setPtr,
const word& name,
SetOrigin origin
) const
{
const label oldSize = setPtr->size();
bool updated = false;
const polyMesh& mesh = dynamic_cast<const polyMesh&>(setPtr->db());
if (debug)
{
Info<< "UpdateSet: " << setPtr->name() << " Id: " << name
<< " Origin: " << int(origin) << endl;
}
switch (origin)
{
case SetOrigin::FILE:
{
IOobject header
(
name,
mesh.time().timeName(),
polyMesh::meshSubDir/"sets",
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE
);
if (header.typeHeaderOk<T>())
{
if (debug)
{
Pout<< "Rereading from "
<< header.localFilePath(T::typeName) << endl;
}
setPtr.reset(new T(header));
updated = true;
}
break;
}
case SetOrigin::NEW:
case SetOrigin::MEMORY:
case SetOrigin::CACHE:
{
if (origin == SetOrigin::NEW)
{
WarningInFunction
<< "State NEW shouldn't exist"
<< endl;
}
word sName = name;
const T* ptr = mesh.thisDb().findObject<T>(name);
if (ptr)
{
if (debug)
{
Info<< "Found " << name
<< " and rereading it" << endl;
}
setPtr.reset(new T(mesh, name, *ptr));
}
else
{
FatalErrorInFunction
<< name << " Not found" << endl
<< "In registry: " << mesh.thisDb().names() << endl
<< exit(FatalError);
}
updated = true;
break;
}
case INVALID:
{
FatalErrorInFunction
<< T::typeName << ' ' << name << " is invalid" << endl
<< exit(FatalError);
break;
}
default:
{
if (debug)
{
Info<< "Origin " << int(origin) << " not implemented" << endl;
}
break;
}
}
if (debug)
{
Pout<< name << " old size " << oldSize << " new: "
<< setPtr->size() << endl;
}
return updated;
}
// ************************************************************************* //

View File

@ -0,0 +1,186 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2011-2018 Bernhard Gschaider
Copyright (C) 2019 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 "patchExprFieldBase.H"
#include "facePointPatch.H"
#include "fvMesh.H"
#include "fvPatch.H"
#include "pointMesh.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
const Foam::fvPatch&
Foam::expressions::patchExprFieldBase::getFvPatch(const facePointPatch& pp)
{
const polyMesh& pmesh = pp.boundaryMesh().mesh().mesh();
const fvMesh* meshptr = isA<fvMesh>(pmesh);
if (!meshptr)
{
FatalErrorInFunction
<< "Point patch not attached to a base fvMesh, "
<< "cannot use patch expressions" << nl << endl
<< exit(FatalError);
}
return meshptr->boundary()[pp.index()];
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::expressions::patchExprFieldBase::patchExprFieldBase()
:
patchExprFieldBase(false)
{}
Foam::expressions::patchExprFieldBase::patchExprFieldBase
(
bool allowGradient
)
:
debug_(false),
allowGradient_(allowGradient),
evalOnConstruct_(false),
valueExpr_(),
gradExpr_(),
fracExpr_()
{}
Foam::expressions::patchExprFieldBase::patchExprFieldBase
(
const dictionary& dict,
bool allowGradient,
bool isPointVal
)
:
debug_(dict.lookupOrDefault("debug", false)),
allowGradient_(allowGradient),
evalOnConstruct_(dict.lookupOrDefault<bool>("evalOnConstruct", false)),
valueExpr_(),
gradExpr_(),
fracExpr_()
{
if (debug_)
{
Info<< "Expression BC with " << dict << nl;
}
string expr;
if (dict.readIfPresent("valueExpr", expr))
{
valueExpr_ = expressions::exprString(expr, dict);
}
else
{
// No value expression - same as Zero
if (debug_)
{
Info<< "No valueExpr" << nl;
}
}
if (allowGradient)
{
if (dict.readIfPresent("gradientExpr", expr))
{
gradExpr_ = expressions::exprString(expr, dict);
}
else
{
// No gradient expression - same as Zero
if (debug_)
{
Info<< "No gradientExpr" << nl;
}
}
if (dict.readIfPresent("fractionExpr", expr))
{
if (!expr.empty() && expr != "0")
{
if (isPointVal)
{
expr = "toPoint(" + expr + ")";
}
fracExpr_ = expressions::exprString(expr, dict);
}
}
else
{
// No fraction expression - same as 1 (one)
// Mixed BC may elect to simply ignore gradient expression
}
}
}
Foam::expressions::patchExprFieldBase::patchExprFieldBase
(
const patchExprFieldBase& rhs
)
:
debug_(rhs.debug_),
allowGradient_(rhs.allowGradient_),
evalOnConstruct_(rhs.evalOnConstruct_),
valueExpr_(rhs.valueExpr_),
gradExpr_(rhs.gradExpr_),
fracExpr_(rhs.fracExpr_)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::expressions::patchExprFieldBase::write(Ostream& os) const
{
os.writeEntryIfDifferent<bool>("evalOnConstruct", false, evalOnConstruct_);
// Do not emit debug_ value
if (!valueExpr_.empty())
{
os.writeEntry("valueExpr", valueExpr_);
}
if (!gradExpr_.empty())
{
os.writeEntry("gradientExpr", gradExpr_);
}
if (!fracExpr_.empty())
{
os.writeEntry("fractionExpr", fracExpr_);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,131 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2011-2018 Bernhard Gschaider
Copyright (C) 2019 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::patchExprFieldBase
Description
Base class for managing patches with expressions.
The expected input supports values, gradients and mixed conditions
Usage
\table
Property | Description | Required | Default
valueExpr | expression for fixed value | no | 0
gradientExpr | expression for patch normal gradient | no | 0
fractionExpr | expression for value fraction weight | no | 1
\endtable
SourceFiles
patchExprFieldBase.C
\*---------------------------------------------------------------------------*/
#ifndef expressions_patchExprFieldBase_H
#define expressions_patchExprFieldBase_H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "dictionary.H"
#include "exprString.H"
namespace Foam
{
// Forward Declarations
class facePointPatch;
class fvPatch;
namespace expressions
{
/*---------------------------------------------------------------------------*\
Class patchExprFieldBase Declaration
\*---------------------------------------------------------------------------*/
class patchExprFieldBase
{
protected:
// Protected Data
bool debug_;
bool allowGradient_;
//- Slightly dodgy concept here
bool evalOnConstruct_;
// The expressions
expressions::exprString valueExpr_;
expressions::exprString gradExpr_;
expressions::exprString fracExpr_;
public:
// Static Methods
//- Find (guess) fvPatch from a pointPatch
static const fvPatch& getFvPatch(const facePointPatch& fp);
// Constructors
//- Null constructor
patchExprFieldBase();
//- Construct with specified gradient handling
explicit patchExprFieldBase(bool allowGradient);
//- Construct from dictionary
explicit patchExprFieldBase
(
const dictionary& dict,
bool allowGradient = false,
bool isPointVal = false
);
//- Copy constructor
patchExprFieldBase(const patchExprFieldBase& rhs);
// Member Functions
//- Write
void write(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,215 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2009-2018 Bernhard Gschaider
Copyright (C) 2019 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 "exprFixedValueFvPatchField.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
void Foam::exprFixedValueFvPatchField<Type>::setDebug()
{
if (expressions::patchExprFieldBase::debug_ && !debug)
{
debug = 1;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF
)
:
fixedValueFvPatchField<Type>(p, iF),
expressions::patchExprFieldBase(false),
driver_(this->patch())
{}
template<class Type>
Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField
(
const exprFixedValueFvPatchField<Type>& ptf,
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
fixedValueFvPatchField<Type>(ptf, p, iF, mapper),
expressions::patchExprFieldBase(ptf),
driver_(this->patch(), ptf.driver_)
{
setDebug();
DebugInFunction << nl;
}
template<class Type>
Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const dictionary& dict,
const bool valueRequired
)
:
fixedValueFvPatchField<Type>(p, iF),
expressions::patchExprFieldBase(dict),
driver_(this->patch(), dict)
{
setDebug();
DebugInFunction << nl;
// Basic sanity
if (this->valueExpr_.empty())
{
FatalIOErrorInFunction(dict)
<< "The valueExpr was not defined!" << nl
<< exit(FatalIOError);
}
driver_.readDict(dict);
if (dict.found("value"))
{
fvPatchField<Type>::operator=
(
Field<Type>("value", dict, p.size())
);
}
else
{
(*this) == this->patchInternalField();
WarningInFunction
<< "No value defined for "
<< this->internalField().name() << " on "
<< this->patch().name() << " - setting to internalField value "
<< nl;
}
if (this->evalOnConstruct_)
{
// For potentialFoam or other solvers that don't evaluate
this->evaluate();
}
}
template<class Type>
Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField
(
const exprFixedValueFvPatchField<Type>& ptf
)
:
fixedValueFvPatchField<Type>(ptf),
expressions::patchExprFieldBase(ptf),
driver_(this->patch(), ptf.driver_)
{
setDebug();
DebugInFunction << nl;
}
template<class Type>
Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField
(
const exprFixedValueFvPatchField<Type>& ptf,
const DimensionedField<Type, volMesh>& iF
)
:
fixedValueFvPatchField<Type>(ptf, iF),
expressions::patchExprFieldBase(ptf),
driver_(this->patch(), ptf.driver_)
{
setDebug();
DebugInFunction << nl;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::exprFixedValueFvPatchField<Type>::updateCoeffs()
{
if (debug)
{
InfoInFunction
<< "Value: " << this->valueExpr_ << nl
<< "Variables: ";
driver_.writeVariableStrings(Info) << endl;
}
if (this->updated())
{
return;
}
DebugInFunction
<< "updating" << nl;
// Expression evaluation
{
driver_.clearVariables();
if (this->valueExpr_.empty())
{
(*this) == Zero;
}
else
{
tmp<Field<Type>> tresult(driver_.evaluate<Type>(this->valueExpr_));
if (debug)
{
Info<< "Evaluated: " << tresult();
}
(*this) == tresult;
}
}
fixedValueFvPatchField<Type>::updateCoeffs();
}
template<class Type>
void Foam::exprFixedValueFvPatchField<Type>::write(Ostream& os) const
{
fixedValueFvPatchField<Type>::write(os);
expressions::patchExprFieldBase::write(os);
// driver_.writeCommon(os, this->debug_ || debug);
}
// ************************************************************************* //

View File

@ -0,0 +1,175 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2009-2018 Bernhard Gschaider
Copyright (C) 2019 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::exprFixedValueFvPatchField
Description
A fixed value boundary condition with expressions.
Usage
\table
Property | Description | Required | Default
value | fixed value | yes |
valueExpr | expression for fixed value | yes |
\endtable
SourceFiles
exprFixedValueFvPatchField.C
\*---------------------------------------------------------------------------*/
#ifndef exprFixedValueFvPatchField_H
#define exprFixedValueFvPatchField_H
#include "fixedValueFvPatchField.H"
#include "patchExprFieldBase.H"
#include "patchExprDriver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class exprFixedValueFvPatchField Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class exprFixedValueFvPatchField
:
public fixedValueFvPatchField<Type>,
public expressions::patchExprFieldBase
{
protected:
// Protected Data
//- The expression driver
expressions::patchExpr::parseDriver driver_;
// Protected Member Functions
//- Set debug ON if "debug" is enabled
void setDebug();
public:
//- Runtime type information
TypeName("exprFixedValue");
// Constructors
//- Construct from patch and internal field
exprFixedValueFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>&
);
//- Construct from patch, internal field and dictionary
exprFixedValueFvPatchField
(
const fvPatch&,
const DimensionedField<Type, volMesh>&,
const dictionary& dict,
const bool valueRequired=true
);
//- Construct by mapping given exprFixedValueFvPatchField
//- onto a new patch
exprFixedValueFvPatchField
(
const exprFixedValueFvPatchField<Type>&,
const fvPatch&,
const DimensionedField<Type, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
exprFixedValueFvPatchField
(
const exprFixedValueFvPatchField<Type>&
);
//- Construct and return a clone
virtual tmp<fvPatchField<Type>> clone() const
{
return tmp<fvPatchField<Type>>
(
new exprFixedValueFvPatchField<Type>(*this)
);
}
//- Construct as copy setting internal field reference
exprFixedValueFvPatchField
(
const exprFixedValueFvPatchField<Type>&,
const DimensionedField<Type, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchField<Type>> clone
(
const DimensionedField<Type, volMesh>& iF
) const
{
return tmp<fvPatchField<Type>>
(
new exprFixedValueFvPatchField<Type>(*this, iF)
);
}
// Member Functions
//- Update the coefficients associated with the patch field
virtual void updateCoeffs();
//- Write
virtual void write(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "exprFixedValueFvPatchField.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "exprFixedValueFvPatchFields.H"
#include "volFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
makePatchFields(exprFixedValue);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
\*---------------------------------------------------------------------------*/
#ifndef exprFixedValueFvPatchFields_H
#define exprFixedValueFvPatchFields_H
#include "exprFixedValueFvPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeFieldTypedefs(exprFixedValue);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
\*---------------------------------------------------------------------------*/
#ifndef exprFixedValueFvPatchFieldsFwd_H
#define exprFixedValueFvPatchFieldsFwd_H
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> class exprFixedValueFvPatchField;
makePatchTypeFieldTypedefs(exprFixedValue);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,309 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2009-2018 Bernhard Gschaider
Copyright (C) 2019 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 "exprMixedFvPatchField.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
void Foam::exprMixedFvPatchField<Type>::setDebug()
{
if (expressions::patchExprFieldBase::debug_ && !debug)
{
debug = 1;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF
)
:
mixedFvPatchField<Type>(p, iF),
expressions::patchExprFieldBase(true), // allowGradient
driver_(this->patch())
{
this->refValue() = Zero;
this->refGrad() = Zero;
this->valueFraction() = scalar(1);
}
template<class Type>
Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField
(
const exprMixedFvPatchField<Type>& ptf,
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const fvPatchFieldMapper& mapper
)
:
mixedFvPatchField<Type>(ptf, p, iF, mapper),
expressions::patchExprFieldBase(ptf),
driver_(this->patch(), ptf.driver_)
{
setDebug();
DebugInFunction << nl;
}
template<class Type>
Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>& iF,
const dictionary& dict
)
:
mixedFvPatchField<Type>(p, iF),
expressions::patchExprFieldBase(dict, true),
driver_(this->patch(), dict)
{
setDebug();
DebugInFunction << nl;
// Basic sanity checks
if (this->valueExpr_.empty() && this->gradExpr_.empty())
{
if (this->valueExpr_.empty())
{
FatalIOErrorInFunction(dict)
<< "The valueExpr was not defined!" << nl
<< exit(FatalIOError);
}
if (this->gradExpr_.empty())
{
FatalIOErrorInFunction(dict)
<< "The gradientExpr was not defined!" << nl
<< exit(FatalIOError);
}
}
driver_.readDict(dict);
// Similar to fvPatchField constructor, which we have bypassed
dict.readIfPresent("patchType", this->patchType());
if (dict.found("refValue"))
{
this->refValue() = Field<Type>("refValue", dict, p.size());
}
else
{
this->refValue() = this->patchInternalField();
}
if (dict.found("value"))
{
fvPatchField<Type>::operator=
(
Field<Type>("value", dict, p.size())
);
if (!dict.found("refValue"))
{
// Ensure refValue has a sensible value for the "update" below
this->refValue() = Field<Type>("value", dict, p.size());
}
}
else
{
fvPatchField<Type>::operator=(this->refValue());
WarningInFunction
<< "No value defined for "
<< this->internalField().name()
<< " on " << this->patch().name() << " therefore using "
<< "the internal field next to the patch"
<< endl;
}
if (dict.found("refGradient"))
{
this->refGrad() = Field<Type>("refGradient", dict, p.size());
}
else
{
this->refGrad() = Zero;
}
if (dict.found("valueFraction"))
{
this->valueFraction() = Field<scalar>("valueFraction", dict, p.size());
}
else
{
this->valueFraction() = 1;
}
if (this->evalOnConstruct_)
{
// For potentialFoam or other solvers that don't evaluate
this->evaluate();
}
else
{
// Emulate mixedFvPatchField<Type>::evaluate,
// but avoid our own updateCoeffs
if (!this->updated())
{
this->mixedFvPatchField<Type>::updateCoeffs();
}
Field<Type>::operator=
(
this->valueFraction()*this->refValue()
+
(1.0 - this->valueFraction())*
(
this->patchInternalField()
+ this->refGrad()/this->patch().deltaCoeffs()
)
);
fvPatchField<Type>::evaluate();
}
}
template<class Type>
Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField
(
const exprMixedFvPatchField<Type>& ptf
)
:
mixedFvPatchField<Type>(ptf),
expressions::patchExprFieldBase(ptf),
driver_(this->patch(), ptf.driver_)
{
setDebug();
DebugInFunction << nl;
}
template<class Type>
Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField
(
const exprMixedFvPatchField<Type>& ptf,
const DimensionedField<Type, volMesh>& iF
)
:
mixedFvPatchField<Type>(ptf, iF),
expressions::patchExprFieldBase(ptf),
driver_(this->patch(), ptf.driver_)
{
setDebug();
DebugInFunction << nl;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::exprMixedFvPatchField<Type>::updateCoeffs()
{
if (debug)
{
InfoInFunction
<< "Value: " << this->valueExpr_ << nl
<< "Gradient: " << this->gradExpr_ << nl
<< "Fraction: " << this->fracExpr_ << nl
<< "Variables: ";
driver_.writeVariableStrings(Info) << endl;
}
if (this->updated())
{
return;
}
DebugInFunction << " - updating" << nl;
// Expression evaluation
{
driver_.clearVariables();
if (this->valueExpr_.empty())
{
this->refValue() = Zero;
}
else
{
this->refValue() = driver_.evaluate<Type>(this->valueExpr_);
}
bool evalGrad = !this->gradExpr_.empty();
if (this->fracExpr_.empty() || this->fracExpr_ == "1")
{
evalGrad = false;
this->valueFraction() = scalar(1);
}
else if (this->fracExpr_ == "0")
{
this->valueFraction() = Zero;
}
else
{
this->valueFraction() = driver_.evaluate<scalar>(this->fracExpr_);
}
if (evalGrad)
{
this->refGrad() = driver_.evaluate<Type>(this->gradExpr_);
}
else
{
this->refGrad() = Zero;
}
}
mixedFvPatchField<Type>::updateCoeffs();
}
template<class Type>
void Foam::exprMixedFvPatchField<Type>::write(Ostream& os) const
{
mixedFvPatchField<Type>::write(os);
expressions::patchExprFieldBase::write(os);
// driver_.writeCommon(os, this->debug_ || debug);
}
// ************************************************************************* //

View File

@ -0,0 +1,172 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2009-2018 Bernhard Gschaider
Copyright (C) 2019 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::exprMixedFvPatchField
Description
A mixed boundary condition with expressions.
Usage
\table
Property | Description | Required | Default
valueExpr | expression for fixed value | no | 0
gradientExpr | expression for patch normal gradient | no | 0
fractionExpr | expression for value weighting | no | 1
\endtable
SourceFiles
exprMixedFvPatchField.C
\*---------------------------------------------------------------------------*/
#ifndef exprMixedFvPatchField_H
#define exprMixedFvPatchField_H
#include "mixedFvPatchField.H"
#include "patchExprFieldBase.H"
#include "patchExprDriver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class exprMixedFvPatchField Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class exprMixedFvPatchField
:
public mixedFvPatchField<Type>,
public expressions::patchExprFieldBase
{
protected:
// Protected Data
//- The expression driver
expressions::patchExpr::parseDriver driver_;
// Protected Member Functions
//- Set debug ON if "debug" is enabled
void setDebug();
public:
//- Runtime type information
TypeName("exprMixed");
// Constructors
//- Construct from patch and internal field
exprMixedFvPatchField
(
const fvPatch& p,
const DimensionedField<Type, volMesh>&
);
//- Construct from patch, internal field and dictionary
exprMixedFvPatchField
(
const fvPatch&,
const DimensionedField<Type, volMesh>&,
const dictionary& dict
);
//- Construct by mapping given exprMixedFvPatchField onto a new patch
exprMixedFvPatchField
(
const exprMixedFvPatchField<Type>&,
const fvPatch&,
const DimensionedField<Type, volMesh>&,
const fvPatchFieldMapper&
);
//- Construct as copy
exprMixedFvPatchField
(
const exprMixedFvPatchField<Type>&
);
//- Construct and return a clone
virtual tmp<fvPatchField<Type>> clone() const
{
return tmp<fvPatchField<Type>>
(
new exprMixedFvPatchField<Type>(*this)
);
}
//- Construct as copy setting internal field reference
exprMixedFvPatchField
(
const exprMixedFvPatchField<Type>&,
const DimensionedField<Type, volMesh>&
);
//- Construct and return a clone setting internal field reference
virtual tmp<fvPatchField<Type> > clone
(
const DimensionedField<Type, volMesh>& iF
) const
{
return tmp<fvPatchField<Type>>
(
new exprMixedFvPatchField<Type>(*this, iF)
);
}
// Member Functions
//- Update the coefficients associated with the patch field
virtual void updateCoeffs();
//- Write
virtual void write(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "exprMixedFvPatchField.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "exprMixedFvPatchFields.H"
#include "volFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
makePatchFields(exprMixed);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
\*---------------------------------------------------------------------------*/
#ifndef exprMixedFvPatchFields_H
#define exprMixedFvPatchFields_H
#include "exprMixedFvPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePatchTypeFieldTypedefs(exprMixed);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
\*---------------------------------------------------------------------------*/
#ifndef exprMixedFvPatchFieldsFwd_H
#define exprMixedFvPatchFieldsFwd_H
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type> class exprMixedFvPatchField;
makePatchTypeFieldTypedefs(exprMixed);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,219 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2010-2018 Bernhard Gschaider
Copyright (C) 2019 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 "exprValuePointPatchField.H"
#include "pointPatchFieldMapper.H"
#include "typeInfo.H"
#include "facePointPatch.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type>
Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
const pointPatch& p,
const DimensionedField<Type, pointMesh>& iF
)
:
valuePointPatchField<Type>(p, iF),
expressions::patchExprFieldBase(false),
driver_
(
expressions::patchExprFieldBase::getFvPatch
(
dynamicCast<const facePointPatch>(this->patch())
)
)
{}
template<class Type>
Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
const exprValuePointPatchField<Type>& ptf,
const pointPatch& p,
const DimensionedField<Type, pointMesh>& iF,
const pointPatchFieldMapper& mapper
)
:
valuePointPatchField<Type>(ptf, p, iF, mapper),
expressions::patchExprFieldBase(ptf),
driver_
(
expressions::patchExprFieldBase::getFvPatch
(
dynamicCast<const facePointPatch>(this->patch())
),
ptf.driver_
)
{}
template<class Type>
Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
const pointPatch& p,
const DimensionedField<Type, pointMesh>& iF,
const dictionary& dict
)
:
valuePointPatchField<Type>(p, iF),
expressions::patchExprFieldBase(dict, false, true),
driver_
(
expressions::patchExprFieldBase::getFvPatch
(
dynamicCast<const facePointPatch>(this->patch())
),
dict
)
{
// Basic sanity
if (this->valueExpr_.empty())
{
FatalIOErrorInFunction(dict)
<< "The valueExpr was not defined!" << nl
<< exit(FatalIOError);
}
driver_.readDict(dict);
if (dict.found("value"))
{
Field<Type>::operator=
(
Field<Type>("value", dict, p.size())
);
}
else
{
WarningInFunction
<< "No value defined for "
<< this->internalField().name()
<< " on " << this->patch().name()
<< endl;
}
if (this->evalOnConstruct_)
{
// For potentialFoam or other solvers that don't evaluate
this->evaluate();
}
}
template<class Type>
Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
const exprValuePointPatchField<Type>& ptf,
const DimensionedField<Type, pointMesh>& iF
)
:
valuePointPatchField<Type>(ptf, iF),
expressions::patchExprFieldBase(ptf),
driver_
(
expressions::patchExprFieldBase::getFvPatch
(
dynamicCast<const facePointPatch>(this->patch())
),
ptf.driver_
)
{}
template<class Type>
Foam::exprValuePointPatchField<Type>::exprValuePointPatchField
(
const exprValuePointPatchField<Type>& ptf
)
:
valuePointPatchField<Type>(ptf),
expressions::patchExprFieldBase(ptf),
driver_
(
expressions::patchExprFieldBase::getFvPatch
(
dynamicCast<const facePointPatch>(this->patch())
),
ptf.driver_
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::exprValuePointPatchField<Type>::updateCoeffs()
{
if (debug)
{
InfoInFunction
<< "Value: " << this->valueExpr_ << nl
<< "Variables: ";
driver_.writeVariableStrings(Info) << endl;
}
if (this->updated())
{
return;
}
// Expression evaluation
{
driver_.clearVariables();
if (this->valueExpr_.empty())
{
(*this) == Zero;
}
else
{
Field<Type>::operator=
(
driver_.evaluate<Type>(this->valueExpr_, true)
);
}
}
valuePointPatchField<Type>::updateCoeffs();
}
template<class Type>
void Foam::exprValuePointPatchField<Type>::write(Ostream& os) const
{
valuePointPatchField<Type>::write(os);
expressions::patchExprFieldBase::write(os);
this->writeEntry("value",os);
// driver_.writeCommon(os,this->debug_ || debug);
}
// ************************************************************************* //

View File

@ -0,0 +1,175 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Original code Copyright (C) 2010-2018 Bernhard Gschaider
Copyright (C) 2019 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::exprValuePointPatchField
Description
A fixed value point boundary condition with expressions.
Usage
\table
Property | Description | Required | Default
value | fixed value | yes |
valueExpr | expression for fixed value | yes |
\endtable
SourceFiles
exprValuePointPatchField.C
\*---------------------------------------------------------------------------*/
#ifndef exprValuePointPatchField_H
#define exprValuePointPatchField_H
#include "valuePointPatchField.H"
#include "patchExprFieldBase.H"
#include "patchExprDriver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class exprValuePointPatchField Declaration
\*---------------------------------------------------------------------------*/
template<class Type>
class exprValuePointPatchField
:
public valuePointPatchField<Type>,
public expressions::patchExprFieldBase
{
protected:
// Protected Data
//- The expression driver
expressions::patchExpr::parseDriver driver_;
public:
//- Runtime type information
TypeName("exprValue");
// Constructors
//- Construct from patch and internal field
exprValuePointPatchField
(
const pointPatch&,
const DimensionedField<Type, pointMesh>&
);
//- Construct from patch, internal field and dictionary
exprValuePointPatchField
(
const pointPatch&,
const DimensionedField<Type, pointMesh>&,
const dictionary&
);
//- Construct by mapping given patchField<Type> onto a new patch
exprValuePointPatchField
(
const exprValuePointPatchField<Type>&,
const pointPatch&,
const DimensionedField<Type, pointMesh>&,
const pointPatchFieldMapper&
);
//- Construct as copy setting internal field reference
exprValuePointPatchField
(
const exprValuePointPatchField<Type>&,
const DimensionedField<Type, pointMesh>&
);
//- Construct as copy
exprValuePointPatchField
(
const exprValuePointPatchField<Type>&
);
//- Construct and return a clone
virtual autoPtr<pointPatchField<Type> > clone() const
{
return autoPtr<pointPatchField<Type>>
(
new exprValuePointPatchField<Type>
(
*this
)
);
}
//- Construct and return a clone setting internal field reference
virtual autoPtr<pointPatchField<Type>> clone
(
const DimensionedField<Type, pointMesh>& iF
) const
{
return autoPtr<pointPatchField<Type>>
(
new exprValuePointPatchField<Type>
(
*this,
iF
)
);
}
// Member Functions
//- Update the patch field
virtual void updateCoeffs();
//- Write
virtual void write(Ostream& os) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "exprValuePointPatchField.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "exprValuePointPatchFields.H"
#include "pointPatchFields.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
makePointPatchFields(exprValue);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
\*---------------------------------------------------------------------------*/
#ifndef exprValuePointPatchFields_H
#define exprValuePointPatchFields_H
#include "exprValuePointPatchField.H"
#include "fieldTypes.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
makePointPatchFieldTypedefs(exprValue);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,13 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
# Manually create ragel scanner and lemon parser header
prefix=patchExpr
"${WM_PROJECT_DIR:?}/wmake/scripts/makeParser" \
-prefix="$prefix" \
-scanner=Scanner.rl \
-parser=LemonParser.lyy-m4 \
"$@"
#------------------------------------------------------------------------------

View File

@ -0,0 +1,45 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "patchExprFwd.H"
#include "defineDebugSwitch.H"
// * * * * * * * * * * * * * * * * Globals * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
defineDebugSwitchWithName(patchExpr, "patchExpr", 0);
registerDebugSwitchWithName(patchExpr, patchExpr, "patchExpr");
} // End namespace expressions
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,188 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "patchExprDriver.H"
#include "patchExprScanner.H"
#include "error.H"
#include "fvPatch.H"
#include "fvMesh.H"
#include "className.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
namespace patchExpr
{
defineTypeNameAndDebug(parseDriver, 0);
addNamedToRunTimeSelectionTable
(
fvExprDriver,
parseDriver,
dictionary,
patch
);
addNamedToRunTimeSelectionTable
(
fvExprDriver,
parseDriver,
idName,
patch
);
} // End namespace patchExpr
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
static label getPatchID(const fvMesh& mesh, const word& patchName)
{
const auto& bMesh = mesh.boundaryMesh();
const label patchId = bMesh.findPatchID(patchName);
if (patchId < 0)
{
FatalErrorInFunction
<< "No patch " << patchName << " found in "
<< flatOutput(bMesh.names()) << nl
<< exit(FatalError);
}
return patchId;
}
static inline const fvPatch& findFvPatch
(
const fvMesh& mesh,
const word& patchName
)
{
return mesh.boundary()[getPatchID(mesh, patchName)];
}
} // End namespace Foam
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
const Foam::fvPatch& Foam::expressions::patchExpr::parseDriver::getFvPatch
(
const fvMesh& fvm,
const dictionary& dict
)
{
return findFvPatch
(
regionMesh(dict, fvm, true),
dict.get<word>("patch")
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::expressions::patchExpr::parseDriver::parseDriver(const fvPatch& p)
:
parsing::genericRagelLemonDriver(),
expressions::fvExprDriver(),
patch_(p)
{}
Foam::expressions::patchExpr::parseDriver::parseDriver
(
const fvPatch& p,
const dictionary& dict
)
:
parsing::genericRagelLemonDriver(),
expressions::fvExprDriver(dict),
patch_(p)
{}
Foam::expressions::patchExpr::parseDriver::parseDriver
(
const fvPatch& p,
const parseDriver& driver_
)
:
parsing::genericRagelLemonDriver(),
expressions::fvExprDriver(driver_),
patch_(p)
{}
Foam::expressions::patchExpr::parseDriver::parseDriver
(
const word& patchName,
const fvMesh& mesh
)
:
parseDriver(findFvPatch(mesh, patchName))
{}
Foam::expressions::patchExpr::parseDriver::parseDriver
(
const dictionary& dict,
const fvMesh& mesh
)
:
parseDriver(getFvPatch(mesh, dict), dict)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
unsigned Foam::expressions::patchExpr::parseDriver::parse
(
const std::string& expr,
size_t pos,
size_t len
)
{
scanner scan(this->debugScanner());
scan.process(expr, pos, len, *this);
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,305 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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::patchExpr::parseDriver
Description
Driver for patch expressions
In addition to the standard mathematical functions, operations and
logical and relational operations, the volume expression support the
following driver-specific functions:
Functions
\table
Function | Description | Number of arguments |
vol | The cell volumes | 0 |
pos | The face centres | 0 |
pts | The face points | 0 |
area | The face area magnitudes | 0 |
weightAverage| Area weighted average | 1 |
weightSum | Area weighted sum | 1 |
face | The face areaNormal vectors | 0 |
point | A point-field point value | 1 |
faceToPoint | Interpolate face values onto points | 1 |
pointToFace | Interpolate point values onto faces | 1 |
rand | Random field | 0/1 |
\endtable
SourceFiles
patchExprDriver.C
patchExprDriverFields.C
patchExprDriverTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef expressions_patchExprDriver_H
#define expressions_patchExprDriver_H
#include "patchExprFwd.H"
#include "fvExprDriver.H"
#include "Enum.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "pointFields.H"
#include "genericRagelLemonDriver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
namespace patchExpr
{
/*---------------------------------------------------------------------------*\
Class parseDriver Declaration
\*---------------------------------------------------------------------------*/
class parseDriver
:
public parsing::genericRagelLemonDriver,
public expressions::fvExprDriver
{
// Private Member Functions
static const fvPatch& getFvPatch
(
const fvMesh& fvm,
const dictionary& dict
);
protected:
// Protected Data
//- The referenced patch
const fvPatch& patch_;
// Protected Member Functions
// No copy copy construct
parseDriver(const parseDriver&) = delete;
// No copy assignment
void operator=(const parseDriver&) = delete;
public:
ClassName("patchExpr::driver");
// Constructors
//- Construct for specified patch
explicit parseDriver(const fvPatch& p);
//- Construct for specified patch with given dictionary
parseDriver(const fvPatch& p, const dictionary& dict);
//- Construct for specified patch with copy of driver context
parseDriver(const fvPatch& p, const parseDriver& driver_);
//- Construct with patchName for the given mesh
parseDriver(const word& patchName, const fvMesh& mesh);
//- Construct with "patch" (mandatory) and "region" (optional)
//- specified in dictionary
parseDriver(const dictionary& dict, const fvMesh& mesh);
//- Clone
virtual autoPtr<expressions::fvExprDriver> clone() const
{
return autoPtr<expressions::fvExprDriver>
(
new parseDriver(this->patch_, *this)
);
}
//- Destructor
virtual ~parseDriver() = default;
// Public Member Functions
//- The mesh we are attached to
virtual const fvMesh& mesh() const
{
return patch_.boundaryMesh().mesh();
}
//- The underlying field size for the expression
virtual label size() const
{
return patch_.patch().size();
}
//- The underlying point field size for the expression
virtual label pointSize() const
{
return patch_.patch().nPoints();
}
//- Field size associated with different geometric field types
inline label size(const FieldAssociation geoType) const;
// Evaluation
//- Perform parsing on (sub) string
using genericRagelLemonDriver::content;
//- Execute the parser
virtual unsigned parse
(
const std::string& expr,
size_t pos = 0,
size_t len = std::string::npos
);
// Field Information
// Fields
//- Set result
template<class Type>
void setResult(Field<Type>* ptr, bool pointVal = false)
{
result().setResult<Type>(ptr, pointVal);
}
//- Retrieve variable as field if possible.
// Test tmp for validity to determine success of the operation.
template<class Type>
tmp<Field<Type>> getVariableIfAvailable(const word& fldName) const;
//- Retrieve field (vol field)
template<class Type>
tmp<Field<Type>>
getVolField(const word& fldName);
//- Retrieve field (surface field)
template<class Type>
tmp<Field<Type>>
getSurfaceField(const word& fldName);
//- Retrieve field (point field)
template<class Type>
tmp<Field<Type>>
getPointField(const word& fldName);
//- Return named field
template<class Type>
tmp<Field<Type>> getField(const word& fldName);
// Field "shape" conversions
//- Interpolate face to point
template<class Type>
tmp<Field<Type>> faceToPoint(const Field<Type>& field) const;
//- Interpolate point to face values
template<class Type>
tmp<Field<Type>> pointToFace(const Field<Type>& field) const;
// Custom Field Functions
//- The area-weighted average of a field
template<class Type>
Type areaAverage(const Field<Type>& fld) const
{
return weightedAverage(patch_.magSf(), fld);
}
//- The area-weighted sum of a field
template<class Type>
Type areaSum(const Field<Type>& fld) const
{
return weightedSum(patch_.magSf(), fld);
}
//- The face area magnitudes [magSf] - (swak = area)
tmp<scalarField> field_faceArea() const;
//- The face centres - (swak = pos)
tmp<vectorField> field_faceCentre() const;
//- The face areas with their vector direction [Sf] - (swak = face)
tmp<vectorField> field_areaNormal() const;
//- The patch point locations - (swak = pts)
tmp<vectorField> field_pointField() const;
//- A uniform random field
tmp<scalarField> field_rand(label seed=0, bool gaussian=false) const;
//- A Gaussian random field
tmp<scalarField> field_randGaussian(label seed=0) const
{
return field_rand(seed, true);
}
};
// Template specializations
//- Retrieve field (surface field: bool)
template<>
tmp<Field<bool>> parseDriver::getSurfaceField<bool>(const word& fldName);
//- Retrieve field (point field: bool)
template<>
tmp<Field<bool>> parseDriver::getPointField<bool>(const word& fldName);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace patchExpr
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "patchExprDriverI.H"
#ifdef NoRepository
#include "patchExprDriverTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,100 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "patchExprDriver.H"
#include "fvPatch.H"
#include "error.H"
// * * * * * * * * * * * * Template Specializations * * * * * * * * * * * * //
template<>
Foam::tmp<Foam::Field<bool>>
Foam::expressions::patchExpr::parseDriver::getSurfaceField<bool>
(
const word& name
)
{
return getVariable<bool>(name, this->size());
}
template<>
Foam::tmp<Foam::Field<bool>>
Foam::expressions::patchExpr::parseDriver::getPointField<bool>
(
const word& name
)
{
return getVariable<bool>(name, this->pointSize());
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::scalarField>
Foam::expressions::patchExpr::parseDriver::field_faceArea() const
{
return patch_.magSf();
}
Foam::tmp<Foam::vectorField>
Foam::expressions::patchExpr::parseDriver::field_faceCentre() const
{
return patch_.Cf();
}
Foam::tmp<Foam::vectorField>
Foam::expressions::patchExpr::parseDriver::field_areaNormal() const
{
return patch_.Sf();
}
Foam::tmp<Foam::vectorField>
Foam::expressions::patchExpr::parseDriver::field_pointField() const
{
return patch_.patch().localPoints();
}
Foam::tmp<Foam::scalarField>
Foam::expressions::patchExpr::parseDriver::field_rand
(
label seed,
bool gaussian
) const
{
auto tresult = tmp<scalarField>::New(this->size());
fill_random(tresult.ref(), seed, gaussian);
return tresult;
}
// ************************************************************************* //

View File

@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 Foam::label Foam::expressions::patchExpr::parseDriver::size
(
const FieldAssociation geoType
) const
{
switch (geoType)
{
case FieldAssociation::POINT_DATA :
return patch_.patch().nPoints();
break;
case FieldAssociation::SURFACE_DATA :
return patch_.patch().size();
break;
default:
break;
}
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,228 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "primitivePatchInterpolation.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::patchExpr::parseDriver::getVariableIfAvailable
(
const word& name
) const
{
bool isPointVal = false;
bool isUniformVal = false;
tmp<Field<Type>> tfield;
if (hasVariable(name) && variable(name).isType<Type>())
{
const expressions::exprResult& var = variable(name);
isPointVal = var.isPointValue();
isUniformVal = var.isUniform();
tfield = var.cref<Type>().clone();
}
else if (isGlobalVariable<Type>(name, false))
{
const expressions::exprResult& var = lookupGlobal(name);
isUniformVal = var.isUniform();
tfield = var.cref<Type>().clone();
}
if (tfield.valid())
{
const label fldLen = tfield().size();
const label len = (isPointVal ? this->pointSize() : this->size());
if (returnReduce((fldLen == len), andOp<bool>()))
{
return tfield;
}
if (!isUniformVal)
{
WarningInFunction
<< "Variable " << name
<< " does not fit the size and is not a uniform value." << nl
<< "Using average value" << endl;
}
return tmp<Field<Type>>::New(this->size(), gAverage(tfield));
}
return tfield;
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::patchExpr::parseDriver::getVolField(const word& name)
{
return getField<Type>(name);
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::patchExpr::parseDriver::getSurfaceField(const word& name)
{
return getField<Type>(name);
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::patchExpr::parseDriver::getPointField(const word& name)
{
return getField<Type>(name);
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::patchExpr::parseDriver::getField(const word& name)
{
tmp<Field<Type>> tfield = getVariableIfAvailable<Type>(name);
if (tfield.valid())
{
return tfield;
}
typedef GeometricField<Type, fvPatchField, volMesh> vfieldType;
typedef GeometricField<Type, fvsPatchField, surfaceMesh> sfieldType;
typedef GeometricField<Type, pointPatchField, pointMesh> pfieldType;
const objectRegistry& obr = this->mesh().thisDb();
const vfieldType* vfield = obr.findObject<vfieldType>(name);
const sfieldType* sfield = obr.findObject<sfieldType>(name);
const pfieldType* pfield = obr.findObject<pfieldType>(name);
// Local, temporary storage
tmp<vfieldType> t_vfield;
tmp<sfieldType> t_sfield;
tmp<pfieldType> t_pfield;
if (searchFiles() && !vfield && !sfield && !pfield)
{
const word fldType = this->getTypeOfField(name);
if (fldType == vfieldType::typeName)
{
t_vfield = this->readAndRegister<vfieldType>(name, mesh());
vfield = t_vfield.get();
}
else if (fldType == sfieldType::typeName)
{
t_sfield = this->readAndRegister<sfieldType>(name, mesh());
sfield = t_sfield.get();
}
else if (fldType == pfieldType::typeName)
{
t_pfield = this->readAndRegister<pfieldType>
(
name,
pointMesh::New(mesh())
);
pfield = t_pfield.get();
}
}
const label patchIndex = patch_.index();
if (vfield)
{
return tmp<Field<Type>>::New
(
vfield->boundaryField()[patchIndex]
);
}
if (sfield)
{
return tmp<Field<Type>>::New
(
sfield->boundaryField()[patchIndex]
);
}
if (pfield)
{
return pfield->boundaryField()[patchIndex].patchInternalField();
}
FatalErrorInFunction
<< "No field '" << name << "' of type "
<< pTraits<Type>::typeName << nl << nl
<< vfieldType::typeName << " Fields: "
<< flatOutput(obr.sortedNames<vfieldType>()) << nl
<< sfieldType::typeName << " Fields: "
<< flatOutput(obr.sortedNames<sfieldType>()) << nl
<< pfieldType::typeName << " Fields: "
<< flatOutput(obr.sortedNames<pfieldType>()) << nl
<< exit(FatalError);
return tmp<Field<Type>>::New();
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::patchExpr::parseDriver::faceToPoint
(
const Field<Type>& field
) const
{
primitivePatchInterpolation interp(patch_.patch());
return interp.pointToFaceInterpolate(field);
}
template<class Type>
Foam::tmp<Foam::Field<Type>>
Foam::expressions::patchExpr::parseDriver::pointToFace
(
const Field<Type>& field
) const
{
primitivePatchInterpolation interp(patch_.patch());
return interp.faceToPointInterpolate(field);
}
// ************************************************************************* //

View File

@ -0,0 +1,84 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Namespace
Foam::expressions::patchExpr
Description
Namespace for patch expressions parsing and evaluation
\*---------------------------------------------------------------------------*/
#ifndef expressions_patchExprFwd_H
#define expressions_patchExprFwd_H
namespace Foam
{
namespace expressions
{
namespace patchExpr
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward Declarations
class parser;
class scanner;
class parseDriver;
union scanToken;
//- Static debugging option
extern int debug;
//- The field association for patch expressions (mutually exclusive)
enum FieldAssociation : unsigned char
{
NO_DATA = 0, //!< No data
POINT_DATA = 1, //!< Point data
SURFACE_DATA = 2 //!< Surface data
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace patchExpr
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Typedef for patchExpr parseDriver
typedef patchExpr::parseDriver patchExprDriver;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,110 @@
#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_TIME 28
#define TOK_SCALAR_ID 29
#define TOK_SSCALAR_ID 30
#define TOK_MIN 31
#define TOK_COMMA 32
#define TOK_MAX 33
#define TOK_SUM 34
#define TOK_AVERAGE 35
#define TOK_EXP 36
#define TOK_LOG 37
#define TOK_LOG10 38
#define TOK_SQR 39
#define TOK_SQRT 40
#define TOK_CBRT 41
#define TOK_SIN 42
#define TOK_COS 43
#define TOK_TAN 44
#define TOK_ASIN 45
#define TOK_ACOS 46
#define TOK_ATAN 47
#define TOK_SINH 48
#define TOK_COSH 49
#define TOK_TANH 50
#define TOK_POW 51
#define TOK_ATAN2 52
#define TOK_POS 53
#define TOK_NEG 54
#define TOK_POS0 55
#define TOK_NEG0 56
#define TOK_SIGN 57
#define TOK_FLOOR 58
#define TOK_CEIL 59
#define TOK_ROUND 60
#define TOK_HYPOT 61
#define TOK_RAND 62
#define TOK_VECTOR_ID 63
#define TOK_SVECTOR_ID 64
#define TOK_SPH_TENSOR_ID 65
#define TOK_SSPH_TENSOR_ID 66
#define TOK_SYM_TENSOR_ID 67
#define TOK_SSYM_TENSOR_ID 68
#define TOK_UNIT_TENSOR 69
#define TOK_TENSOR_ID 70
#define TOK_STENSOR_ID 71
#define TOK_LTRUE 72
#define TOK_LFALSE 73
#define TOK_BOOL 74
#define TOK_SBOOL_ID 75
#define TOK_FACE_AREA 76
#define TOK_FACE_EXPR 77
#define TOK_WEIGHT_AVERAGE 78
#define TOK_WEIGHT_SUM 79
#define TOK_POINT_EXPR 80
#define TOK_PSCALAR_ID 81
#define TOK_PVECTOR_ID 82
#define TOK_PSPH_TENSOR_ID 83
#define TOK_PSYM_TENSOR_ID 84
#define TOK_PTENSOR_ID 85
#define TOK_PBOOL_ID 86
#define TOK_POINTS 87
#define TOK_MAG 88
#define TOK_MAGSQR 89
#define TOK_VECTOR 90
#define TOK_TENSOR 91
#define TOK_SYM_TENSOR 92
#define TOK_SPH_TENSOR 93
#define TOK_CMPT_X 94
#define TOK_CMPT_Y 95
#define TOK_CMPT_Z 96
#define TOK_CMPT_XX 97
#define TOK_CMPT_XY 98
#define TOK_CMPT_XZ 99
#define TOK_CMPT_YX 100
#define TOK_CMPT_YY 101
#define TOK_CMPT_YZ 102
#define TOK_CMPT_ZX 103
#define TOK_CMPT_ZY 104
#define TOK_CMPT_ZZ 105
#define TOK_CMPT_II 106
#define TOK_TRANSPOSE 107
#define TOK_DIAG 108
#define TOK_POINT_TO_FACE 109
#define TOK_FACE_TO_POINT 110

View File

@ -0,0 +1,565 @@
%include
{
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Description
Lemon grammar for patch expressions.
https://www.sqlite.org/src/doc/trunk/doc/lemon.html
See detailed notes in the field expression parser.
\*---------------------------------------------------------------------------*/
} // %include
/*
* include[patchExprLemonParserMacros.m4]
*include(`patchExprLemonParserMacros.m4')dnl
!done in a comment since many editors have issues matching m4 quotes!
*/
%include
{
#include "patchExprDriver.H"
#include "patchExprParser.H"
#include "patchExprScanner.H"
#include "unitConversion.H"
#include "error.H"
#include "volFields.H"
#include "exprOps.H"
#include "exprDriverOps.H"
#include "GeometricFieldOps.H"
// Enable ParseTrace
#undef NDEBUG
compiler_pragmas()
// Local Functions
tmp_management()
} // %include
// ------------------------------------------------------------------------- //
%namespace {}
// Use extra argument for the return value
%extra_context { Foam::expressions::patchExpr::parseDriver* driver }
%parse_failure { driver->reportFatal("Parse failure, giving up..."); }
%syntax_error { driver->reportFatal("Syntax error"); }
%token_prefix TOK_
// Terminals
%token_type {Foam::expressions::patchExpr::scanToken*}
// Non-terminals
%type ivalue { Foam::label }
%type svalue { Foam::scalar }
%type ident { Foam::word* }
// Face fields
declare_field(lfield, Foam::boolField, bool, newField, getSurfaceField)
declare_field(sfield, Foam::scalarField, Foam::scalar, newField, getField)
declare_field(vfield, Foam::vectorField, Foam::vector, newField, getField)
declare_field(hfield, Foam::sphericalTensorField, Foam::sphericalTensor, newField, getField)
declare_field(yfield, Foam::symmTensorField, Foam::symmTensor, newField, getField)
declare_field(tfield, Foam::tensorField, Foam::tensor, newField, getField)
// Point fields
declare_field(plfield, Foam::boolField, bool, newPointField, getPointField)
declare_field(psfield, Foam::scalarField, Foam::scalar, newPointField, getPointField)
declare_field(pvfield, Foam::vectorField, Foam::vector, newPointField, getPointField)
declare_field(phfield, Foam::sphericalTensorField, Foam::sphericalTensor, newPointField, getPointField)
declare_field(pyfield, Foam::symmTensorField, Foam::symmTensor, newPointField, getPointField)
declare_field(ptfield, Foam::tensorField, Foam::tensor, newPointField, getPointField)
// For each rule action with code, destruction must be done by that code block
// Lemon does not generate a destructor for that.
// So do not use Lemon destructors for anything.
operator_precedence()
%start_symbol evaluate
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*\
* Productions (scalar)
\*---------------------------------------------------------------------------*/
svalue (lhs) ::= NUMBER (a) . { lhs = (a)->svalue; } // From 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(); }
svalue (lhs) ::= RAD_TO_DEG LPAREN RPAREN . { lhs = Foam::radToDeg(); }
svalue (lhs) ::= TIME LPAREN RPAREN . { lhs = driver->timeValue(); }
/* * * * * * * * * * * * * * * * * Face Fields * * * * * * * * * * * * * * * *\
dnl
define([_logic_], [lfield])dnl
define([_scalar_], [sfield])dnl
define([_vector_], [vfield])dnl
define([_sphTensor_], [hfield])dnl
define([_symTensor_], [yfield])dnl
define([_tensor_], [tfield])dnl
dnl
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*---------------------------------------------------------------------------*\
* Productions (scalarField)
dnl
define([_target_], [sfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, svalue)
rule_get_field(_target_, SCALAR_ID)
rule_get_field(_target_, SSCALAR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
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>())
// Non-standard but works directly for scalarField
rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
// Other functions
_target_ (lhs) ::= RAND LPAREN RPAREN.
{
lhs = driver->field_rand().ptr();
}
_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();
}
/*---------------------------------------------------------------------------*\
* Productions (vectorField)
dnl
define([_target_], [vfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, VECTOR_ID)
rule_get_field(_target_, SVECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
/*---------------------------------------------------------------------------*\
* Productions (sphericalTensorField)
dnl
define([_target_], [hfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, SPH_TENSOR_ID)
rule_get_field(_target_, SSPH_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_sphTensor_operations()
rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (symmTensorField)
dnl
define([_target_], [yfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, SYM_TENSOR_ID)
rule_get_field(_target_, SSYM_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_symTensor_operations()
rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (tensorField)
dnl
define([_target_], [tfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
tfield (lhs) ::= UNIT_TENSOR . { lhs = _new_tfield(Foam::tensor::I); }
rule_get_field(_target_, TENSOR_ID)
rule_get_field(_target_, STENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_tensor_operations()
rules_tensor_functions()
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*\
* Logic field productions (boolField)
dnl
define([_target_], [lfield])dnl
define([_value_type_], [bool])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
_logic_ (lhs) ::= LTRUE . { lhs = _new_lfield(_logic_true_); }
_logic_ (lhs) ::= LFALSE . { lhs = _new_lfield(_logic_false_); }
rule_cast_logical(_target_, _target_)
rule_cast_logical(_target_, _scalar_, Foam::scalar)
dnl/* Handling of named logic fields not really tested (disable in scanner) */
rule_get_field(_target_, SBOOL_ID)
rules_logical_operations(_logic_, _value_type_)
/*---------------------------------------------------------------------------*\
* General Surface-related productions
\*---------------------------------------------------------------------------*/
rules_driver_surface_functions()
/* * * * * * * * * * * * * * * * Point Fields * * * * * * * * * * * * * * * *\
dnl
define([_logic_], [plfield])dnl
define([_scalar_], [psfield])dnl
define([_vector_], [pvfield])dnl
define([_sphTensor_], [phfield])dnl
define([_symTensor_], [pyfield])dnl
define([_tensor_], [ptfield])dnl
dnl
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*---------------------------------------------------------------------------*\
* Productions (point scalarField)
dnl
define([_target_], [psfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
rule_field_from_value(_target_, svalue, POINT_EXPR)
rule_get_field(_target_, PSCALAR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
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>())
// Non-standard but works directly for scalarField
rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
/*---------------------------------------------------------------------------*\
* Productions (point vectorField)
dnl
define([_target_], [pvfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
rule_get_field(_target_, PVECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
/*---------------------------------------------------------------------------*\
* Productions (point sphericalTensorField)
dnl
define([_target_], [phfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
rule_get_field(_target_, PSPH_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_sphTensor_operations()
rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (point symmTensorField)
dnl
define([_target_], [pyfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
rule_get_field(_target_, PSYM_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_symTensor_operations()
rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (point tensorField)
dnl
define([_target_], [ptfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
rule_get_field(_target_, PTENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_tensor_operations()
rules_tensor_functions()
/*---------------------------------------------------------------------------*\
* Logic field productions (point boolField)
dnl
define([_target_], [plfield])dnl
define([_value_type_], [bool])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
_logic_ (lhs) ::= POINT_EXPR LPAREN LTRUE RPAREN . { lhs = _new_plfield(_logic_true_); }
_logic_ (lhs) ::= POINT_EXPR LPAREN LFALSE RPAREN . { lhs = _new_plfield(_logic_false_); }
rule_cast_logical(_target_, _target_)
rule_cast_logical(_target_, _scalar_, Foam::scalar)
dnl/* Handling of named logic fields not really tested (disable in scanner) */
rule_get_field(_target_, PBOOL_ID)
rules_logical_operations(_logic_, _value_type_)
/*---------------------------------------------------------------------------*\
* General Point-related productions
\*---------------------------------------------------------------------------*/
rules_driver_point_functions()
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*\
* Face field composition
\*---------------------------------------------------------------------------*/
rule_mag_logical(sfield, lfield)
rules_mag_functions(sfield, sfield)
rules_mag_functions(sfield, vfield)
rules_mag_functions(sfield, tfield)
rules_mag_functions(sfield, yfield)
rules_mag_functions(sfield, hfield)
rule_vector_zip(vfield, sfield, VECTOR)
rule_tensor_zip(tfield, sfield, TENSOR)
rule_symTensor_zip(yfield, sfield, SYM_TENSOR)
rule_sphTensor_zip(hfield, sfield, SPH_TENSOR)
rule_vector_components(sfield, vfield)
rule_tensor_components(sfield, tfield)
rule_symTensor_components(sfield, yfield)
rule_sphTensor_components(sfield, hfield)
rule_tensor_transpose(tfield)
rule_symTensor_transpose(yfield)
rule_sphTensor_transpose(hfield)
rule_tensor_unzipDiag(vfield, yfield)
rule_tensor_unzipAll(vfield, tfield)
rule_pointToFace(sfield, psfield)
rule_pointToFace(vfield, pvfield)
rule_pointToFace(tfield, ptfield)
rule_pointToFace(yfield, pyfield)
rule_pointToFace(hfield, phfield)
/*---------------------------------------------------------------------------*\
* Point field composition
\*---------------------------------------------------------------------------*/
rule_mag_logical(psfield, plfield)
rules_mag_functions(psfield, psfield)
rules_mag_functions(psfield, pvfield)
rules_mag_functions(psfield, ptfield)
rules_mag_functions(psfield, pyfield)
rules_mag_functions(psfield, phfield)
rule_vector_zip(pvfield, psfield, VECTOR)
rule_tensor_zip(ptfield, psfield, TENSOR)
rule_symTensor_zip(pyfield, psfield, SYM_TENSOR)
rule_sphTensor_zip(phfield, psfield, SPH_TENSOR)
rule_vector_components(psfield, pvfield)
rule_tensor_components(psfield, ptfield)
rule_symTensor_components(psfield, pyfield)
rule_sphTensor_components(psfield, phfield)
rule_tensor_transpose(ptfield)
rule_symTensor_transpose(pyfield)
rule_sphTensor_transpose(phfield)
rule_tensor_unzipDiag(pvfield, pyfield)
rule_tensor_unzipAll(pvfield, ptfield)
rule_faceToPoint(psfield, sfield)
rule_faceToPoint(pvfield, vfield)
rule_faceToPoint(ptfield, tfield)
rule_faceToPoint(pyfield, yfield)
rule_faceToPoint(phfield, hfield)
// ************************************************************************* //
dnl/* Standard m4 quoting
changequote([`],['])dnl
dnl*/
%code
{
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::expressions::patchExpr::parser::stop()
{
if (lemon_)
{
ParseFree(lemon_, ::operator delete);
#ifndef NDEBUG
ParseTrace(nullptr, nullptr);
#endif
lemon_ = nullptr;
}
}
void Foam::expressions::patchExpr::parser::start(parseDriver& driver_)
{
this->stop();
lemon_ = ParseAlloc(::operator new, &driver_);
if (debug || driver_.debugParser())
{
#ifndef NDEBUG
ParseTrace(stderr, const_cast<char*>(prompt_));
#endif
}
}
void Foam::expressions::patchExpr::parser::parse
(
int tokenId,
scanToken* tokenVal
)
{
Parse(lemon_, tokenId, tokenVal);
}
Foam::word Foam::expressions::patchExpr::parser::nameOfToken
(
int tokenId
) const
{
#ifndef NDEBUG
if
(
tokenId > 0
&& unsigned(tokenId) < (sizeof(yyTokenName) / sizeof(char*))
)
{
return yyTokenName[tokenId];
}
return "<invalid>";
#else
return word();
#endif
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End of %code
// ************************************************************************* //

View File

@ -0,0 +1,109 @@
divert(-1)dnl
#-----------------------------------*- m4 -*-----------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration |
# \\ / A nd | www.openfoam.com
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, licensed under GNU General Public License
# <http://www.gnu.org/licenses/>.
#
# Description
# Driver-specific m4/lemon macros for patch expressions.
#
#------------------------------------------------------------------------------
include(`m4/lemon/base-setup.m4')dnl
include([m4/lemon/operator-precedence.m4])dnl
dnl
include([m4/lemon/rules-standard.m4])dnl
include([m4/lemon/rules-operations.m4])dnl
include([m4/lemon/rules-functions.m4])dnl
include([m4/lemon/rules-components.m4])dnl
include([m4/lemon/rules-fields-components.m4])dnl
include([m4/lemon/rules-scalar-logic.m4])dnl
dnl
divert(-1)dnl
use_bool_logic()dnl # Use boolField directly
#-------------------------------------------------------------------------------
# Driver rules
#-------------------------------------------------------------------------------
define([rules_driver_surface_functions],
[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
dnl
rule_driver_inplace_unary(_scalar_, WEIGHT_AVERAGE, areaAverage)dnl
rule_driver_inplace_unary(_vector_, WEIGHT_AVERAGE, areaAverage)dnl
rule_driver_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, areaAverage)dnl
rule_driver_inplace_unary(_symTensor_, WEIGHT_AVERAGE, areaAverage)dnl
rule_driver_inplace_unary(_tensor_, WEIGHT_AVERAGE, areaAverage)dnl
dnl
rule_driver_inplace_unary(_scalar_, WEIGHT_SUM, areaSum)dnl
rule_driver_inplace_unary(_vector_, WEIGHT_SUM, areaSum)dnl
rule_driver_inplace_unary(_sphTensor_, WEIGHT_SUM, areaSum)dnl
rule_driver_inplace_unary(_symTensor_, WEIGHT_SUM, areaSum)dnl
rule_driver_inplace_unary(_tensor_, WEIGHT_SUM, areaSum)dnl
dnl
])
define([rules_driver_point_functions],
[dnl
rule_driver_nullary(_vector_, POINTS, field_pointField)dnl
dnl
dnl NB use non-driver versions for points - ie, unweighted
dnl
rule_inplace_unary(_scalar_, WEIGHT_AVERAGE, Foam::gAverage)dnl
rule_inplace_unary(_vector_, WEIGHT_AVERAGE, Foam::gAverage)dnl
rule_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl
rule_inplace_unary(_symTensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl
rule_inplace_unary(_tensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl
dnl
rule_inplace_unary(_scalar_, WEIGHT_SUM, Foam::gSum)dnl
rule_inplace_unary(_vector_, WEIGHT_SUM, Foam::gSum)dnl
rule_inplace_unary(_sphTensor_, WEIGHT_SUM, Foam::gSum)dnl
rule_inplace_unary(_symTensor_, WEIGHT_SUM, Foam::gSum)dnl
rule_inplace_unary(_tensor_, WEIGHT_SUM, Foam::gSum)dnl
dnl
])
#------------------------------------------------------------------------------
# rule_faceToPoint(out, in)
# rule_pointToFace(out, in)
#
# Description
# Production rules for driver faceToPoint, pointToFace,
# methods
#------------------------------------------------------------------------------
define([rule_faceToPoint],
[rule_driver_unary($1, $2, FACE_TO_POINT, faceToPoint)])
define([rule_pointToFace],
[rule_driver_unary($1, $2, POINT_TO_FACE, pointToFace)])
#------------------------------------------------------------------------------
# Standard rules for fields: declaration, new/get, driver functions etc.
include([m4/lemon/rules-fields.m4])dnl
divert(-1)dnl
#------------------------------------------------------------------------------
# Additional safety measures
undefine([substr])dnl # Avoid collision with C/C++ naming
#------------------------------------------------------------------------------
divert(0)dnl

View File

@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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::patchExpr::parser
Description
Lemon parser interface for patch expressions grammar
\*---------------------------------------------------------------------------*/
#ifndef expressions_patchExprParser_H
#define expressions_patchExprParser_H
#include "patchExprFwd.H"
namespace Foam
{
namespace expressions
{
namespace patchExpr
{
/*---------------------------------------------------------------------------*\
Class parser Declaration
\*---------------------------------------------------------------------------*/
class parser
{
// Private Data
//- Prompt for parser tracing
static constexpr const char* const prompt_ = "patchExpr:";
//- The lemon parser (demand-driven)
void* lemon_;
public:
//- Local object debugging
int debug;
// Constructors
//- Construct null
parser() : lemon_(nullptr), debug(patchExpr::debug) {}
//- Destructor, deletes parser backend
~parser()
{
stop();
}
// Member Functions
//- Start parsing, with the given driver context
void start(parseDriver& driver_);
//- Stop parsing, freeing the allocated parser
void stop();
//- Push token/value to parser
void parse(int tokenId, scanToken* tokenVal);
//- Return the text name corresponding to the tokenId
word nameOfToken(int tokenId) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace patchExpr
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,162 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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::patchExpr::scanner
Description
Ragel lexer/scanner interface for patch expressions.
Note
Ragel code generated with the ./createCode script.
\*---------------------------------------------------------------------------*/
#ifndef expressions_patchExprScanner_H
#define expressions_patchExprScanner_H
#include "patchExprFwd.H"
#include "scalar.H"
namespace Foam
{
namespace expressions
{
namespace patchExpr
{
/*---------------------------------------------------------------------------*\
Class scanToken Declaration
\*---------------------------------------------------------------------------*/
union scanToken
{
Foam::label ivalue;
Foam::scalar svalue;
Foam::word* name;
//- Null construct, bit-wise zero for union content
scanToken() : ivalue(0) {}
};
/*---------------------------------------------------------------------------*\
Class scanner Declaration
\*---------------------------------------------------------------------------*/
class scanner
{
// Private Data
//- Wrapped lemon parser
parser* parser_;
// Ragel code state, action
int cs, act;
// Private Member Functions
//- Dispatch .method to parser (if known) or Fatal
bool dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
) const;
//- Dispatch identifier to parser (if possible) or Fatal
bool dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
) const;
public:
//- Local debugging
int debug;
// Constructors
//- Construct null, optionally setting debugging
explicit scanner(bool withDebug = false)
:
parser_(nullptr),
debug(patchExpr::debug)
{
if (withDebug)
{
debug |= 4;
}
}
//- Destructor, deletes parser
~scanner();
// Member Functions
//- Evaluate sub-string
bool process
(
const std::string& str, size_t pos, size_t len,
parseDriver& driver_
);
//- Evaluate sub-string
bool process
(
const std::string& str, size_t pos,
parseDriver& driver_
)
{
return process(str, pos, std::string::npos, driver_);
}
//- Evaluate string
bool process(const std::string& str, parseDriver& driver_)
{
return process(str, 0, std::string::npos, driver_);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace patchExpr
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,664 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Description
Ragel lexer interface for lemon grammar for patch expressions
\*---------------------------------------------------------------------------*/
#include "patchExprScanner.H"
#include "patchExprDriver.H"
#include "patchExprLemonParser.h"
#include "patchExprParser.H"
#include "Enum.H"
#include "macros.H"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wold-style-cast"
// Debugging to stderr
#undef DebugInfo
#define DebugInfo if (debug) InfoErr
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
//- Paste token prefix
#define TOKEN_OF(T) TOK_##T
//- An {int, c_str} enum pairing
#define TOKEN_PAIR(Name,T) { TOKEN_OF(T), Name }
#undef HAS_LOOKBEHIND_TOKENS
// Special handling of predefined method types. Eg, .x(), .y(), ...
static const Enum<int> fieldMethodEnums
({
TOKEN_PAIR("x", CMPT_X),
TOKEN_PAIR("y", CMPT_Y),
TOKEN_PAIR("z", CMPT_Z),
TOKEN_PAIR("xx", CMPT_XX),
TOKEN_PAIR("xy", CMPT_XY),
TOKEN_PAIR("xz", CMPT_XZ),
TOKEN_PAIR("yx", CMPT_YX),
TOKEN_PAIR("yy", CMPT_YY),
TOKEN_PAIR("yz", CMPT_YZ),
TOKEN_PAIR("zx", CMPT_ZX),
TOKEN_PAIR("zy", CMPT_ZY),
TOKEN_PAIR("zz", CMPT_ZZ),
TOKEN_PAIR("ii", CMPT_II),
TOKEN_PAIR("diag", DIAG), /* tensors only */
TOKEN_PAIR("T", TRANSPOSE), /* tensors only */
});
// Known field-token types
static const Enum<int> fieldTokenEnums
({
#ifdef TOK_SCALAR_ID
TOKEN_PAIR(volScalarField::typeName.c_str(), SCALAR_ID),
TOKEN_PAIR(volVectorField::typeName.c_str(), VECTOR_ID),
TOKEN_PAIR(volTensorField::typeName.c_str(), TENSOR_ID),
TOKEN_PAIR(volSymmTensorField::typeName.c_str(), SYM_TENSOR_ID),
TOKEN_PAIR(volSphericalTensorField::typeName.c_str(), SPH_TENSOR_ID),
#else
#error TOK_SCALAR_ID not defined
#endif
#ifdef TOK_SSCALAR_ID
TOKEN_PAIR(surfaceScalarField::typeName.c_str(), SSCALAR_ID),
TOKEN_PAIR(surfaceVectorField::typeName.c_str(), SVECTOR_ID),
TOKEN_PAIR(surfaceTensorField::typeName.c_str(), STENSOR_ID),
TOKEN_PAIR(surfaceSymmTensorField::typeName.c_str(), SSYM_TENSOR_ID),
TOKEN_PAIR(surfaceSphericalTensorField::typeName.c_str(), SSPH_TENSOR_ID),
#else
#error TOK_SSCALAR_ID not defined
#endif
#ifdef TOK_PSCALAR_ID
TOKEN_PAIR(pointScalarField::typeName.c_str(), PSCALAR_ID),
TOKEN_PAIR(pointVectorField::typeName.c_str(), PVECTOR_ID),
TOKEN_PAIR(pointTensorField::typeName.c_str(), PTENSOR_ID),
TOKEN_PAIR(pointSymmTensorField::typeName.c_str(), PSYM_TENSOR_ID),
TOKEN_PAIR(pointSphericalTensorField::typeName.c_str(), PSPH_TENSOR_ID),
#else
#warning TOK_PSCALAR_ID not defined
#endif
});
// Simple compile-time function name declarations.
// Useful for handling driver-specific dispatching, or functions that
// are not universally available.
static const Enum<int> funcTokenEnums
({
#ifdef TOK_FLOOR
TOKEN_PAIR("floor", FLOOR),
TOKEN_PAIR("ceil", CEIL),
TOKEN_PAIR("round", ROUND),
#endif
#ifdef TOK_HYPOT /* Can use hypot? */
TOKEN_PAIR("hypot", HYPOT),
#endif
// Already parsed as function: TOKEN_PAIR("pos", FACE_CENTRE),
TOKEN_PAIR("point", POINT_EXPR), // Point value
TOKEN_PAIR("face", FACE_EXPR), // Face areaNormal
TOKEN_PAIR("faceToPoint", FACE_TO_POINT),
TOKEN_PAIR("pointToFace", POINT_TO_FACE),
TOKEN_PAIR("area", FACE_AREA),
TOKEN_PAIR("pts", POINTS),
});
} // End namespace Foam
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Classifying token type based on an identifier name is indeed ugly.
//
// 1)
// Handle special cases (eg, cellSet,...) first that have been tagged
// as expected content with the stashed "look-behind" token.
// Handle not-found errors here directly.
//
// 2)
// Fallback to determining which field-type (volScalarField etc) the name
// corresponds to.
// Handle not-found errors by return -1.
//
static int driverTokenType
(
const expressions::patchExpr::parseDriver& driver_,
const word& ident
)
{
#if 0
// Get stashed "look-behind" to decide what type of identifier we expect
const int lookBehind = driver_.resetStashedTokenId();
if (lookBehind && lookBehindTokenEnums.found(lookBehind))
{
bool good = false;
switch (lookBehind)
{
case TOK_CSET : good = driver_.isCellSet(ident); break;
case TOK_FSET : good = driver_.isFaceSet(ident); break;
case TOK_PSET : good = driver_.isPointSet(ident); break;
case TOK_CZONE : good = driver_.isCellZone(ident); break;
case TOK_FZONE : good = driver_.isFaceZone(ident); break;
case TOK_PZONE : good = driver_.isPointZone(ident); break;
}
if (good)
{
return TOK_IDENTIFIER;
}
// Fatal
driver_.reportFatal
(
"Error no " + lookBehindTokenEnums.get(lookBehind) + ": " + ident
);
return -2; // Extra safety
}
#endif
// Face variables
#ifdef TOK_SSCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(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);
}
#endif
// Point variables
#ifdef TOK_PSCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(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);
}
#endif
#undef checkFieldToken
// Check registered fields and/or disk-files
{
const word fieldType(driver_.getFieldClassName(ident));
int tokType = fieldTokenEnums.get(fieldType, -1);
if (tokType > 0)
{
return tokType;
}
}
return -1;
}
} // End anonymous namespace
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Ragel machine definition
// Ragel variables (p, pe, eof, cs, top, stack, ts, te, act) defined later...
//
// Can use 'variable p xxx;' etc to change these names
#define EMIT_TOKEN(T) \
driver_.parsePosition() = (ts-buf); \
DebugInfo<< STRINGIFY(T) << ": " << driver_.parsePosition() << nl; \
parser_->parse(TOKEN_OF(T), nullptr); \
driver_.parsePosition() = (p-buf);
%%{
machine patchExpr;
write data;
action 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))
{
parser_->parse(TOKEN_OF(NUMBER), &scanTok);
}
else
{
driver_.reportFatal
(
"Error parsing number: " + std::string(ts, te-ts)
);
}
driver_.parsePosition() = (p-buf);
}
action emit_ident {
driver_.parsePosition() = (ts-buf);
dispatch_ident(driver_, scanTok, 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));
driver_.parsePosition() = (p-buf);
}
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ;
ident = ((alpha|'_') . ((alnum|[._])**)) ;
dquoted = '"' [^\"]+ '"' ;
squoted = "'" [^\']+ "'" ;
## The scanner
main := |*
space*;
number => emit_number;
## operators
'!' =>{ EMIT_TOKEN(NOT); };
'%' =>{ EMIT_TOKEN(PERCENT); };
'(' =>{ EMIT_TOKEN(LPAREN); };
')' =>{ EMIT_TOKEN(RPAREN); };
'*' =>{ EMIT_TOKEN(TIMES); };
'+' =>{ EMIT_TOKEN(PLUS); };
'-' =>{ EMIT_TOKEN(MINUS); };
',' =>{ EMIT_TOKEN(COMMA); };
'.' =>{ EMIT_TOKEN(DOT); };
'/' =>{ EMIT_TOKEN(DIVIDE); };
'?' =>{ EMIT_TOKEN(QUESTION); };
':' =>{ EMIT_TOKEN(COLON); };
'<' =>{ EMIT_TOKEN(LESS); };
'<=' =>{ EMIT_TOKEN(LESS_EQ); };
'>' =>{ EMIT_TOKEN(GREATER); };
'>=' =>{ EMIT_TOKEN(GREATER_EQ); };
'==' =>{ EMIT_TOKEN(EQUAL); };
'!=' =>{ EMIT_TOKEN(NOT_EQUAL); };
'&&' =>{ EMIT_TOKEN(LAND); };
'||' =>{ EMIT_TOKEN(LOR); };
'&' =>{ EMIT_TOKEN(BIT_AND); };
## Not needed? '|' =>{ EMIT_TOKEN(BIT_OK); };
'^' =>{ EMIT_TOKEN(BIT_XOR); };
## Some '.method' - Error if unknown
'.' alpha+ => emit_method;
## Regular functions
"pi" =>{ EMIT_TOKEN(PI); };
"degToRad" =>{ EMIT_TOKEN(DEG_TO_RAD); };
"radToDeg" =>{ EMIT_TOKEN(RAD_TO_DEG); };
"exp" =>{ EMIT_TOKEN(EXP); };
"log" =>{ EMIT_TOKEN(LOG); };
"log10" =>{ EMIT_TOKEN(LOG10); };
"pow" =>{ EMIT_TOKEN(POW); };
"sqr" =>{ EMIT_TOKEN(SQR); };
"sqrt" =>{ EMIT_TOKEN(SQRT); };
"cbrt" =>{ EMIT_TOKEN(CBRT); };
"sin" =>{ EMIT_TOKEN(SIN); };
"cos" =>{ EMIT_TOKEN(COS); };
"tan" =>{ EMIT_TOKEN(TAN); };
"asin" =>{ EMIT_TOKEN(ASIN); };
"acos" =>{ EMIT_TOKEN(ACOS); };
"atan" =>{ EMIT_TOKEN(ATAN); };
"atan2" =>{ EMIT_TOKEN(ATAN2); };
"sinh" =>{ EMIT_TOKEN(SINH); };
"cosh" =>{ EMIT_TOKEN(COSH); };
"tanh" =>{ EMIT_TOKEN(TANH); };
"mag" =>{ EMIT_TOKEN(MAG); };
"magSqr" =>{ EMIT_TOKEN(MAGSQR); };
"pos" =>{ EMIT_TOKEN(POS); };
"neg" =>{ EMIT_TOKEN(NEG); };
"pos0" =>{ EMIT_TOKEN(POS0); };
"neg0" =>{ EMIT_TOKEN(NEG0); };
"sign" =>{ EMIT_TOKEN(SIGN); };
## Reductions, or other special functions
"min" =>{ EMIT_TOKEN(MIN); };
"max" =>{ EMIT_TOKEN(MAX); };
"average" =>{ EMIT_TOKEN(AVERAGE); };
"sum" =>{ EMIT_TOKEN(SUM); };
"weightAverage" =>{ EMIT_TOKEN(WEIGHT_AVERAGE); };
"weightSum" =>{ EMIT_TOKEN(WEIGHT_SUM); };
"rand" =>{ EMIT_TOKEN(RAND); };
## Types
"bool" =>{ EMIT_TOKEN(BOOL); };
"vector" =>{ EMIT_TOKEN(VECTOR); };
"tensor" =>{ EMIT_TOKEN(TENSOR); };
"symmTensor" =>{ EMIT_TOKEN(SYM_TENSOR); };
"sphericalTensor" =>{ EMIT_TOKEN(SPH_TENSOR); };
## Single value (constants, etc)
"Zero" =>{ EMIT_TOKEN(ZERO); };
"true" =>{ EMIT_TOKEN(LTRUE); };
"false" =>{ EMIT_TOKEN(LFALSE); };
"tensor::I" =>{ EMIT_TOKEN(UNIT_TENSOR); };
"time" =>{ EMIT_TOKEN(TIME); };
## Identifier (field, etc - error if unknown)
## Handle 'bare' names and single/double quoted ones
ident => emit_ident;
dquoted => emit_ident;
squoted => emit_ident;
space*;
*|;
}%%
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::expressions::patchExpr::scanner::~scanner()
{
if (parser_)
{
delete parser_;
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::expressions::patchExpr::scanner::dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
) const
{
if (ident[0] == '.')
{
ident.erase(0, 1);
}
DebugInfo
<< "Method:" << ident
<< " at " << driver_.parsePosition() << nl;
const int methType = fieldMethodEnums.get(ident, -1);
if (methType > 0)
{
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
return true;
}
driver_.reportFatal("Unknown method: " + ident);
return false;
}
bool Foam::expressions::patchExpr::scanner::dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
) const
{
int tokType = -1;
const bool quoted =
(
(ident.front() == '"' || ident.front() == '\'')
&& (ident.front() == ident.back())
);
if (quoted)
{
ident.erase(ident.size()-1);
ident.erase(0, 1);
}
else
{
// Check for function name
tokType = funcTokenEnums.get(ident, -1);
if (tokType > 0)
{
DebugInfo
<< "Emit:" << ident << " function:"
<< parser_->nameOfToken(tokType) << nl;
parser_->parse(tokType, nullptr);
return true;
}
#ifdef HAS_LOOKBEHIND_TOKENS
// Specials such "cset" also reset the look-behind
tokType = lookBehindTokenEnums.get(ident, -1);
if (tokType > 0)
{
DebugInfo
<< "Emit:" << ident << " as look-behind:"
<< parser_->nameOfToken(tokType) << nl;
driver_.resetStashedTokenId(tokType);
parser_->parse(tokType, nullptr);
return true;
}
#endif
}
// Can also peek at stashed "look-behind"
// const int lookBehind = driver_.stashedTokenId();
tokType = driverTokenType(driver_, ident);
if (tokType > 0)
{
DebugInfo
<< "Emit:" << ident << " token:"
<< parser_->nameOfToken(tokType) << nl;
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
return true;
}
// Not found? Attempt to strip off '.x' endings etc,
// but not when quoted
const auto dot = ident.rfind('.');
const int methType =
(
quoted || dot == std::string::npos
? -1
: fieldMethodEnums.get(ident.substr(dot+1), -1)
);
if
(
methType > 0
&& (tokType = driverTokenType(driver_, ident.substr(0, dot))) > 0
)
{
DebugInfo
<< "Emit:" << ident.substr(0, dot).c_str() << " token:"
<< parser_->nameOfToken(tokType) << " with "
<< ident.substr(dot).c_str() << " token:"
<< parser_->nameOfToken(methType) << nl;
// The field (before the ".")
ident.erase(dot);
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
return true;
}
driver_.reportFatal
(
"Object " + ident + " does not exist or wrong type"
);
return false;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::expressions::patchExpr::scanner::process
(
const std::string& str,
size_t strBeg,
size_t strLen,
parseDriver& driver_
)
{
// Save debug value
const int oldDebug = debug;
if (driver_.debugScanner())
{
debug |= 4;
}
if (!parser_)
{
parser_ = new parser();
}
driver_.content(str, strBeg, strLen);
size_t strEnd = str.length();
if (strBeg > str.length())
{
strBeg = str.length();
}
else if (strLen != std::string::npos)
{
strLen += strBeg;
if (strLen < str.length())
{
strEnd = strLen;
}
}
parser_->start(driver_);
// Scan token type
scanToken scanTok;
// Ragel token start/end (required naming)
const char* ts;
const char* te;
// Local buffer data.
// - p, pe, eof are required Ragel naming
// - buf is our own naming
const char* buf = &(str[strBeg]);
const char* eof = &(str[strEnd]);
const char* p = buf;
const char* pe = eof;
// Initialize FSM variables
%%{write init;}%% /* ^^^ FSM initialization here ^^^ */;
%%{write exec;}%% /* ^^^ FSM execution here ^^^ */;
if (%%{write error;}%% == cs)
{
driver_.reportFatal("Parse error while scanning", (p-buf));
}
if (p != eof)
{
driver_.reportFatal("Parsing failed with remaining content", (p-buf));
}
// Terminate parser execution
parser_->parse(0, nullptr);
parser_->stop();
// Restore debug value
debug = oldDebug;
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,13 @@
#!/bin/sh
cd ${0%/*} || exit 1 # Run from this directory
# Manually create ragel scanner and lemon parser header
prefix=volumeExpr
"${WM_PROJECT_DIR:?}/wmake/scripts/makeParser" \
-prefix="$prefix" \
-scanner=Scanner.rl \
-parser=LemonParser.lyy-m4 \
"$@"
#------------------------------------------------------------------------------

View File

@ -0,0 +1,44 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "volumeExprFwd.H"
#include "defineDebugSwitch.H"
// * * * * * * * * * * * * * * * * Globals * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
defineDebugSwitchWithName(volumeExpr, "volumeExpr", 0);
registerDebugSwitchWithName(volumeExpr, volumeExpr, "volumeExpr");
} // End namespace expressions
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,226 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "volumeExprDriver.H"
#include "volumeExprScanner.H"
#include "error.H"
#include "fvPatch.H"
#include "fvMesh.H"
#include "className.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
namespace volumeExpr
{
defineTypeNameAndDebug(parseDriver, 0);
addNamedToRunTimeSelectionTable
(
fvExprDriver,
parseDriver,
dictionary,
volume
);
addNamedToRunTimeSelectionTable
(
fvExprDriver,
parseDriver,
idName,
volume
);
addNamedToRunTimeSelectionTable
(
fvExprDriver,
parseDriver,
dictionary,
internalField
);
addNamedToRunTimeSelectionTable
(
fvExprDriver,
parseDriver,
idName,
internalField
);
} // End namespace volumeExpr
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
static label getPatchID(const fvMesh& mesh, const word& patchName)
{
const auto& bMesh = mesh.boundaryMesh();
const label patchId = bMesh.findPatchID(patchName);
if (patchId < 0)
{
FatalErrorInFunction
<< "No patch " << patchName << " found in "
<< flatOutput(bMesh.names()) << nl
<< exit(FatalError);
}
return patchId;
}
static inline const polyPatch& findPolyPatch
(
const fvMesh& mesh,
const word& patchName
)
{
return mesh.boundaryMesh()[getPatchID(mesh, patchName)];
}
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::expressions::volumeExpr::parseDriver::parseDriver
(
const fvMesh& mesh,
bool cacheReadFields
)
:
parsing::genericRagelLemonDriver(),
expressions::fvExprDriver(cacheReadFields),
mesh_(mesh),
resultType_(),
isLogical_(false),
fieldGeoType_(NO_DATA),
resultDimension_()
{}
Foam::expressions::volumeExpr::parseDriver::parseDriver
(
const fvMesh& mesh,
const dictionary& dict
)
:
parsing::genericRagelLemonDriver(),
expressions::fvExprDriver(dict),
mesh_(mesh),
resultType_(),
isLogical_(false),
fieldGeoType_(NO_DATA),
resultDimension_()
{}
Foam::expressions::volumeExpr::parseDriver::parseDriver
(
const fvMesh& mesh,
const parseDriver& driver
)
:
parsing::genericRagelLemonDriver(),
expressions::fvExprDriver(driver),
mesh_(mesh),
resultType_(),
isLogical_(false),
fieldGeoType_(NO_DATA),
resultDimension_()
{}
Foam::expressions::volumeExpr::parseDriver::parseDriver
(
const word& meshName,
const fvMesh& mesh
)
:
parseDriver(mesh)
{
//?? Info<< "Warn that meshName is ignored?" << nl;
}
Foam::expressions::volumeExpr::parseDriver::parseDriver
(
const dictionary& dict,
const fvMesh& mesh
)
:
parsing::genericRagelLemonDriver(),
expressions::fvExprDriver(dict),
mesh_(mesh),
resultType_(),
isLogical_(false),
fieldGeoType_(NO_DATA),
resultDimension_()
{}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
bool Foam::expressions::volumeExpr::parseDriver::readDict
(
const dictionary& dict
)
{
expressions::fvExprDriver::readDict(dict);
dict.readIfPresent("dimensions", resultDimension_);
return true;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
unsigned Foam::expressions::volumeExpr::parseDriver::parse
(
const std::string& expr,
size_t pos,
size_t len
)
{
scanner scan(this->debugScanner());
scan.process(expr, pos, len, *this);
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,510 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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::volumeExpr::parseDriver
Description
Driver for volume, surface, point field expressions
Additional Properties
\table
Property | Description | Required | Default
dimensions | Dimensions for the expression result | no |
\endtable
In addition to the standard mathematical functions, operations and
logical and relational operations, the volume expression support the
following driver-specific functions:
Functions
\table
Function | Description | Number of arguments |
vol | The cell volumes | 0 |
pos | The cell centres | 0 |
pts | The cell points | 0 |
area | The face area magnitudes | 0 |
fpos | The face centres | 0 |
weightAverage| Volume or area weighted average | 1 |
weightSum | Volume or area weighted sum | 1 |
face | The face areaNormal vectors | 0 |
face | A surface-field face value | 1 |
point | A point-field point value | 1 |
cellToFace | Interpolate cell values onto faces | 1 |
cellToPoint | Interpolate cell values onto points | 1 |
pointToCell | Interpolate point values onto cells | 1 |
reconstruct | Reconstruct cell vector from surface scalar | 1 |
rand | Random field | 0/1 |
\endtable
Selections
\table
Function| Description | Number of arguments |
cset | Logical vol field corresponding to cellSet | 1 |
fset | Logical surf field corresponding to faceSet | 1 |
pset | Logical point field corresponding to pointSet | 1 |
czone | Logical vol field corresponding to cellZone | 1 |
fzone | Logical surf field corresponding to faceZone | 1 |
pzone | Logical point field corresponding to pointZone| 1 |
\endtable
SourceFiles
volumeExprDriver.C
\*---------------------------------------------------------------------------*/
#ifndef expressions_volumeExprDriver_H
#define expressions_volumeExprDriver_H
#include "volumeExprFwd.H"
#include "fvExprDriver.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "pointFields.H"
#include "genericRagelLemonDriver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace expressions
{
namespace volumeExpr
{
/*---------------------------------------------------------------------------*\
Class parseDriver Declaration
\*---------------------------------------------------------------------------*/
class parseDriver
:
public parsing::genericRagelLemonDriver,
public expressions::fvExprDriver
{
protected:
// Protected Data
//- The referenced mesh
const fvMesh& mesh_;
//- The results (volume, surface, point)
autoPtr<regIOobject> resultField_;
//- The result type-name.
// Normally volScalarField, surfaceVectorField etc,
// but Scalar is modified for logical as volScalarField etc
word resultType_;
//- A logical (bool-like) field (but actually a scalar)
bool isLogical_;
//- A volume/surface/point field
enum FieldAssociation fieldGeoType_;
//- The result dimensions
dimensionSet resultDimension_;
// Protected Member Functions
//- Deep-copy the internalField as a result.
// Uses the isLogical() and isPointData() values to handle
// additional bookkeeping.
// For isLogical(), renames the resultType_ from '*Scalar*'
// to '*Logical*' (eg, volLogicalField)
template<class Type>
void setInternalFieldResult(const Field<Type>& fld);
//- Cell selections (as logical)
tmp<volScalarField> field_cellSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const;
//- Face selections (as logical)
tmp<surfaceScalarField> field_faceSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const;
//- Point selections (as logical)
tmp<pointScalarField> field_pointSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const;
// No copy copy construct
parseDriver(const parseDriver&) = delete;
// No copy assignment
void operator=(const parseDriver&) = delete;
public:
ClassName("volumeExpr::driver");
// Constructors
//- Construct for specified mesh
explicit parseDriver
(
const fvMesh& mesh,
bool cacheReadFields = false
);
//- Construct for specified mesh with given dictionary
parseDriver(const fvMesh& mesh, const dictionary& dict);
//- Construct for specified mesh with copy of driver context
parseDriver(const fvMesh& mesh, const parseDriver& driver);
//- Construct with meshName for the given mesh
parseDriver(const word& meshName, const fvMesh& mesh);
//- Construct with patchName and region specified in dictionary
parseDriver(const dictionary& dict, const fvMesh& mesh);
//- Clone
virtual autoPtr<expressions::fvExprDriver> clone() const
{
return autoPtr<expressions::fvExprDriver>
(
new parseDriver(this->mesh_, *this)
);
}
//- Destructor
virtual ~parseDriver() = default;
// Public Member Functions
//- The mesh we are attached to
virtual const fvMesh& mesh() const
{
return mesh_;
}
//- The underlying field size for the expression
virtual label size() const
{
return mesh_.nCells();
}
//- The underlying point field size for the expression
virtual label pointSize() const
{
return mesh_.nPoints();
}
//- Field size associated with different geometric field types
inline label size(const FieldAssociation geoType) const;
// Reading
//- Read variables, tables etc.
// Adds support for "dimensions"
virtual bool readDict(const dictionary& dict);
// Evaluation
//- Perform parsing on (sub) string
using genericRagelLemonDriver::content;
//- Execute the parser
virtual unsigned parse
(
const std::string& expr,
size_t pos = 0,
size_t len = std::string::npos
);
// Field Information
//- The result type-name.
// Normally volScalarField, surfaceVectorField etc,
// but Scalar is modified for logical as volScalarField etc
const word& resultType() const
{
return resultType_;
}
//- The geometric field association
FieldAssociation fieldAssociation() const
{
return fieldGeoType_;
}
//- A logical (bool-like) field. Actually stored as a scalar.
bool isLogical() const
{
return isLogical_;
}
//- A volume field
bool isVolumeData() const
{
return fieldGeoType_ == FieldAssociation::VOLUME_DATA;
}
//- A surface field
bool isSurfaceData() const
{
return fieldGeoType_ == FieldAssociation::SURFACE_DATA;
}
//- A point field
bool isPointData() const
{
return fieldGeoType_ == FieldAssociation::POINT_DATA;
}
//- Test if stored result pointer is the specified type
template<class GeoField>
const GeoField* isResultType() const;
//- Test if stored result pointer is the specified type
//- and matches the specified logical type
template<class GeoField>
const GeoField* isResultType(bool logical, bool dieOnNull=false) const;
// Set Fields
//- Set result (vol field)
template<class Type>
void setResult
(
GeometricField<Type, fvPatchField, volMesh>* ptr,
bool logical = false
);
//- Set result (surface field)
template<class Type>
void setResult
(
GeometricField<Type, fvsPatchField, surfaceMesh>* ptr,
bool logical = false
);
//- Set result (point field)
template<class Type>
void setResult
(
GeometricField<Type, pointPatchField, pointMesh>* ptr,
bool logical = false
);
// New Fields
//- Return a new volume field with the mesh size
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
newVolField(const Type& val = pTraits<Type>::zero) const;
//- Return a new surface field with the mesh nInternalFaces size
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
newSurfaceField(const Type& val = pTraits<Type>::zero) const;
//- Return a new point field with the mesh nPoints size
template<class Type>
tmp<GeometricField<Type, pointPatchField, pointMesh>>
newPointField(const Type& val = pTraits<Type>::zero) const;
//- Retrieve field (vol field)
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
getVolField(const word& fldName, bool getOldTime=false);
//- Retrieve field (surface field)
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
getSurfaceField(const word& fldName, bool getOldTime=false);
//- Retrieve field (surface field)
template<class Type>
tmp<GeometricField<Type, pointPatchField, pointMesh>>
getPointField(const word& fldName, bool getOldTime=false);
// Field "shape" conversions
//- Interpolate cell to face values
template<class Type>
tmp<GeometricField<Type, fvsPatchField, surfaceMesh>>
cellToFace
(
const GeometricField<Type,fvPatchField,volMesh>& field
) const;
//- Interpolate cell to point values
template<class Type>
tmp<GeometricField<Type, pointPatchField, pointMesh>>
cellToPoint
(
const GeometricField<Type, fvPatchField, volMesh>& field
) const;
//- Interpolate point to cell values
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
pointToCell
(
const GeometricField<Type, pointPatchField, pointMesh>& field
) const;
// Custom Field Functions
//- The volume-weighted average of a field
template<class Type>
Type volAverage
(
GeometricField<Type, fvPatchField, volMesh>& fld
) const
{
return weightedAverage(fld.mesh().V(), fld.primitiveField());
}
//- The volume-weighted sum of a field
template<class Type>
Type volSum
(
GeometricField<Type, fvPatchField, volMesh>& fld
) const
{
return weightedSum(fld.mesh().V(), fld.primitiveField());
}
//- The area-weighted average of a field
template<class Type>
Type areaAverage
(
GeometricField<Type, fvsPatchField, surfaceMesh>& fld
) const
{
return weightedAverage
(
fld.mesh().magSf().primitiveField(),
fld.primitiveField()
);
}
//- The area-weighted sum of a field
template<class Type>
Type areaSum
(
GeometricField<Type, fvsPatchField, surfaceMesh>& fld
) const
{
return weightedSum
(
fld.mesh().magSf().primitiveField(),
fld.primitiveField()
);
}
//- The cell volumes - (swak = vol)
tmp<volScalarField> field_cellVolume() const;
//- The cell centres - (swak = pos)
tmp<volVectorField> field_cellCentre() const;
//- The face area magnitudes [magSf] - (swak = area)
tmp<surfaceScalarField> field_faceArea() const;
//- The face centres - (swak = fpos)
tmp<surfaceVectorField> field_faceCentre() const;
//- The face areas with their vector direction [Sf] - (swak = face)
tmp<surfaceVectorField> field_areaNormal() const;
//- The mesh point locations - (swak = pts)
tmp<pointVectorField> field_pointField() const;
//- Cell selection (set)
inline tmp<volScalarField> field_cellSet(const word& name) const;
//- Cell selection (zone)
inline tmp<volScalarField> field_cellZone(const word& name) const;
//- Face selection (set)
inline tmp<surfaceScalarField> field_faceSet(const word& name) const;
//- Face selection (zone)
inline tmp<surfaceScalarField> field_faceZone(const word& name) const;
//- Point selection (set)
inline tmp<pointScalarField> field_pointSet(const word& name) const;
//- Point selection (zone)
inline tmp<pointScalarField> field_pointZone(const word& name) const;
//- A uniform random field
tmp<volScalarField> field_rand(label seed=0, bool gaussian=false) const;
//- A Gaussian random field
tmp<volScalarField> field_randGaussian(label seed=0) const
{
return field_rand(seed, true);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace volumeExpr
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "volumeExprDriverI.H"
#ifdef NoRepository
#include "volumeExprDriverTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,283 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "volumeExprDriver.H"
#include "fvPatch.H"
#include "error.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::volScalarField>
Foam::expressions::volumeExpr::parseDriver::field_cellSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const
{
auto tresult = volScalarField::New
(
"selected",
mesh(),
dimensionedScalar(Zero)
);
labelList selected;
switch (setType)
{
case topoSetSource::sourceType::CELLZONE_SOURCE:
case topoSetSource::sourceType::CELLSET_SOURCE:
{
selected = getTopoSetLabels(name, setType);
break;
}
default:
{
FatalErrorInFunction
<< "Unexpected sourceType: " << int(setType) << nl
<< exit(FatalError);
break;
}
}
auto& fld = tresult.ref().primitiveFieldRef();
UIndirectList<scalar>(fld, selected) = scalar(1);
return tresult;
}
Foam::tmp<Foam::surfaceScalarField>
Foam::expressions::volumeExpr::parseDriver::field_faceSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const
{
auto tresult = surfaceScalarField::New
(
"selected",
mesh(),
dimensionedScalar(Zero)
);
labelList selected;
switch (setType)
{
case topoSetSource::sourceType::FACESET_SOURCE:
case topoSetSource::sourceType::FACEZONE_SOURCE:
{
selected = getTopoSetLabels(name, setType);
break;
}
default:
{
FatalErrorInFunction
<< "Unexpected sourceType: " << int(setType) << nl
<< exit(FatalError);
break;
}
}
const auto& bmesh = mesh().boundaryMesh();
auto& result = tresult.ref();
auto& fld = result.primitiveFieldRef();
auto& bfld = result.boundaryFieldRef();
label nErrors = 0;
for (const label facei : selected)
{
if (facei < mesh().nInternalFaces())
{
fld[facei] = scalar(1);
}
else
{
const label patchi = bmesh.whichPatch(facei);
if (patchi < 0)
{
++nErrors;
}
else
{
bfld[patchi][facei-bmesh[patchi].start()] = scalar(1);
}
}
}
if (nErrors)
{
WarningInFunction
<< "The faceSet/faceZone " << name << " contained "
<< nErrors << " faces outside of the addressing range" << nl
<< nl;
}
return tresult;
}
Foam::tmp<Foam::pointScalarField>
Foam::expressions::volumeExpr::parseDriver::field_pointSelection
(
const word& name,
enum topoSetSource::sourceType setType
) const
{
auto tresult = pointScalarField::New
(
"selected",
pointMesh::New(mesh()),
dimensionedScalar(Zero)
);
labelList selected;
switch (setType)
{
case topoSetSource::sourceType::POINTSET_SOURCE:
case topoSetSource::sourceType::POINTZONE_SOURCE:
{
selected = getTopoSetLabels(name, setType);
break;
}
default:
{
FatalErrorInFunction
<< "Unexpected sourceType: " << int(setType) << nl
<< exit(FatalError);
break;
}
}
auto& fld = tresult.ref().primitiveFieldRef();
UIndirectList<scalar>(fld, selected) = scalar(1);
return tresult;
}
Foam::tmp<Foam::volScalarField>
Foam::expressions::volumeExpr::parseDriver::field_cellVolume() const
{
return volScalarField::New
(
"vol",
mesh(),
dimVol,
mesh().V()
);
}
Foam::tmp<Foam::volVectorField>
Foam::expressions::volumeExpr::parseDriver::field_cellCentre() const
{
return tmp<volVectorField>::New(mesh().C());
}
Foam::tmp<Foam::surfaceScalarField>
Foam::expressions::volumeExpr::parseDriver::field_faceArea() const
{
return surfaceScalarField::New
(
"face",
mesh(),
dimless,
mesh().magSf()
);
}
Foam::tmp<Foam::surfaceVectorField>
Foam::expressions::volumeExpr::parseDriver::field_faceCentre() const
{
return surfaceVectorField::New
(
"fpos",
mesh(),
dimless,
mesh().Cf()
);
}
Foam::tmp<Foam::surfaceVectorField>
Foam::expressions::volumeExpr::parseDriver::field_areaNormal() const
{
return surfaceVectorField::New
(
"face",
mesh(),
dimless,
mesh().Sf()
);
}
Foam::tmp<Foam::pointVectorField>
Foam::expressions::volumeExpr::parseDriver::field_pointField() const
{
return pointVectorField::New
(
"pts",
pointMesh::New(mesh()),
dimless,
mesh().points()
);
}
Foam::tmp<Foam::volScalarField>
Foam::expressions::volumeExpr::parseDriver::field_rand
(
label seed,
bool gaussian
) const
{
auto tresult = volScalarField::New
(
"rand",
mesh(),
dimless
);
auto& fld = tresult.ref().primitiveFieldRef();
fill_random(fld, seed, gaussian);
return tresult;
}
// ************************************************************************* //

View File

@ -0,0 +1,137 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 Foam::label Foam::expressions::volumeExpr::parseDriver::size
(
const FieldAssociation geoType
) const
{
switch (geoType)
{
case FieldAssociation::POINT_DATA :
return mesh_.nPoints();
break;
case FieldAssociation::SURFACE_DATA :
return mesh_.nInternalFaces();
break;
case FieldAssociation::VOLUME_DATA :
return mesh_.nCells();
break;
default:
break;
}
return 0;
}
inline Foam::tmp<Foam::volScalarField>
Foam::expressions::volumeExpr::parseDriver::parseDriver::field_cellSet
(
const word& name
) const
{
return field_cellSelection
(
name,
topoSetSource::sourceType::CELLSET_SOURCE
);
}
inline Foam::tmp<Foam::volScalarField>
Foam::expressions::volumeExpr::parseDriver::field_cellZone
(
const word& name
) const
{
return field_cellSelection
(
name,
topoSetSource::sourceType::CELLZONE_SOURCE
);
}
inline Foam::tmp<Foam::surfaceScalarField>
Foam::expressions::volumeExpr::parseDriver::field_faceSet
(
const word& name
) const
{
return field_faceSelection
(
name,
topoSetSource::sourceType::FACESET_SOURCE
);
}
inline Foam::tmp<Foam::surfaceScalarField>
Foam::expressions::volumeExpr::parseDriver::field_faceZone
(
const word& name
) const
{
return field_faceSelection
(
name,
topoSetSource::sourceType::FACEZONE_SOURCE
);
}
inline Foam::tmp<Foam::pointScalarField>
Foam::expressions::volumeExpr::parseDriver::field_pointSet
(
const word& name
) const
{
return field_pointSelection
(
name,
topoSetSource::sourceType::POINTSET_SOURCE
);
}
inline Foam::tmp<Foam::pointScalarField>
Foam::expressions::volumeExpr::parseDriver::field_pointZone
(
const word& name
) const
{
return field_pointSelection
(
name,
topoSetSource::sourceType::POINTZONE_SOURCE
);
}
// ************************************************************************* //

View File

@ -0,0 +1,331 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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 "exprOps.H"
#include "FieldOps.H"
#include "surfaceInterpolate.H"
#include "volPointInterpolation.H"
#include "interpolatePointToCell.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
void Foam::expressions::volumeExpr::parseDriver::setInternalFieldResult
(
const Field<Type>& fld
)
{
if (isLogical_)
{
// Eg, volScalarField -> volLogicalField
resultType_.replace("Scalar", "Logical");
Field<bool> bools(fld.size());
FieldOps::assign(bools, fld, expressions::boolOp<Type>());
this->result().setResult(std::move(bools), this->isPointData());
}
else
{
// Deep copy
this->result().setResult(fld, this->isPointData());
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class Type>
void Foam::expressions::volumeExpr::parseDriver::setResult
(
GeometricField<Type, fvPatchField, volMesh>* ptr,
bool logical
)
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
resultField_.clear();
// Characteristics
resultType_ = pTraits<fieldType>::typeName;
isLogical_ = logical;
fieldGeoType_ = VOLUME_DATA;
// Always strip out dimensions?
if (!resultDimension_.dimensionless())
{
ptr->dimensions().reset(resultDimension_);
}
setInternalFieldResult(ptr->primitiveField());
// Take ownership
resultField_.reset(ptr);
}
template<class Type>
void Foam::expressions::volumeExpr::parseDriver::setResult
(
GeometricField<Type, fvsPatchField, surfaceMesh>* ptr,
bool logical
)
{
typedef GeometricField<Type, fvsPatchField, surfaceMesh> fieldType;
resultField_.clear();
// Characteristics
resultType_ = pTraits<fieldType>::typeName;
isLogical_ = logical;
fieldGeoType_ = SURFACE_DATA;
// Always strip out dimensions?
if (!resultDimension_.dimensionless())
{
ptr->dimensions().reset(resultDimension_);
}
setInternalFieldResult(ptr->primitiveField());
// Take ownership
resultField_.reset(ptr);
}
template<class Type>
void Foam::expressions::volumeExpr::parseDriver::setResult
(
GeometricField<Type, pointPatchField, pointMesh>* ptr,
bool logical
)
{
typedef GeometricField<Type, pointPatchField, pointMesh> fieldType;
resultField_.clear();
// Characteristics
resultType_ = pTraits<fieldType>::typeName;
isLogical_ = logical;
fieldGeoType_ = POINT_DATA;
// Always strip out dimensions?
if (!resultDimension_.dimensionless())
{
ptr->dimensions().reset(resultDimension_);
}
setInternalFieldResult(ptr->primitiveField());
// Take ownership
resultField_.reset(ptr);
}
template<class GeomField>
const GeomField*
Foam::expressions::volumeExpr::parseDriver::isResultType() const
{
return dynamic_cast<const GeomField*>(resultField_.get());
}
template<class GeomField>
const GeomField*
Foam::expressions::volumeExpr::parseDriver::isResultType
(
bool logical,
bool dieOnNull
) const
{
const regIOobject* ptr = resultField_.get();
if (dieOnNull && ptr != nullptr)
{
FatalErrorInFunction
<< "No result available. Requested "
<< pTraits<GeomField>::typeName << nl
<< exit(FatalError);
}
if (isLogical_ == logical)
{
return dynamic_cast<const GeomField*>(ptr);
}
return nullptr;
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::expressions::volumeExpr::parseDriver::getVolField
(
const word& fldName,
bool getOldTime
)
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
return this->getOrReadField<fieldType>
(
fldName,
true, // mandatory
getOldTime
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
Foam::expressions::volumeExpr::parseDriver::getSurfaceField
(
const word& fldName,
bool getOldTime
)
{
typedef GeometricField<Type, fvsPatchField, surfaceMesh> fieldType;
return this->getOrReadField<fieldType>
(
fldName,
true, // mandatory
getOldTime
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>>
Foam::expressions::volumeExpr::parseDriver::getPointField
(
const word& fldName,
bool getOldTime
)
{
typedef GeometricField<Type, pointPatchField, pointMesh> fieldType;
return this->getOrReadPointField<fieldType>
(
fldName,
true, // mandatory
getOldTime
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::expressions::volumeExpr::parseDriver::newVolField
(
const Type& val
) const
{
return GeometricField<Type,fvPatchField,volMesh>::New
(
word("constant.") + word(pTraits<Type>::typeName),
mesh(),
dimensioned<Type>("", dimless, val)
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
Foam::expressions::volumeExpr::parseDriver::newSurfaceField
(
const Type& val
) const
{
return GeometricField<Type,fvsPatchField,surfaceMesh>::New
(
word("constant.") + word(pTraits<Type>::typeName),
mesh(),
dimensioned<Type>("", dimless, val)
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>>
Foam::expressions::volumeExpr::parseDriver::newPointField
(
const Type& val
) const
{
return GeometricField<Type,pointPatchField,pointMesh>::New
(
word("constant.") + word(pTraits<Type>::typeName),
pointMesh::New(mesh()),
dimensioned<Type>("", dimless, val)
);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvsPatchField, Foam::surfaceMesh>>
Foam::expressions::volumeExpr::parseDriver::cellToFace
(
const GeometricField<Type, fvPatchField, volMesh>& field
) const
{
return fvc::interpolate(field);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::pointPatchField, Foam::pointMesh>>
Foam::expressions::volumeExpr::parseDriver::cellToPoint
(
const GeometricField<Type, fvPatchField, volMesh>& field
) const
{
volPointInterpolation interp(this->mesh());
return interp.interpolate(field);
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type,Foam::fvPatchField,Foam::volMesh>>
Foam::expressions::volumeExpr::parseDriver::pointToCell
(
const GeometricField<Type, pointPatchField, pointMesh>& field
) const
{
auto tresult = newVolField<Type>();
auto& result = tresult.ref();
forAll(result,celli)
{
result[celli] = interpolatePointToCell(field, celli);
}
return tresult;
}
// ************************************************************************* //

View File

@ -0,0 +1,84 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Namespace
Foam::expressions::volumeExpr
Description
Namespace for volume field expressions parsing and evaluation
\*---------------------------------------------------------------------------*/
#ifndef expressions_volumeExprFwd_H
#define expressions_volumeExprFwd_H
namespace Foam
{
namespace expressions
{
namespace volumeExpr
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Forward Declarations
class parser;
class scanner;
class parseDriver;
union scanToken;
//- Static debugging option
extern int debug;
//- The field association for volume expressions (mutually exclusive)
enum FieldAssociation : unsigned char
{
NO_DATA = 0, //!< No data
POINT_DATA = 1, //!< Point data
SURFACE_DATA = 2, //!< Surface data
VOLUME_DATA = 3 //!< Volume data
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace volumeExpr
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Typedef for volumeExpr parseDriver
typedef volumeExpr::parseDriver volumeExprDriver;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,119 @@
#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_TIME 28
#define TOK_SCALAR_ID 29
#define TOK_MIN 30
#define TOK_COMMA 31
#define TOK_MAX 32
#define TOK_SUM 33
#define TOK_AVERAGE 34
#define TOK_EXP 35
#define TOK_LOG 36
#define TOK_LOG10 37
#define TOK_SQR 38
#define TOK_SQRT 39
#define TOK_CBRT 40
#define TOK_SIN 41
#define TOK_COS 42
#define TOK_TAN 43
#define TOK_ASIN 44
#define TOK_ACOS 45
#define TOK_ATAN 46
#define TOK_SINH 47
#define TOK_COSH 48
#define TOK_TANH 49
#define TOK_POW 50
#define TOK_ATAN2 51
#define TOK_POS 52
#define TOK_NEG 53
#define TOK_POS0 54
#define TOK_NEG0 55
#define TOK_SIGN 56
#define TOK_FLOOR 57
#define TOK_CEIL 58
#define TOK_ROUND 59
#define TOK_HYPOT 60
#define TOK_RAND 61
#define TOK_VECTOR_ID 62
#define TOK_SPH_TENSOR_ID 63
#define TOK_SYM_TENSOR_ID 64
#define TOK_UNIT_TENSOR 65
#define TOK_TENSOR_ID 66
#define TOK_LTRUE 67
#define TOK_LFALSE 68
#define TOK_BOOL 69
#define TOK_CSET 70
#define TOK_IDENTIFIER 71
#define TOK_CZONE 72
#define TOK_CELL_VOLUME 73
#define TOK_WEIGHT_AVERAGE 74
#define TOK_WEIGHT_SUM 75
#define TOK_FACE_EXPR 76
#define TOK_SSCALAR_ID 77
#define TOK_SVECTOR_ID 78
#define TOK_SSPH_TENSOR_ID 79
#define TOK_SSYM_TENSOR_ID 80
#define TOK_STENSOR_ID 81
#define TOK_FSET 82
#define TOK_FZONE 83
#define TOK_FACE_AREA 84
#define TOK_FACE_CENTRE 85
#define TOK_POINT_EXPR 86
#define TOK_PSCALAR_ID 87
#define TOK_PVECTOR_ID 88
#define TOK_PSPH_TENSOR_ID 89
#define TOK_PSYM_TENSOR_ID 90
#define TOK_PTENSOR_ID 91
#define TOK_PSET 92
#define TOK_PZONE 93
#define TOK_POINTS 94
#define TOK_MAG 95
#define TOK_MAGSQR 96
#define TOK_VECTOR 97
#define TOK_TENSOR 98
#define TOK_SYM_TENSOR 99
#define TOK_SPH_TENSOR 100
#define TOK_CMPT_X 101
#define TOK_CMPT_Y 102
#define TOK_CMPT_Z 103
#define TOK_CMPT_XX 104
#define TOK_CMPT_XY 105
#define TOK_CMPT_XZ 106
#define TOK_CMPT_YX 107
#define TOK_CMPT_YY 108
#define TOK_CMPT_YZ 109
#define TOK_CMPT_ZX 110
#define TOK_CMPT_ZY 111
#define TOK_CMPT_ZZ 112
#define TOK_CMPT_II 113
#define TOK_TRANSPOSE 114
#define TOK_DIAG 115
#define TOK_POINT_TO_CELL 116
#define TOK_RECONSTRUCT 117
#define TOK_CELL_TO_FACE 118
#define TOK_CELL_TO_POINT 119

View File

@ -0,0 +1,826 @@
%include
{
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Description
Lemon grammar for volume expressions.
https://www.sqlite.org/src/doc/trunk/doc/lemon.html
See detailed notes in the field expression parser.
\*---------------------------------------------------------------------------*/
} // %include
/*
* include[volumeExprLemonParserMacros.m4]
*include(`volumeExprLemonParserMacros.m4')dnl
!done in a comment since many editors have issues matching m4 quotes!
*/
%include
{
#include "volumeExprDriver.H"
#include "volumeExprParser.H"
#include "volumeExprScanner.H"
#include "unitConversion.H"
#include "error.H"
#include "volFields.H"
#include "surfaceFields.H"
#include "pointFields.H"
#include "exprDriverOps.H"
#include "GeometricFieldOps.H"
#include "fvcReconstruct.H"
// Enable ParseTrace
#undef NDEBUG
compiler_pragmas()
// Local Functions
tmp_management()
dnl
dnl #if 0
dnl namespace Foam
dnl {
dnl //- Check field sizes
dnl template<class T1, class T2>
dnl static bool checkSizes(const char* what, T1* arg1, T2* arg2)
dnl {
dnl if (arg1 == nullptr || arg2 == nullptr)
dnl {
dnl FatalError
dnl << "Null pointer in " << what << nl
dnl << Foam::exit(Foam::FatalError);
dnl }
dnl if (arg1->size() != arg2->size())
dnl {
dnl FatalError
dnl << "Size mismatch in " << what << ' '
dnl << pTraits<typename T1::value_type>::typeName << ", "
dnl << pTraits<typename T2::value_type>::typeName << "\n("
dnl << arg1->size() << " != " << arg2->size() << ')' << nl
dnl << Foam::exit(Foam::FatalError);
dnl }
dnl
dnl return true;
dnl }
dnl } // End namespace Foam
dnl #endif
dnl
} // %include
// ------------------------------------------------------------------------- //
%namespace {}
// Use extra argument for the return value
%extra_context { Foam::expressions::volumeExpr::parseDriver* driver }
%parse_failure { driver->reportFatal("Parse failure, giving up..."); }
%syntax_error { driver->reportFatal("Syntax error"); }
%token_prefix TOK_
// Terminals
%token_type {Foam::expressions::volumeExpr::scanToken*}
// Non-terminals
%type ivalue { Foam::label }
%type svalue { Foam::scalar }
%type ident { Foam::word* }
// Volume fields
declare_field(lfield, Foam::volScalarField, Foam::scalar, newVolField, getVolField)
declare_field(sfield, Foam::volScalarField, Foam::scalar, newVolField, getVolField)
declare_field(vfield, Foam::volVectorField, Foam::vector, newVolField, getVolField)
declare_field(hfield, Foam::volSphericalTensorField, Foam::sphericalTensor, newVolField, getVolField)
declare_field(yfield, Foam::volSymmTensorField, Foam::symmTensor, newVolField, getVolField)
declare_field(tfield, Foam::volTensorField, Foam::tensor, newVolField, getVolField)
// Surface fields
declare_field(slfield, Foam::surfaceScalarField, Foam::scalar, newSurfaceField, getSurfaceField)
declare_field(ssfield, Foam::surfaceScalarField, Foam::scalar, newSurfaceField, getSurfaceField)
declare_field(svfield, Foam::surfaceVectorField, Foam::vector, newSurfaceField, getSurfaceField)
declare_field(shfield, Foam::surfaceSphericalTensorField, Foam::sphericalTensor, newSurfaceField, getSurfaceField)
declare_field(syfield, Foam::surfaceSymmTensorField, Foam::symmTensor, newSurfaceField, getSurfaceField)
declare_field(stfield, Foam::surfaceTensorField, Foam::tensor, newSurfaceField, getSurfaceField)
// Point fields
declare_field(plfield, Foam::pointScalarField, Foam::scalar, newPointField, getPointField)
declare_field(psfield, Foam::pointScalarField, Foam::scalar, newPointField, getPointField)
declare_field(pvfield, Foam::pointVectorField, Foam::vector, newPointField, getPointField)
declare_field(phfield, Foam::pointSphericalTensorField, Foam::sphericalTensor, newPointField, getPointField)
declare_field(pyfield, Foam::pointSymmTensorField, Foam::symmTensor, newPointField, getPointField)
declare_field(ptfield, Foam::pointTensorField, Foam::tensor, newPointField, getPointField)
// For each rule action with code, destruction must be done by that code block
// Lemon does not generate a destructor for that.
// So do not use Lemon destructors for anything.
operator_precedence()
%start_symbol evaluate
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*\
* Productions (scalar)
\*---------------------------------------------------------------------------*/
svalue (lhs) ::= NUMBER (a) . { lhs = (a)->svalue; } // From 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(); }
svalue (lhs) ::= RAD_TO_DEG LPAREN RPAREN . { lhs = Foam::radToDeg(); }
svalue (lhs) ::= TIME LPAREN RPAREN . { lhs = driver->timeValue(); }
/* * * * * * * * * * * * * * * * Volume Fields * * * * * * * * * * * * * * * *\
dnl
define([_logic_], [lfield])dnl
define([_scalar_], [sfield])dnl
define([_vector_], [vfield])dnl
define([_sphTensor_], [hfield])dnl
define([_symTensor_], [yfield])dnl
define([_tensor_], [tfield])dnl
dnl
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*---------------------------------------------------------------------------*\
* Productions (volScalarField)
dnl
define([_target_], [sfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, svalue)
rule_get_field(_target_, SCALAR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
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>())
// Non-standard but manage via FieldOps::assign
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<Foam::scalar>())
// Other functions
_target_ (lhs) ::= RAND LPAREN RPAREN .
{
lhs = driver->field_rand().ptr();
}
_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();
}
/*---------------------------------------------------------------------------*\
* Productions (volVectorField)
dnl
define([_target_], [vfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, VECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
/*---------------------------------------------------------------------------*\
* Productions (volSphericalTensorField)
dnl
define([_target_], [hfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, SPH_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_sphTensor_operations()
rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (volSymmTensorField)
dnl
define([_target_], [yfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, SYM_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_symTensor_operations()
rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (volTensorField)
dnl
define([_target_], [tfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
tfield (lhs) ::= UNIT_TENSOR . { lhs = _new_tfield(Foam::tensor::I); }
rule_get_field(_target_, TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_tensor_operations()
rules_tensor_functions()
/*---------------------------------------------------------------------------*\
* Logic field productions (volScalarField)
dnl
define([_target_], [lfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Logical */ }
_logic_ (lhs) ::= LTRUE . { lhs = _new_lfield(_logic_true_); }
_logic_ (lhs) ::= LFALSE . { lhs = _new_lfield(_logic_false_); }
rule_cast_logical(_target_, _target_)
rule_cast_logical(_target_, _scalar_, Foam::scalar)
rules_logical_operations(_logic_, _value_type_)
/*---------------------------------------------------------------------------*\
* General Volume-related productions
\*---------------------------------------------------------------------------*/
rules_driver_volume_functions()
/* * * * * * * * * * * * * * * * Surface Fields * * * * * * * * * * * * * * *\
dnl
define([_logic_], [slfield])dnl
define([_scalar_], [ssfield])dnl
define([_vector_], [svfield])dnl
define([_sphTensor_], [shfield])dnl
define([_symTensor_], [syfield])dnl
define([_tensor_], [stfield])dnl
dnl
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
dnl> %ifndef disable_surface_fields
/*---------------------------------------------------------------------------*\
* Productions (surfaceScalarField)
dnl
define([_target_], [ssfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, svalue, FACE_EXPR)
rule_get_field(_target_, SSCALAR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
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>())
// Non-standard but manage via FieldOps::assign
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<Foam::scalar>())
/*---------------------------------------------------------------------------*\
* Productions (surfaceVectorField)
dnl
define([_target_], [svfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, SVECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
/*---------------------------------------------------------------------------*\
* Productions (surfaceSphericalTensorField)
dnl
define([_target_], [shfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, SSPH_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_sphTensor_operations()
rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (surfaceSymmTensorField)
dnl
define([_target_], [syfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, SSYM_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_symTensor_operations()
rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (surfaceTensorField)
dnl
define([_target_], [stfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, STENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_tensor_operations()
rules_tensor_functions()
/*---------------------------------------------------------------------------*\
* Logic field productions (surfaceScalarField)
dnl
define([_target_], [slfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Logical */ }
_logic_ (lhs) ::= FACE_EXPR LPAREN LTRUE RPAREN . { lhs = _new_slfield(_logic_true_); }
_logic_ (lhs) ::= FACE_EXPR LPAREN LFALSE RPAREN . { lhs = _new_slfield(_logic_false_); }
rule_cast_logical(_target_, _target_)
rule_cast_logical(_target_, _scalar_, Foam::scalar)
rules_logical_operations(_logic_, _value_type_)
/*---------------------------------------------------------------------------*\
* General Surface-related productions
\*---------------------------------------------------------------------------*/
rules_driver_surface_functions()
dnl> %endif
// End disable_surface_fields
/* * * * * * * * * * * * * * * * Point Fields * * * * * * * * * * * * * * * *\
dnl
define([_logic_], [plfield])dnl
define([_scalar_], [psfield])dnl
define([_vector_], [pvfield])dnl
define([_sphTensor_], [phfield])dnl
define([_symTensor_], [pyfield])dnl
define([_tensor_], [ptfield])dnl
dnl
dnl Several functions are incomplete for point fields
dnl
pushdef([incomplete_rule_unary_func], [])
pushdef([incomplete_rule_binary_func], [])
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
dnl> %ifndef disable_point_fields
/*---------------------------------------------------------------------------*\
* Productions (pointScalarField)
dnl
define([_target_], [psfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_field_from_value(_target_, svalue, POINT_EXPR)
rule_get_field(_target_, PSCALAR_ID)
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>())
// Non-standard but manage via FieldOps::assign
rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp<Foam::scalar>())
/*---------------------------------------------------------------------------*\
* Some special handling for point fields.
* Some operators are incomplete, or ambiguous.
* Just calculate directly on the primitiveField, which is not as bad as it
* sounds since most of the pointPatchField operators are dummies (no-op)
* anyhow.
dnl
pushdef([rule_binary_op],
[$1 (lhs) ::= $2 (a) $4 $3 (b) .
{
lhs = _new_$1();
(*lhs).primitiveFieldRef() =
(make_obj(a).primitiveField() $5 make_obj(b).primitiveField());
}]
)dnl>
dnl
pushdef([rule_unary_func],
[$1 (lhs) ::= $3 LPAREN $2 (a) RPAREN .
{
lhs = _new_$1();
(*lhs).primitiveFieldRef() = $4 (make_obj(a).primitiveField());
}]
)dnl>
dnl
pushdef([rule_binary_func],
[$1 (lhs) ::= $4 LPAREN $2 (a) COMMA $3 (b) RPAREN .
{
lhs = _new_$1();
(*lhs).primitiveFieldRef() =
$5(make_obj(a).primitiveField(), make_obj(b).primitiveField());
}]
)dnl>
dnl
\*---------------------------------------------------------------------------*/
rules_scalar_operations()
rules_scalar_functions()
dnl/* Restore definitions
popdef([rule_binary_op])dnl
popdef([rule_unary_func])dnl
popdef([rule_binary_func])dnl
popdef([incomplete_rule_unary_func])dnl
popdef([incomplete_rule_binary_func])dnl
dnl*/
/*---------------------------------------------------------------------------*\
* Productions (pointVectorField)
dnl
define([_target_], [pvfield])dnl
define([_value_type_], [Foam::vector])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, PVECTOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_vector_operations()
rules_vector_functions()
/*---------------------------------------------------------------------------*\
* Productions (pointSphericalTensorField)
dnl
define([_target_], [phfield])dnl
define([_value_type_], [Foam::sphericalTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, PSPH_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_sphTensor_operations()
rules_sphTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (pointSymmTensorField)
dnl
define([_target_], [pyfield])dnl
define([_value_type_], [Foam::symmTensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, PSYM_TENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_symTensor_operations()
rules_symTensor_functions()
/*---------------------------------------------------------------------------*\
* Productions (pointTensorField)
dnl
define([_target_], [ptfield])dnl
define([_value_type_], [Foam::tensor])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a); }
rule_get_field(_target_, PTENSOR_ID)
rules_standard(_target_, _value_type_, _logic_)
rules_inplace_gUnary(_target_)
rules_tensor_operations()
rules_tensor_functions()
/*---------------------------------------------------------------------------*\
* Logic field productions (pointScalarField)
dnl
define([_target_], [plfield])dnl
define([_value_type_], [Foam::scalar])dnl
dnl
\*---------------------------------------------------------------------------*/
evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Logical */ }
_logic_ (lhs) ::= POINT_EXPR LPAREN LTRUE RPAREN . { lhs = _new_plfield(_logic_true_); }
_logic_ (lhs) ::= POINT_EXPR LPAREN LFALSE RPAREN . { lhs = _new_plfield(_logic_false_); }
rules_logical_operations(_logic_, _value_type_)
/*---------------------------------------------------------------------------*\
* General Point-related productions
\*---------------------------------------------------------------------------*/
rules_driver_point_functions()
dnl> %endif
// End disable_point_fields
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
/*---------------------------------------------------------------------------*\
* Volume field composition
\*---------------------------------------------------------------------------*/
rule_mag_logical(sfield, lfield)
rules_mag_functions(sfield, sfield)
rules_mag_functions(sfield, vfield)
rules_mag_functions(sfield, tfield)
rules_mag_functions(sfield, yfield)
rules_mag_functions(sfield, hfield)
rule_vector_zip(vfield, sfield, VECTOR)
rule_tensor_zip(tfield, sfield, TENSOR)
rule_symTensor_zip(yfield, sfield, SYM_TENSOR)
rule_sphTensor_zip(hfield, sfield, SPH_TENSOR)
rule_vector_components(sfield, vfield)
rule_tensor_components(sfield, tfield)
rule_symTensor_components(sfield, yfield)
rule_sphTensor_components(sfield, hfield)
rule_tensor_transpose(tfield)
rule_symTensor_transpose(yfield)
rule_sphTensor_transpose(hfield)
rule_tensor_unzipDiag(vfield, yfield)
rule_tensor_unzipAll(vfield, tfield)
rule_pointToCell(sfield, psfield)
rule_pointToCell(vfield, pvfield)
rule_pointToCell(tfield, ptfield)
rule_pointToCell(yfield, pyfield)
rule_pointToCell(hfield, phfield)
vfield (lhs) ::= RECONSTRUCT LPAREN ssfield (a) RPAREN.
{
lhs = Foam::fvc::reconstruct(make_obj(a)).ptr();
}
/*---------------------------------------------------------------------------*\
* Surface field composition
\*---------------------------------------------------------------------------*/
rule_mag_logical(ssfield, slfield)
rules_mag_functions(ssfield, ssfield)
rules_mag_functions(ssfield, svfield)
rules_mag_functions(ssfield, stfield)
rules_mag_functions(ssfield, syfield)
rules_mag_functions(ssfield, shfield)
rule_vector_zip(svfield, ssfield, VECTOR)
rule_tensor_zip(stfield, ssfield, TENSOR)
rule_symTensor_zip(syfield, ssfield, SYM_TENSOR)
rule_sphTensor_zip(shfield, ssfield, SPH_TENSOR)
rule_vector_components(ssfield, svfield)
rule_tensor_components(ssfield, stfield)
rule_symTensor_components(ssfield, syfield)
rule_sphTensor_components(ssfield, shfield)
rule_tensor_transpose(stfield)
rule_symTensor_transpose(syfield)
rule_sphTensor_transpose(shfield)
rule_tensor_unzipDiag(svfield, syfield)
rule_tensor_unzipAll(svfield, stfield)
rule_cellToFace(ssfield, sfield)
rule_cellToFace(svfield, vfield)
rule_cellToFace(stfield, tfield)
rule_cellToFace(syfield, yfield)
rule_cellToFace(shfield, hfield)
/*---------------------------------------------------------------------------*\
* Point field composition
* - Use primitiveField directly
dnl
pushdef([field_write_access], [($1).primitiveFieldRef()])dnl
pushdef([field_read_access], [($1).primitiveField()])dnl
dnl
\*---------------------------------------------------------------------------*/
rule_mag_logical(psfield, plfield)
rules_mag_functions(psfield, psfield)
rules_mag_functions(psfield, pvfield)
rules_mag_functions(psfield, ptfield)
rules_mag_functions(psfield, pyfield)
rules_mag_functions(psfield, phfield)
rule_vector_zip(pvfield, psfield, VECTOR)
rule_tensor_zip(ptfield, psfield, TENSOR)
rule_symTensor_zip(pyfield, psfield, SYM_TENSOR)
rule_sphTensor_zip(phfield, psfield, SPH_TENSOR)
rule_vector_components(psfield, pvfield)
rule_tensor_components(psfield, ptfield)
rule_symTensor_components(psfield, pyfield)
rule_sphTensor_components(psfield, phfield)
rule_tensor_transpose(ptfield)
rule_symTensor_transpose(pyfield)
rule_sphTensor_transpose(phfield)
rule_tensor_unzipDiag(pvfield, pyfield)
rule_tensor_unzipAll(pvfield, ptfield)
rule_cellToPoint(psfield, sfield)
rule_cellToPoint(pvfield, vfield)
rule_cellToPoint(ptfield, tfield)
rule_cellToPoint(pyfield, yfield)
rule_cellToPoint(phfield, hfield)
dnl/* Restore definitions
popdef([field_write_access])dnl
popdef([field_read_access])dnl
dnl*/
// ************************************************************************* //
dnl/* Standard m4 quoting
changequote([`],['])dnl
dnl*/
%code
{
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::expressions::volumeExpr::parser::stop()
{
if (lemon_)
{
ParseFree(lemon_, ::operator delete);
#ifndef NDEBUG
ParseTrace(nullptr, nullptr);
#endif
lemon_ = nullptr;
}
}
void Foam::expressions::volumeExpr::parser::start(parseDriver& driver_)
{
this->stop();
lemon_ = ParseAlloc(::operator new, &driver_);
if (debug || driver_.debugParser())
{
#ifndef NDEBUG
ParseTrace(stderr, const_cast<char*>(prompt_));
#endif
}
}
void Foam::expressions::volumeExpr::parser::parse
(
int tokenId,
scanToken* tokenVal
)
{
Parse(lemon_, tokenId, tokenVal);
}
Foam::word Foam::expressions::volumeExpr::parser::nameOfToken
(
int tokenId
) const
{
#ifndef NDEBUG
if
(
tokenId > 0
&& unsigned(tokenId) < (sizeof(yyTokenName) / sizeof(char*))
)
{
return yyTokenName[tokenId];
}
return "<invalid>";
#else
return word();
#endif
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End of %code
// ************************************************************************* //

View File

@ -0,0 +1,139 @@
divert(-1)dnl
#-----------------------------------*- m4 -*-----------------------------------
# ========= |
# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
# \\ / O peration |
# \\ / A nd | www.openfoam.com
# \\/ M anipulation |
#------------------------------------------------------------------------------
# Copyright (C) 2019 OpenCFD Ltd.
#------------------------------------------------------------------------------
# License
# This file is part of OpenFOAM, licensed under GNU General Public License
# <http://www.gnu.org/licenses/>.
#
# Description
# Driver-specific m4/lemon macros for volume expressions.
#
#------------------------------------------------------------------------------
include(`m4/lemon/base-setup.m4')dnl
include([m4/lemon/operator-precedence.m4])dnl
dnl
include([m4/lemon/rules-standard.m4])dnl
include([m4/lemon/rules-operations.m4])dnl
include([m4/lemon/rules-functions.m4])dnl
include([m4/lemon/rules-components.m4])dnl
include([m4/lemon/rules-fields-components.m4])dnl
include([m4/lemon/rules-scalar-logic.m4])dnl
dnl
divert(-1)dnl
#------------------------------------------------------------------------------
# Driver rules
#------------------------------------------------------------------------------
define([rules_driver_volume_functions],
[dnl
rule_driver_select(_logic_, CSET, field_cellSet)dnl
rule_driver_select(_logic_, CZONE, field_cellZone)dnl
dnl
rule_driver_nullary(_scalar_, CELL_VOLUME, field_cellVolume)dnl
rule_driver_nullary(_vector_, POS, field_cellCentre)dnl CELL_CENTRE
dnl
rule_driver_inplace_unary(_scalar_, WEIGHT_AVERAGE, volAverage)dnl
rule_driver_inplace_unary(_vector_, WEIGHT_AVERAGE, volAverage)dnl
rule_driver_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, volAverage)dnl
rule_driver_inplace_unary(_symTensor_, WEIGHT_AVERAGE, volAverage)dnl
rule_driver_inplace_unary(_tensor_, WEIGHT_AVERAGE, volAverage)dnl
dnl
rule_driver_inplace_unary(_scalar_, WEIGHT_SUM, volSum)dnl
rule_driver_inplace_unary(_vector_, WEIGHT_SUM, volSum)dnl
rule_driver_inplace_unary(_sphTensor_, WEIGHT_SUM, volSum)dnl
rule_driver_inplace_unary(_symTensor_, WEIGHT_SUM, volSum)dnl
rule_driver_inplace_unary(_tensor_, WEIGHT_SUM, volSum)dnl
dnl
])
define([rules_driver_surface_functions],
[dnl
rule_driver_select(_logic_, FSET, field_faceSet)dnl
rule_driver_select(_logic_, FZONE, field_faceZone)dnl
dnl
rule_driver_nullary(_scalar_, FACE_AREA, field_faceArea)dnl
rule_driver_nullary(_vector_, FACE_CENTRE, field_faceCentre)dnl
rule_driver_nullary(_vector_, FACE_EXPR, field_areaNormal)dnl
dnl
rule_driver_inplace_unary(_scalar_, WEIGHT_AVERAGE, areaAverage)dnl
rule_driver_inplace_unary(_vector_, WEIGHT_AVERAGE, areaAverage)dnl
rule_driver_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, areaAverage)dnl
rule_driver_inplace_unary(_symTensor_, WEIGHT_AVERAGE, areaAverage)dnl
rule_driver_inplace_unary(_tensor_, WEIGHT_AVERAGE, areaAverage)dnl
dnl
rule_driver_inplace_unary(_scalar_, WEIGHT_SUM, areaSum)dnl
rule_driver_inplace_unary(_vector_, WEIGHT_SUM, areaSum)dnl
rule_driver_inplace_unary(_sphTensor_, WEIGHT_SUM, areaSum)dnl
rule_driver_inplace_unary(_symTensor_, WEIGHT_SUM, areaSum)dnl
rule_driver_inplace_unary(_tensor_, WEIGHT_SUM, areaSum)dnl
dnl
])
define([rules_driver_point_functions],
[dnl
rule_driver_select(_logic_, PSET, field_pointSet)dnl
rule_driver_select(_logic_, PZONE, field_pointZone)dnl
dnl
rule_driver_nullary(_vector_, POINTS, field_pointField)dnl
dnl
dnl NB use non-driver versions for points - ie, unweighted
dnl
rule_inplace_unary(_scalar_, WEIGHT_AVERAGE, Foam::gAverage)dnl
rule_inplace_unary(_vector_, WEIGHT_AVERAGE, Foam::gAverage)dnl
rule_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl
rule_inplace_unary(_symTensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl
rule_inplace_unary(_tensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl
dnl
rule_inplace_unary(_scalar_, WEIGHT_SUM, Foam::gSum)dnl
rule_inplace_unary(_vector_, WEIGHT_SUM, Foam::gSum)dnl
rule_inplace_unary(_sphTensor_, WEIGHT_SUM, Foam::gSum)dnl
rule_inplace_unary(_symTensor_, WEIGHT_SUM, Foam::gSum)dnl
rule_inplace_unary(_tensor_, WEIGHT_SUM, Foam::gSum)dnl
dnl
])
#------------------------------------------------------------------------------
# rule_cellToFace(out, in)
# rule_cellToPoint(out, in)
# rule_pointToCell(out, in)
#
# Description
# Production rules for driver cellToFace, cellToPoint, pointToCell,
# methods
#------------------------------------------------------------------------------
define([rule_cellToFace],
[rule_driver_unary($1, $2, CELL_TO_FACE, cellToFace)])
define([rule_cellToPoint],
[rule_driver_unary($1, $2, CELL_TO_POINT, cellToPoint)])
define([rule_pointToCell],
[rule_driver_unary($1, $2, POINT_TO_CELL, pointToCell)])
#------------------------------------------------------------------------------
# Standard rules for fields: declaration, new/get, driver functions etc.
include([m4/lemon/rules-fields.m4])dnl
divert(-1)dnl
#------------------------------------------------------------------------------
# Additional safety measures
undefine([substr])dnl # Avoid collision with C/C++ naming
#------------------------------------------------------------------------------
divert(0)dnl

View File

@ -0,0 +1,106 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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::volumeExpr::parser
Description
Lemon parser interface for volume expressions grammar
\*---------------------------------------------------------------------------*/
#ifndef expressions_volumeExprParser_H
#define expressions_volumeExprParser_H
#include "volumeExprFwd.H"
namespace Foam
{
namespace expressions
{
namespace volumeExpr
{
/*---------------------------------------------------------------------------*\
Class parser Declaration
\*---------------------------------------------------------------------------*/
class parser
{
// Private Data
//- Prompt for parser tracing
static constexpr const char* const prompt_ = "volExpr:";
//- The lemon parser (demand-driven)
void* lemon_;
public:
//- Local object debugging
int debug;
// Constructors
//- Construct null
parser() : lemon_(nullptr), debug(volumeExpr::debug) {}
//- Destructor, deletes parser backend
~parser()
{
stop();
}
// Member Functions
//- Start parsing, with the given driver context
void start(parseDriver& driver_);
//- Stop parsing, freeing the allocated parser
void stop();
//- Push token/value to parser
void parse(int tokenId, scanToken* tokenVal);
//- Return the text name corresponding to the tokenId
word nameOfToken(int tokenId) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace volumeExpr
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,162 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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::volumeExpr::scanner
Description
Ragel lexer/scanner interface for volume expressions.
Note
Ragel code generated with the ./createCode script.
\*---------------------------------------------------------------------------*/
#ifndef expressions_volumeExprScanner_H
#define expressions_volumeExprScanner_H
#include "volumeExprFwd.H"
#include "scalar.H"
namespace Foam
{
namespace expressions
{
namespace volumeExpr
{
/*---------------------------------------------------------------------------*\
Class scanToken Declaration
\*---------------------------------------------------------------------------*/
union scanToken
{
Foam::label ivalue;
Foam::scalar svalue;
Foam::word* name;
//- Null construct, bit-wise zero for union content
scanToken() : ivalue(0) {}
};
/*---------------------------------------------------------------------------*\
Class scanner Declaration
\*---------------------------------------------------------------------------*/
class scanner
{
// Private Data
//- Wrapped lemon parser
parser* parser_;
// Ragel code state, action
int cs, act;
// Private Member Functions
//- Dispatch .method to parser (if known) or Fatal
bool dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
) const;
//- Dispatch identifier to parser (if possible) or Fatal
bool dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
) const;
public:
//- Local debugging
int debug;
// Constructors
//- Construct null, optionally setting debugging
explicit scanner(bool withDebug = false)
:
parser_(nullptr),
debug(volumeExpr::debug)
{
if (withDebug)
{
debug |= 4;
}
}
//- Destructor, deletes parser
~scanner();
// Member Functions
//- Evaluate sub-string
bool process
(
const std::string& str, size_t pos, size_t len,
parseDriver& driver_
);
//- Evaluate sub-string
bool process
(
const std::string& str, size_t pos,
parseDriver& driver_
)
{
return process(str, pos, std::string::npos, driver_);
}
//- Evaluate string
bool process(const std::string& str, parseDriver& driver_)
{
return process(str, 0, std::string::npos, driver_);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace volumeExpr
} // End namespace expressions
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,694 @@
/*--------------------------------*- C++ -*----------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 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/>.
Description
Ragel lexer interface for lemon grammar of volume field expressions
\*---------------------------------------------------------------------------*/
#include "volumeExprScanner.H"
#include "volumeExprDriver.H"
#include "volumeExprLemonParser.h"
#include "volumeExprParser.H"
#include "Enum.H"
#include "macros.H"
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wold-style-cast"
// Debugging to stderr
#undef DebugInfo
#define DebugInfo if (debug) InfoErr
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
//- Paste token prefix
#define TOKEN_OF(T) TOK_##T
//- An {int, c_str} enum pairing
#define TOKEN_PAIR(Name,T) { TOKEN_OF(T), Name }
// Special handling for these known (stashed) look-back types
static const Enum<int> lookBehindTokenEnums
({
TOKEN_PAIR("cellSet", CSET),
TOKEN_PAIR("faceSet", FSET),
TOKEN_PAIR("pointSet", PSET),
TOKEN_PAIR("cellZone", CZONE),
TOKEN_PAIR("faceZone", FZONE),
TOKEN_PAIR("pointZone", PZONE),
});
#define HAS_LOOKBEHIND_TOKENS
// Special handling of predefined method types. Eg, .x(), .y(), ...
static const Enum<int> fieldMethodEnums
({
TOKEN_PAIR("x", CMPT_X),
TOKEN_PAIR("y", CMPT_Y),
TOKEN_PAIR("z", CMPT_Z),
TOKEN_PAIR("xx", CMPT_XX),
TOKEN_PAIR("xy", CMPT_XY),
TOKEN_PAIR("xz", CMPT_XZ),
TOKEN_PAIR("yx", CMPT_YX),
TOKEN_PAIR("yy", CMPT_YY),
TOKEN_PAIR("yz", CMPT_YZ),
TOKEN_PAIR("zx", CMPT_ZX),
TOKEN_PAIR("zy", CMPT_ZY),
TOKEN_PAIR("zz", CMPT_ZZ),
TOKEN_PAIR("ii", CMPT_II),
TOKEN_PAIR("diag", DIAG), /* tensors only */
TOKEN_PAIR("T", TRANSPOSE), /* tensors only */
});
// Known field-token types
static const Enum<int> fieldTokenEnums
({
#ifdef TOK_SCALAR_ID
TOKEN_PAIR(volScalarField::typeName.c_str(), SCALAR_ID),
TOKEN_PAIR(volVectorField::typeName.c_str(), VECTOR_ID),
TOKEN_PAIR(volTensorField::typeName.c_str(), TENSOR_ID),
TOKEN_PAIR(volSymmTensorField::typeName.c_str(), SYM_TENSOR_ID),
TOKEN_PAIR(volSphericalTensorField::typeName.c_str(), SPH_TENSOR_ID),
#else
#error TOK_SCALAR_ID not defined
#endif
#ifdef TOK_SSCALAR_ID
TOKEN_PAIR(surfaceScalarField::typeName.c_str(), SSCALAR_ID),
TOKEN_PAIR(surfaceVectorField::typeName.c_str(), SVECTOR_ID),
TOKEN_PAIR(surfaceTensorField::typeName.c_str(), STENSOR_ID),
TOKEN_PAIR(surfaceSymmTensorField::typeName.c_str(), SSYM_TENSOR_ID),
TOKEN_PAIR(surfaceSphericalTensorField::typeName.c_str(), SSPH_TENSOR_ID),
#else
#warning TOK_SSCALAR_ID not defined
#endif
#ifdef TOK_PSCALAR_ID
TOKEN_PAIR(pointScalarField::typeName.c_str(), PSCALAR_ID),
TOKEN_PAIR(pointVectorField::typeName.c_str(), PVECTOR_ID),
TOKEN_PAIR(pointTensorField::typeName.c_str(), PTENSOR_ID),
TOKEN_PAIR(pointSymmTensorField::typeName.c_str(), PSYM_TENSOR_ID),
TOKEN_PAIR(pointSphericalTensorField::typeName.c_str(), PSPH_TENSOR_ID),
#else
#warning TOK_PSCALAR_ID not defined
#endif
});
// Simple compile-time function name declarations.
// Useful for handling driver-specific dispatching, or functions that
// are not universally available.
static const Enum<int> funcTokenEnums
({
#ifdef TOK_FLOOR
TOKEN_PAIR("floor", FLOOR),
TOKEN_PAIR("ceil", CEIL),
TOKEN_PAIR("round", ROUND),
#endif
#ifdef TOK_HYPOT /* Can use hypot? */
TOKEN_PAIR("hypot", HYPOT),
#endif
// Already parsed as function: TOKEN_PAIR("pos", CELL_CENTRE),
TOKEN_PAIR("point", POINT_EXPR), // Point value
TOKEN_PAIR("face", FACE_EXPR), // Face value, Face areaNormal
TOKEN_PAIR("cellToPoint", CELL_TO_POINT),
TOKEN_PAIR("cellToFace", CELL_TO_FACE),
TOKEN_PAIR("pointToCell", POINT_TO_CELL),
TOKEN_PAIR("area", FACE_AREA),
TOKEN_PAIR("vol", CELL_VOLUME),
TOKEN_PAIR("fpos", FACE_CENTRE),
TOKEN_PAIR("pts", POINTS),
});
} // End namespace Foam
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
namespace Foam
{
// Classifying token type based on an identifier name is indeed ugly.
//
// 1)
// Handle special cases (eg, cellSet,...) first that have been tagged
// as expected content with the stashed "look-behind" token.
// Handle not-found errors here directly.
//
// 2)
// Fallback to determining which field-type (volScalarField etc) the name
// corresponds to.
// Handle not-found errors by return -1.
//
static int driverTokenType
(
const expressions::volumeExpr::parseDriver& driver_,
const word& ident
)
{
// Get stashed "look-behind" to decide what type of identifier we expect
const int lookBehind = driver_.resetStashedTokenId();
if (lookBehind && lookBehindTokenEnums.found(lookBehind))
{
bool good = false;
switch (lookBehind)
{
case TOK_CSET : good = driver_.isCellSet(ident); break;
case TOK_FSET : good = driver_.isFaceSet(ident); break;
case TOK_PSET : good = driver_.isPointSet(ident); break;
case TOK_CZONE : good = driver_.isCellZone(ident); break;
case TOK_FZONE : good = driver_.isFaceZone(ident); break;
case TOK_PZONE : good = driver_.isPointZone(ident); break;
}
if (good)
{
return TOK_IDENTIFIER;
}
// Fatal
driver_.reportFatal
(
"Error no " + lookBehindTokenEnums.get(lookBehind) + ": " + ident
);
return -2; // Extra safety
}
// 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; \
}
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);
}
#endif
// Point variables
#ifdef TOK_PSCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(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);
}
#endif
// Volume variables
#ifdef TOK_SCALAR_ID
{
#undef checkFieldToken
#define checkFieldToken(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);
}
#endif
#undef checkFieldToken
// Check registered fields and/or disk-files
{
const word fieldType(driver_.getFieldClassName(ident));
int tokType = fieldTokenEnums.get(fieldType, -1);
if (tokType > 0)
{
return tokType;
}
}
return -1;
}
} // End anonymous namespace
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Ragel machine definition
// Ragel variables (p, pe, eof, cs, top, stack, ts, te, act) defined later...
//
// Can use 'variable p xxx;' etc to change these names
#define EMIT_TOKEN(T) \
driver_.parsePosition() = (ts-buf); \
DebugInfo<< STRINGIFY(T) << ": " << driver_.parsePosition() << nl; \
parser_->parse(TOKEN_OF(T), nullptr); \
driver_.parsePosition() = (p-buf);
%%{
machine volumeExpr;
write data;
action 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))
{
parser_->parse(TOKEN_OF(NUMBER), &scanTok);
}
else
{
driver_.reportFatal
(
"Error parsing number: " + std::string(ts, te-ts)
);
}
driver_.parsePosition() = (p-buf);
}
action emit_ident {
driver_.parsePosition() = (ts-buf);
dispatch_ident(driver_, scanTok, 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));
driver_.parsePosition() = (p-buf);
}
decimal = ((digit* '.' digit+) | (digit+ '.'?)) ;
number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ;
ident = ((alpha|'_') . ((alnum|[._])**)) ;
dquoted = '"' [^\"]+ '"' ;
squoted = "'" [^\']+ "'" ;
## The scanner
main := |*
space*;
number => emit_number;
## operators
'!' =>{ EMIT_TOKEN(NOT); };
'%' =>{ EMIT_TOKEN(PERCENT); };
'(' =>{ EMIT_TOKEN(LPAREN); };
')' =>{ EMIT_TOKEN(RPAREN); };
'*' =>{ EMIT_TOKEN(TIMES); };
'+' =>{ EMIT_TOKEN(PLUS); };
'-' =>{ EMIT_TOKEN(MINUS); };
',' =>{ EMIT_TOKEN(COMMA); };
'.' =>{ EMIT_TOKEN(DOT); };
'/' =>{ EMIT_TOKEN(DIVIDE); };
'?' =>{ EMIT_TOKEN(QUESTION); };
':' =>{ EMIT_TOKEN(COLON); };
'<' =>{ EMIT_TOKEN(LESS); };
'<=' =>{ EMIT_TOKEN(LESS_EQ); };
'>' =>{ EMIT_TOKEN(GREATER); };
'>=' =>{ EMIT_TOKEN(GREATER_EQ); };
'==' =>{ EMIT_TOKEN(EQUAL); };
'!=' =>{ EMIT_TOKEN(NOT_EQUAL); };
'&&' =>{ EMIT_TOKEN(LAND); };
'||' =>{ EMIT_TOKEN(LOR); };
'&' =>{ EMIT_TOKEN(BIT_AND); };
## Not needed? '|' =>{ EMIT_TOKEN(BIT_OK); };
'^' =>{ EMIT_TOKEN(BIT_XOR); };
## Some '.method' - Error if unknown
'.' alpha+ => emit_method;
## Regular functions
"pi" =>{ EMIT_TOKEN(PI); };
"degToRad" =>{ EMIT_TOKEN(DEG_TO_RAD); };
"radToDeg" =>{ EMIT_TOKEN(RAD_TO_DEG); };
"exp" =>{ EMIT_TOKEN(EXP); };
"log" =>{ EMIT_TOKEN(LOG); };
"log10" =>{ EMIT_TOKEN(LOG10); };
"pow" =>{ EMIT_TOKEN(POW); };
"sqr" =>{ EMIT_TOKEN(SQR); };
"sqrt" =>{ EMIT_TOKEN(SQRT); };
"cbrt" =>{ EMIT_TOKEN(CBRT); };
"sin" =>{ EMIT_TOKEN(SIN); };
"cos" =>{ EMIT_TOKEN(COS); };
"tan" =>{ EMIT_TOKEN(TAN); };
"asin" =>{ EMIT_TOKEN(ASIN); };
"acos" =>{ EMIT_TOKEN(ACOS); };
"atan" =>{ EMIT_TOKEN(ATAN); };
"atan2" =>{ EMIT_TOKEN(ATAN2); };
"sinh" =>{ EMIT_TOKEN(SINH); };
"cosh" =>{ EMIT_TOKEN(COSH); };
"tanh" =>{ EMIT_TOKEN(TANH); };
"mag" =>{ EMIT_TOKEN(MAG); };
"magSqr" =>{ EMIT_TOKEN(MAGSQR); };
"pos" =>{ EMIT_TOKEN(POS); };
"neg" =>{ EMIT_TOKEN(NEG); };
"pos0" =>{ EMIT_TOKEN(POS0); };
"neg0" =>{ EMIT_TOKEN(NEG0); };
"sign" =>{ EMIT_TOKEN(SIGN); };
## Reductions, or other special functions
"min" =>{ EMIT_TOKEN(MIN); };
"max" =>{ EMIT_TOKEN(MAX); };
"average" =>{ EMIT_TOKEN(AVERAGE); };
"sum" =>{ EMIT_TOKEN(SUM); };
"weightAverage" =>{ EMIT_TOKEN(WEIGHT_AVERAGE); };
"weightSum" =>{ EMIT_TOKEN(WEIGHT_SUM); };
"rand" =>{ EMIT_TOKEN(RAND); };
## Types
"bool" =>{ EMIT_TOKEN(BOOL); };
"vector" =>{ EMIT_TOKEN(VECTOR); };
"tensor" =>{ EMIT_TOKEN(TENSOR); };
"symmTensor" =>{ EMIT_TOKEN(SYM_TENSOR); };
"sphericalTensor" =>{ EMIT_TOKEN(SPH_TENSOR); };
## Single value (constants, etc)
"Zero" =>{ EMIT_TOKEN(ZERO); };
"true" =>{ EMIT_TOKEN(LTRUE); };
"false" =>{ EMIT_TOKEN(LFALSE); };
"tensor::I" =>{ EMIT_TOKEN(UNIT_TENSOR); };
"time" =>{ EMIT_TOKEN(TIME); };
## Identifier (field, etc - error if unknown)
## Handle 'bare' names and single/double quoted ones
ident => emit_ident;
dquoted => emit_ident;
squoted => emit_ident;
space*;
*|;
}%%
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::expressions::volumeExpr::scanner::~scanner()
{
if (parser_)
{
delete parser_;
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::expressions::volumeExpr::scanner::dispatch_method
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
) const
{
if (ident[0] == '.')
{
ident.erase(0, 1);
}
DebugInfo
<< "Method:" << ident
<< " at " << driver_.parsePosition() << nl;
const int methType = fieldMethodEnums.get(ident, -1);
if (methType > 0)
{
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
return true;
}
driver_.reportFatal("Unknown method: " + ident);
return false;
}
bool Foam::expressions::volumeExpr::scanner::dispatch_ident
(
const parseDriver& driver_,
scanToken& scanTok,
word&& ident
) const
{
int tokType = -1;
const bool quoted =
(
(ident.front() == '"' || ident.front() == '\'')
&& (ident.front() == ident.back())
);
if (quoted)
{
ident.erase(ident.size()-1);
ident.erase(0, 1);
}
else
{
// Check for function name
tokType = funcTokenEnums.get(ident, -1);
if (tokType > 0)
{
DebugInfo
<< "Emit:" << ident << " function:"
<< parser_->nameOfToken(tokType) << nl;
parser_->parse(tokType, nullptr);
return true;
}
#ifdef HAS_LOOKBEHIND_TOKENS
// Specials such "cset" also reset the look-behind
tokType = lookBehindTokenEnums.get(ident, -1);
if (tokType > 0)
{
DebugInfo
<< "Emit:" << ident << " as look-behind:"
<< parser_->nameOfToken(tokType) << nl;
driver_.resetStashedTokenId(tokType);
parser_->parse(tokType, nullptr);
return true;
}
#endif
}
// Can also peek at stashed "look-behind"
// const int lookBehind = driver_.stashedTokenId();
tokType = driverTokenType(driver_, ident);
if (tokType > 0)
{
DebugInfo
<< "Emit:" << ident << " token:"
<< parser_->nameOfToken(tokType) << nl;
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
return true;
}
// Not found? Attempt to strip off '.x' endings etc,
// but not when quoted
const auto dot = ident.rfind('.');
const int methType =
(
quoted || dot == std::string::npos
? -1
: fieldMethodEnums.get(ident.substr(dot+1), -1)
);
if
(
methType > 0
&& (tokType = driverTokenType(driver_, ident.substr(0, dot))) > 0
)
{
DebugInfo
<< "Emit:" << ident.substr(0, dot).c_str() << " token:"
<< parser_->nameOfToken(tokType) << " with "
<< ident.substr(dot).c_str() << " token:"
<< parser_->nameOfToken(methType) << nl;
// The field (before the ".")
ident.erase(dot);
scanTok.name = new Foam::word(std::move(ident));
parser_->parse(tokType, &scanTok);
// Dispatch '.' and "method" separately
parser_->parse(TOK_DOT, nullptr);
parser_->parse(methType, nullptr);
return true;
}
driver_.reportFatal
(
"Object " + ident + " does not exist or wrong type"
);
return false;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::expressions::volumeExpr::scanner::process
(
const std::string& str,
size_t strBeg,
size_t strLen,
parseDriver& driver_
)
{
// Save debug value
const int oldDebug = debug;
if (driver_.debugScanner())
{
debug |= 4;
}
if (!parser_)
{
parser_ = new parser();
}
driver_.content(str, strBeg, strLen);
size_t strEnd = str.length();
if (strBeg > str.length())
{
strBeg = str.length();
}
else if (strLen != std::string::npos)
{
strLen += strBeg;
if (strLen < str.length())
{
strEnd = strLen;
}
}
parser_->start(driver_);
// Scan token type
scanToken scanTok;
// Ragel token start/end (required naming)
const char* ts;
const char* te;
// Local buffer data.
// - p, pe, eof are required Ragel naming
// - buf is our own naming
const char* buf = &(str[strBeg]);
const char* eof = &(str[strEnd]);
const char* p = buf;
const char* pe = eof;
// Initialize FSM variables
%%{write init;}%% /* ^^^ FSM initialization here ^^^ */;
%%{write exec;}%% /* ^^^ FSM execution here ^^^ */;
if (%%{write error;}%% == cs)
{
driver_.reportFatal("Parse error while scanning", (p-buf));
}
if (p != eof)
{
driver_.reportFatal("Parsing failed with remaining content", (p-buf));
}
// Terminate parser execution
parser_->parse(0, nullptr);
parser_->stop();
// Restore debug value
debug = oldDebug;
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,55 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
location "0";
object T;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 0 0 1 0 0 0];
internalField uniform 300;
boundaryField
{
inlet
{
type outletMappedUniformInletHeatAddition;
outletPatch outlet1;
Q 5; // Heat addition in W
TMin 300;
TMax 500;
value $internalField;
}
outlet1
{
type inletOutlet;
inletValue $internalField;
value $internalField;
}
outlet2
{
type inletOutlet;
inletValue $internalField;
value $internalField;
}
defaultFaces
{
type zeroGradient;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,50 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
object U;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 1 -1 0 0 0 0];
internalField uniform (0 0 0);
boundaryField
{
inlet
{
type pressureInletOutletVelocity;
value uniform (0 0 0);
}
outlet1
{
type inletOutlet;
inletValue uniform (0 0 0);
value uniform (0 0 0);
}
outlet2
{
type inletOutlet;
inletValue uniform (0 0 0);
value uniform (0 0 0);
}
defaultFaces
{
type fixedValue;
value uniform (0 0 0);
}
}
// ************************************************************************* //

View File

@ -0,0 +1,50 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
location "0";
object alphat;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [1 -1 -1 0 0 0 0];
internalField uniform 1e-3;
boundaryField
{
inlet
{
type calculated;
value uniform 0;
}
outlet1
{
type calculated;
value uniform 0;
}
outlet2
{
type calculated;
value uniform 0;
}
defaultFaces
{
type compressible::alphatWallFunction;
value $internalField;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,53 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
location "0";
object epsilon;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 2 -3 0 0 0 0];
internalField uniform 200;
boundaryField
{
inlet
{
type turbulentMixingLengthDissipationRateInlet;
mixingLength 0.01; // 1cm - half channel height
value $internalField;
}
outlet1
{
type inletOutlet;
inletValue $internalField;
value $internalField;
}
outlet2
{
type inletOutlet;
inletValue $internalField;
value $internalField;
}
defaultFaces
{
type epsilonWallFunction;
value $internalField;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,51 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
location "0";
object k;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 2 -2 0 0 0 0];
internalField uniform 1;
boundaryField
{
inlet
{
type turbulentIntensityKineticEnergyInlet;
intensity 0.05; // 5% turbulent intensity
value $internalField;
}
outlet1
{
type inletOutlet;
inletValue $internalField;
}
outlet2
{
type inletOutlet;
inletValue $internalField;
}
defaultFaces
{
type kqRWallFunction;
value $internalField;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,44 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
object nuTilda;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 2 -1 0 0 0 0];
internalField uniform 0;
boundaryField
{
inlet
{
type zeroGradient;
}
outlet1
{
type zeroGradient;
}
outlet2
{
type zeroGradient;
}
defaultFaces
{
type zeroGradient;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,50 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
location "0";
object nut;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [0 2 -1 0 0 0 0];
internalField uniform 0;
boundaryField
{
inlet
{
type calculated;
value uniform 0;
}
outlet1
{
type calculated;
value uniform 0;
}
outlet2
{
type calculated;
value uniform 0;
}
defaultFaces
{
type nutkWallFunction;
value uniform 0;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,71 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volScalarField;
object p;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dimensions [1 -1 -2 0 0 0 0];
internalField uniform 1e5;
boundaryField
{
inlet
{
type uniformTotalPressure;
gamma 1.2;
p0 table
(
(0 1e5)
(1 1.4e5)
);
}
outlet1
{
type fixedValue;
value $internalField;
}
outlet1
{
type exprFixedValue;
value $internalField;
valueExpr "0.5*(pInlet + pOutlet2)";
variables
(
"pInlet{inlet} = weightAverage(p)"
"pOutlet2{outlet2} = p"
);
// debug true;
// debugScanner true;
// debugParser true;
}
outlet2
{
type fixedValue;
value $internalField;
}
defaultFaces
{
type zeroGradient;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,4 @@
15/8/8 Simple T-junction. Inlet on left, one outlet at bottom, one at top.
To test multiple outlets.
Enable debugScanner/debugParser for a verbose view of the parsing engine.

View File

@ -0,0 +1,22 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object fvOptions;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
viscousDissipation
{
type viscousDissipation;
enabled true;
}
// ************************************************************************* //

View File

@ -0,0 +1,48 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object thermophysicalProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
thermoType
{
type hePsiThermo;
mixture pureMixture;
transport sutherland;
thermo hConst;
equationOfState perfectGas;
specie specie;
energy sensibleEnthalpy;
}
mixture
{
specie
{
molWeight 28.9;
}
thermodynamics
{
Cp 1007;
Hf 0;
}
transport
{
As 1.4792e-06;
Ts 116;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,30 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object turbulenceProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
simulationType RAS;
RAS
{
RASModel kEpsilon;
turbulence on;
printCoeffs on;
}
// ************************************************************************* //

View File

@ -0,0 +1,127 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object blockMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// outlet1
// +-+
// | |
// | |
// | |
// | |
// +-----------+ |
// |inlet |
// +-----------+ |
// | |
// | |
// | |
// | |
// +-+
// outlet2
scale 1;
vertices
(
(0.0 -0.01 0) //0
(0.2 -0.01 0)
(0.2 0.01 0) //2
(0.0 0.01 0)
(0.22 -0.01 0) //4
(0.22 0.01 0)
(0.2 -0.21 0) //6
(0.22 -0.21 0)
(0.2 0.21 0) //8
(0.22 0.21 0)
// Z
(0.0 -0.01 0.02) //0
(0.2 -0.01 0.02)
(0.2 0.01 0.02) //2
(0.0 0.01 0.02)
(0.22 -0.01 0.02) //4
(0.22 0.01 0.02)
(0.2 -0.21 0.02) //6
(0.22 -0.21 0.02)
(0.2 0.21 0.02) //8
(0.22 0.21 0.02)
);
blocks
(
// inlet block
hex (0 1 2 3 10 11 12 13) (50 5 5) simpleGrading (1 1 1)
// central block
hex (1 4 5 2 11 14 15 12) (5 5 5) simpleGrading (1 1 1)
// bottom block
hex (6 7 4 1 16 17 14 11) (5 50 5) simpleGrading (1 1 1)
// top block
hex (2 5 9 8 12 15 19 18) (5 50 5) simpleGrading (1 1 1)
);
edges
(
);
boundary
(
inlet
{
type patch;
faces
(
(0 10 13 3)
);
}
outlet1
{
type patch;
faces
(
(6 7 17 16)
);
}
outlet2
{
type patch;
faces
(
(8 18 19 9)
);
}
defaultFaces
{
type wall;
faces ();
}
);
mergePatchPairs
(
);
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object controlDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
application rhoPimpleFoam;
startFrom startTime;
startTime 0;
stopAt endTime;
endTime 1.0;
deltaT 0.001;
writeControl adjustable;
writeInterval 0.1;
purgeWrite 0;
writeFormat ascii;
writePrecision 6;
writeCompression off;
timeFormat general;
timePrecision 6;
runTimeModifiable true;
adjustTimeStep yes;
maxCo 3;
// ************************************************************************* //

View File

@ -0,0 +1,57 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSchemes;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
ddtSchemes
{
default Euler;
}
gradSchemes
{
default Gauss linear;
}
divSchemes
{
default none;
div(phi,U) Gauss limitedLinearV 1;
div(phi,k) Gauss limitedLinear 1;
div(phi,epsilon) Gauss limitedLinear 1;
div(phi,h) Gauss limitedLinear 1;
div(phi,R) Gauss limitedLinear 1;
div(R) Gauss linear;
div(phi,K) Gauss linear;
div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear;
}
laplacianSchemes
{
default Gauss linear corrected;
}
interpolationSchemes
{
default linear;
}
snGradSchemes
{
default corrected;
}
// ************************************************************************* //

View File

@ -0,0 +1,70 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "system";
object fvSolution;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
solvers
{
p
{
solver GAMG;
tolerance 1e-08;
relTol 0.01;
smoother GaussSeidel;
}
pFinal
{
solver GAMG;
tolerance 1e-08;
relTol 0;
smoother GaussSeidel;
}
"(rho|U|k|epsilon|h)"
{
solver smoothSolver;
smoother symGaussSeidel;
tolerance 1e-07;
relTol 0.05;
}
"(rho|U|k|epsilon|h)Final"
{
$U;
tolerance 1e-07;
relTol 0;
}
}
PIMPLE
{
momentumPredictor no;
transonic no;
nOuterCorrectors 1;
nCorrectors 5;
nNonOrthogonalCorrectors 0;
}
relaxationFactors
{
equations
{
".*" 1;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,32 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object setExprBoundaryFieldsDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
pattern
{
field T;
expressions
(
{
patch outlet2;
target something;
expression #{ (pos().x() < 1e-4 ? 60 : 120) #};
}
);
}
// ************************************************************************* //

View File

@ -0,0 +1,53 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v1912 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object setExprFieldsDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
expressions
(
T
{
field T;
dimensions [0 0 0 1 0 0 0];
constants
{
centre (0.21 0 0.01);
}
variables
(
"radius = 0.1"
);
condition
#{
// Within the radius
(mag(pos() - $[(vector)constants.centre]) < radius)
// but only +ve y!
&& pos((pos() - $[(vector)constants.centre]).y()) > 0
#};
expression
#{
300
+ 200 * (1 - mag(pos() - $[(vector)constants.centre]) / radius)
#};
}
);
// ************************************************************************* //