ENH: driver/parser/scanner for volume expressions

This commit is contained in:
Mark Olesen
2019-12-03 12:34:40 +01:00
parent 82a1e32526
commit 20589430f4
19 changed files with 7563 additions and 17 deletions

View File

@ -265,6 +265,13 @@ $(patchExpr)/patchExprDriverFields.C
$(patchExpr)/patchExprLemonParser.lyy-m4 $(patchExpr)/patchExprLemonParser.lyy-m4
$(patchExpr)/patchExprScanner.cc $(patchExpr)/patchExprScanner.cc
volumeExpr = $(expr)/volume
$(volumeExpr)/volumeExpr.C
$(volumeExpr)/volumeExprDriver.C
$(volumeExpr)/volumeExprDriverFields.C
$(volumeExpr)/volumeExprLemonParser.lyy-m4
$(volumeExpr)/volumeExprScanner.cc
fvMatrices/fvMatrices.C fvMatrices/fvMatrices.C
fvMatrices/fvScalarMatrix/fvScalarMatrix.C fvMatrices/fvScalarMatrix/fvScalarMatrix.C

View File

@ -96,7 +96,7 @@ Foam::expressions::fvExprDriver::fvExprDriver
( (
bool cacheReadFields, bool cacheReadFields,
bool searchInMemory, bool searchInMemory,
bool searchOnDisc, bool searchFiles,
const dictionary& dict const dictionary& dict
) )
: :
@ -104,7 +104,7 @@ Foam::expressions::fvExprDriver::fvExprDriver
( (
cacheReadFields, cacheReadFields,
searchInMemory, searchInMemory,
searchOnDisc, searchFiles,
dict dict
), ),
globalScopes_(), globalScopes_(),
@ -142,7 +142,7 @@ Foam::expressions::fvExprDriver::fvExprDriver
( (
dict.lookupOrDefault("cacheReadFields", false), dict.lookupOrDefault("cacheReadFields", false),
dict.lookupOrDefault("searchInMemory", true), dict.lookupOrDefault("searchInMemory", true),
dict.lookupOrDefault("searchOnDisc", false), dict.lookupOrDefault("searchFiles", false),
dict dict
) )
{ {
@ -603,7 +603,7 @@ Foam::word Foam::expressions::fvExprDriver::getFieldClassName
} }
} }
if (searchOnDisc()) if (searchFiles())
{ {
return getHeaderClassName(this->mesh(), name); return getHeaderClassName(this->mesh(), name);
} }

View File

@ -382,7 +382,7 @@ public:
( (
bool cacheReadFields = false, bool cacheReadFields = false,
bool searchInMemory = true, bool searchInMemory = true,
bool searchOnDisc = false, bool searchFiles = false,
const dictionary& dict = dictionary::null const dictionary& dict = dictionary::null
); );

View File

@ -140,8 +140,8 @@ bool Foam::expressions::fvExprDriver::foundField
{ {
Info<< "fvExprDriver::foundField. Name: " << name Info<< "fvExprDriver::foundField. Name: " << name
<< " Type: " << Type::typeName << " Type: " << Type::typeName
<< " search memory:" << searchInMemory() << " registry:" << searchInMemory()
<< " disc:" << searchOnDisc() << endl; << " disk:" << searchFiles() << endl;
} }
// if (std::is_void<Type>::value) ... // if (std::is_void<Type>::value) ...
@ -155,30 +155,29 @@ bool Foam::expressions::fvExprDriver::foundField
{ {
if (debug) if (debug)
{ {
Info<< "Found " << name << " in memory" << endl; Info<< "Found registered: " << name << endl;
} }
return true; return true;
} }
if (debug) if (debug)
{ {
Info<< "No " << name << " of type " << Type::typeName Info<< "Registered " << name;
<< " found in memory";
if (ioptr) if (ioptr)
{ {
Info<< " but of type " << ioptr->headerClassName(); Info<< " type:" << ioptr->headerClassName();
} }
Info<< endl; Info<< ", not type:" << Type::typeName << nl;
} }
} }
if (searchOnDisc() && getTypeOfField(name) == Type::typeName) if (searchFiles() && getTypeOfField(name) == Type::typeName)
{ {
if (debug) if (debug)
{ {
Info<< "Found " << name << " on disc" << endl; Info<< "Found file: " << name << nl;
} }
return true; return true;
} }
@ -326,7 +325,7 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
{ {
if (debug) if (debug)
{ {
Info<< "Getting " << name << " from memory" << endl; Info<< "Retrieve registered: " << name << nl;
} }
const GeomField& origFld = obr.lookupObject<GeomField>(name); const GeomField& origFld = obr.lookupObject<GeomField>(name);
@ -356,7 +355,7 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
} }
} }
} }
else if (searchOnDisc() && getTypeOfField(name) == GeomField::typeName) else if (searchFiles() && getTypeOfField(name) == GeomField::typeName)
{ {
if (debug) if (debug)
{ {
@ -415,7 +414,7 @@ Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Could not find field " << name << "Could not find field " << name
<< " in memory or on disc" << endl << " in registry or on file-system" << nl
<< exit(FatalError); << exit(FatalError);
} }

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;
}
// ************************************************************************* //