diff --git a/applications/utilities/preProcessing/setExprBoundaryFields/Make/files b/applications/utilities/preProcessing/setExprBoundaryFields/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..c20222837bd1d4fb54a82ed4f4af6e6d5b3bd61e --- /dev/null +++ b/applications/utilities/preProcessing/setExprBoundaryFields/Make/files @@ -0,0 +1,3 @@ +setExprBoundaryFields.C + +EXE = $(FOAM_APPBIN)/setExprBoundaryFields diff --git a/applications/utilities/preProcessing/setExprBoundaryFields/Make/options b/applications/utilities/preProcessing/setExprBoundaryFields/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..969020c4afaf5d784299462b9e1af282040ba6b4 --- /dev/null +++ b/applications/utilities/preProcessing/setExprBoundaryFields/Make/options @@ -0,0 +1,8 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lmeshTools \ + -lgenericPatchFields diff --git a/applications/utilities/preProcessing/setExprBoundaryFields/setExprBoundaryFields.C b/applications/utilities/preProcessing/setExprBoundaryFields/setExprBoundaryFields.C new file mode 100644 index 0000000000000000000000000000000000000000..179361cdc36a2b2b726ac778778bc47011b34b6d --- /dev/null +++ b/applications/utilities/preProcessing/setExprBoundaryFields/setExprBoundaryFields.C @@ -0,0 +1,262 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Application + setExprFields + +Group + grpPreProcessingUtilities + +Description + Set boundary values using an expression + +Note + Based on funkySetBoundaryFields + Copyright 2006-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "fvMesh.H" +#include "pointMesh.H" +#include "volFields.H" +#include "surfaceFields.H" +#include "surfaceFields.H" +#include "pointFields.H" +#include "patchExprDriver.H" +#include "timeSelector.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noFunctionObjects(true); + + // No -constant, no special treatment for 0/ + timeSelector::addOptions(false); + + argList::addOption + ( + "dict", + "file", + "Alternative dictionary for setExprBoundaryFieldsDict" + ); + + argList::addBoolOption + ( + "cache-fields", + "Cache fields between calls", + true // Advanced + ); + argList::addBoolOption + ( + "backup", + "Preserve sub-entry as .backup", + true // Advanced + ); + + argList::addBoolOption + ( + "dry-run", + "Evaluate but do not write" + ); + + #include "addRegionOption.H" + #include "setRootCase.H" + + const bool dryrun = args.found("dry-run"); + const bool backup = args.found("backup"); + const bool cacheFields = args.found("cache-fields"); + + if (cacheFields) + { + Warning + << "The current cache-fields behaviour (caching disk reads) " + << "may lead to unexpected behaviour as previous modifications " + << "will not be visible." + << endl; + } + + const word dictName("setExprBoundaryFieldsDict"); + + #include "createTime.H" + + instantList times = timeSelector::select0(runTime, args); + + if (times.size() < 1) + { + FatalErrorInFunction + << "No times selected." << exit(FatalError); + } + + #include "createNamedMesh.H" + + #include "setSystemMeshDictionaryIO.H" + IOdictionary setExprDict(dictIO); + + forAll(times, timei) + { + runTime.setTime(times[timei], timei); + + Info<< "\nTime = " << runTime.timeName() << endl; + + mesh.readUpdate(); + + for (const entry& dEntry : setExprDict) + { + if (!dEntry.isDict()) + { + Info<< "Ignoring non-dictionary entry " + << dEntry.keyword() << nl; + continue; + } + + const dictionary& dict = dEntry.dict(); + + const word fieldName(dict.get<word>("field")); + + List<dictionary> exprDicts; + dict.readEntry("expressions", exprDicts); + + if (exprDicts.empty()) + { + Info<< "No expressions for " << fieldName << nl; + continue; + } + + + // Read dictionary + // Note: disable class type checking so we can load field + const word oldTypeName = IOdictionary::typeName; + const_cast<word&>(IOdictionary::typeName) = word::null; + + IOobject fieldHeader + ( + fieldName, + mesh.thisDb().time().timeName(), + mesh.thisDb(), + IOobject::MUST_READ_IF_MODIFIED, + IOobject::NO_WRITE, + false + ); + + const bool headOk = fieldHeader.typeHeaderOk<IOdictionary>(false); + + if (!headOk) + { + // Restore type + const_cast<word&>(IOdictionary::typeName) = oldTypeName; + + WarningInFunction + << "Requested field to change " << fieldName + << " does not exist in " << fieldHeader.path() << endl; + continue; + } + + IOdictionary fieldDict(fieldHeader); + + // Restore type + const_cast<word&>(IOdictionary::typeName) = oldTypeName; + + // Fake type back to what was in field + const_cast<word&>(fieldDict.type()) = fieldDict.headerClassName(); + + Info<< "Processing field " << fieldName << nl; + + dictionary& boundaryFieldDict = fieldDict.subDict("boundaryField"); + + for (const dictionary& currDict : exprDicts) + { + const word targetName = currDict.get<word>("target"); + const word patchName = currDict.get<word>("patch"); + + dictionary& patchDict = boundaryFieldDict.subDict(patchName); + + expressions::exprString expr + ( + currDict.get<string>("expression"), + currDict, + true // strip comments + ); + + Info<< "Set boundaryField/" << patchName << '/' + << targetName << nl + << "with expression" << nl + << "<<<<" << nl + << expr.c_str() << nl + << ">>>>" << nl; + + expressions::patchExprDriver driver(currDict, mesh); + + // Search on disc + driver.setSearchBehaviour(cacheFields, false, true); + + driver.clearVariables(); + driver.parse(expr); + + // Serializing via Field::writeEntry etc + OStringStream serialize; + driver.result().writeEntry("", serialize); + + if (backup && !dryrun) + { + patchDict.changeKeyword + ( + targetName, + word(targetName + ".backup"), + true // Overwrite + ); + } + + patchDict.set(targetName, serialize.str().c_str()); + + if (dryrun) + { + Info<< "Evaluated:" << nl + << "<<<<" << nl + << serialize.str().c_str() // (already includes nl) + << ">>>>" << nl; + } + } + + if (!dryrun) + { + Info<< "Write " << fieldDict.filePath() << nl; + fieldDict.regIOobject::write(); + } + } + } + + Info<< "\nEnd\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/setExprBoundaryFields/setExprBoundaryFieldsDict b/applications/utilities/preProcessing/setExprBoundaryFields/setExprBoundaryFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..53724eb90e7baf9a543693485b41561050986dd1 --- /dev/null +++ b/applications/utilities/preProcessing/setExprBoundaryFields/setExprBoundaryFieldsDict @@ -0,0 +1,34 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setExprBoundaryFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +pattern +{ + field T; + + expressions + ( + { + patch bottom; + target theta0; + expression #{ (pos().x() < 1e-4 ? 60 : 120) #}; + } + ); + + keepPatches true; +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/setExprFields/Make/files b/applications/utilities/preProcessing/setExprFields/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..3212112fdc50ac8119e431b38483d06a64182064 --- /dev/null +++ b/applications/utilities/preProcessing/setExprFields/Make/files @@ -0,0 +1,3 @@ +setExprFields.C + +EXE = $(FOAM_APPBIN)/setExprFields diff --git a/applications/utilities/preProcessing/setExprFields/Make/options b/applications/utilities/preProcessing/setExprFields/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..969020c4afaf5d784299462b9e1af282040ba6b4 --- /dev/null +++ b/applications/utilities/preProcessing/setExprFields/Make/options @@ -0,0 +1,8 @@ +EXE_INC = \ + -I$(LIB_SRC)/finiteVolume/lnInclude \ + -I$(LIB_SRC)/meshTools/lnInclude + +EXE_LIBS = \ + -lfiniteVolume \ + -lmeshTools \ + -lgenericPatchFields diff --git a/applications/utilities/preProcessing/setExprFields/setExprFields.C b/applications/utilities/preProcessing/setExprFields/setExprFields.C new file mode 100644 index 0000000000000000000000000000000000000000..21a609124c86503fcd00029462a02d1e27497e7e --- /dev/null +++ b/applications/utilities/preProcessing/setExprFields/setExprFields.C @@ -0,0 +1,915 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Application + setExprFields + +Group + grpPreProcessingUtilities + +Description + Set values on a selected set of cells/patch-faces via a dictionary. + +Note + Based on funkySetFields + Copyright 2006-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "fvMesh.H" +#include "pointMesh.H" +#include "volFields.H" +#include "surfaceFields.H" +#include "surfaceFields.H" +#include "pointFields.H" +#include "exprOps.H" +#include "volumeExprDriver.H" +#include "timeSelector.H" +#include "dlLibraryTable.H" + + +using namespace Foam; + +using FieldAssociation = expressions::volumeExpr::FieldAssociation; + +word fieldGeoType(const FieldAssociation geoType) +{ + switch (geoType) + { + case FieldAssociation::VOLUME_DATA : return "cells"; break; + case FieldAssociation::SURFACE_DATA : return "faces"; break; + case FieldAssociation::POINT_DATA : return "points"; break; + default: break; + } + + return "unknown"; +} + + +//- Simple control structure to with collected switches to simplify passing +struct setExprFieldsControl +{ + bool dryRun; + bool debugParsing; + bool cacheVariables; + bool useDimension; + bool createNew; + bool keepPatches; + bool correctPatches; + bool correctBCs; +}; + + +template<class Type> +void doCorrectBoundaryConditions +( + bool correctBCs, + GeometricField<Type, fvPatchField, volMesh>& field +) +{ + if (correctBCs) + { + Info<< "Correcting boundary conditions: " << field.name() << nl; + field.correctBoundaryConditions(); + } +} + + +template<class Type> +void doCorrectBoundaryConditions +( + bool correctBCs, + GeometricField<Type, pointPatchField, pointMesh>& field +) +{ + if (correctBCs) + { + Info<< "Correcting boundary conditions: " << field.name() << nl; + field.correctBoundaryConditions(); + } +} + + +template<class Type> +void doCorrectBoundaryConditions +( + bool correctBCs, + GeometricField<Type, fvsPatchField, surfaceMesh>& field +) +{} + + +template<class GeoField, class Mesh> +void setField +( + const word& fieldName, + const Mesh& mesh, + const GeoField& result, + const scalarField& cond, + const dimensionSet& dims, + const wordList& valuePatches, + + const setExprFieldsControl& ctrl +) +{ + Info<< "setField(" << fieldName << "): " + << pTraits<GeoField>::typeName << endl; + + tmp<GeoField> toutput; + + if (ctrl.createNew) + { + // Create with zero + toutput = GeoField::New + ( + fieldName, + mesh, + dimensioned<typename GeoField::value_type>(dims) + ); + } + else + { + // Read + toutput = tmp<GeoField>::New + ( + IOobject + ( + fieldName, + mesh.thisDb().time().timeName(), + mesh.thisDb(), + IOobject::MUST_READ, + IOobject::NO_WRITE, + false // No register + ), + mesh + ); + } + + auto& output = toutput.ref(); + + label setCells = 0; + + if (cond.empty()) + { + // No condition + output = result; + + setCells = output.size(); + } + else + { + forAll(output, celli) + { + if (expressions::boolOp<scalar>()(cond[celli])) + { + output[celli] = result[celli]; + ++setCells; + } + } + } + + const label totalCells = returnReduce(output.size(), plusOp<label>()); + reduce(setCells, plusOp<label>()); + + forAll(result.boundaryField(), patchi) + { + auto& pf = output.boundaryFieldRef()[patchi]; + + if (pf.patch().coupled()) + { + pf == result.boundaryField()[patchi]; + } + } + + + if (setCells == totalCells) + { + Info<< "Set all "; + } + else + { + Info<< "Set " << setCells << " of "; + } + Info<< totalCells << " cells" << endl; + + + doCorrectBoundaryConditions(ctrl.correctBCs, output); + + if (ctrl.useDimension) + { + Info<< "Setting dimension to " << dims << endl; + output.dimensions().reset(dims); + } + + if (ctrl.dryRun) + { + Info<< "(dry-run): Writing to " << output.name() << nl; + } + else + { + Info<< "Writing to " << output.name() << nl; + output.write(); + } +} + + +void evaluate +( + const fvMesh& mesh, + const word& fieldName, + const expressions::exprString& expression, + const expressions::exprString& condition, + const dictionary& dict, + const dimensionSet& dims, + const wordList& valuePatches, + + const setExprFieldsControl& ctrl +) +{ + word oldFieldType; + + if (ctrl.createNew) + { + Info<< "Set new field: " << fieldName; + } + else + { + IOobject io + ( + fieldName, + mesh.thisDb().time().timeName(), + mesh.thisDb(), + IOobject::MUST_READ, + IOobject::NO_WRITE + ); + io.typeHeaderOk<IOobject>(false); + + oldFieldType = io.headerClassName(); + + if (oldFieldType == IOobject::typeName) + { + FatalErrorInFunction + << "Field " << fieldName << " is " + << oldFieldType + << ". Seems that it does not exist. Use 'create'" + << nl + << exit(FatalError); + } + + Info<< "Modify field: " << fieldName + << " (type " << oldFieldType << ')'; + } + + Info<< " time=" << mesh.thisDb().time().timeName() << nl + << "Expression:" << nl + << ">>>>" << nl + << expression.c_str() << nl + << "<<<<" << nl + << "Condition:" << nl + << ">>>>" << nl + << condition.c_str() << nl + << "<<<<" << nl; + + if (ctrl.keepPatches) + { + Info<< "Keeping patches unaltered" << endl; + } + else if (!valuePatches.empty()) + { + Info<< "Setting patches " << flatOutput(valuePatches) + << " to fixed value" << endl; + } + + Info<< endl; + + expressions::volumeExprDriver driver + ( + mesh, + ctrl.cacheVariables + ); + + driver.readDict(dict); + + if (ctrl.debugParsing) + { + Info<< "Parsing expression: " << expression << "\nand condition " + << condition << nl << endl; + driver.setDebugging(true, true); + } + + + driver.clearVariables(); + + scalarField conditionField; + + bool evaluatedCondition = false; + + FieldAssociation conditionDataType(FieldAssociation::VOLUME_DATA); + + if (condition.size() && condition != "true") + { + if (ctrl.debugParsing) + { + Info<< "Parsing condition:" << condition << endl; + } + + driver.parse(condition); + if (ctrl.debugParsing) + { + Info<< "Parsed condition" << endl; + } + + // Process any/all scalar fields. May help with diagnosis + + bool goodCond = true; + while (goodCond) + { + // volScalarField + { + const auto* ptr = driver.isResultType<volScalarField>(); + if (ptr) + { + conditionField = ptr->internalField(); + break; + } + } + + // surfaceScalarField + { + const auto* ptr = driver.isResultType<surfaceScalarField>(); + if (ptr) + { + conditionField = ptr->internalField(); + conditionDataType = FieldAssociation::SURFACE_DATA; + break; + } + } + + // pointScalarField + { + const auto* ptr = driver.isResultType<pointScalarField>(); + if (ptr) + { + conditionField = ptr->internalField(); + conditionDataType = FieldAssociation::POINT_DATA; + break; + } + } + + // No matching field types + goodCond = false; + } + + // Verify that it also logical + goodCond = goodCond && driver.isLogical(); + + if (!goodCond) + { + FatalErrorInFunction + << " condition: " << condition + << " does not evaluate to a logical expression: " + << driver.resultType() << nl + #ifdef FULLDEBUG + << "contents: " << conditionField + #endif + << exit(FatalError); + } + + if (ctrl.debugParsing) + { + Info<< "Condition evaluates to " + << conditionField << nl; + } + + evaluatedCondition = true; + } + + if (ctrl.debugParsing) + { + Info<< "Parsing expression:" << expression << endl; + } + + driver.parse(expression); + + if (ctrl.debugParsing) + { + Info<< "Parsed expression" << endl; + } + + if (evaluatedCondition) + { + if (conditionDataType != driver.fieldAssociation()) + { + FatalErrorInFunction + << "Mismatch between condition geometric type (" + << fieldGeoType(conditionDataType) << ") and" << nl + << "expression geometric type (" + << fieldGeoType(driver.fieldAssociation()) << ')' << nl + << nl + << "Expression: " << expression << nl + << "Condition: " << condition << nl + << nl + << exit(FatalError); + } + } + + if (!ctrl.createNew && driver.resultType() != oldFieldType) + { + FatalErrorInFunction + << "Inconsistent types: " << fieldName << " is " + << oldFieldType + << " but the expression evaluates to " + << driver.resultType() + << exit(FatalError); + } + + Info<< "Dispatch ... " << driver.resultType() << nl; + + #undef setFieldDispatch + #define setFieldDispatch(FieldType) \ + { \ + /* FieldType */ \ + const auto* ptr = driver.isResultType<FieldType>(); \ + if (ptr) \ + { \ + /* driver.getResult<FieldType>(correctPatches), */ \ + \ + setField \ + ( \ + fieldName, \ + mesh, \ + *ptr, \ + conditionField, \ + dims, \ + valuePatches, \ + ctrl \ + ); \ + return; \ + } \ + } \ + + + setFieldDispatch(volScalarField); + setFieldDispatch(volVectorField); + setFieldDispatch(volTensorField); + setFieldDispatch(volSymmTensorField); + setFieldDispatch(volSphericalTensorField); + + setFieldDispatch(surfaceScalarField); + setFieldDispatch(surfaceVectorField); + setFieldDispatch(surfaceTensorField); + setFieldDispatch(surfaceSymmTensorField); + setFieldDispatch(surfaceSphericalTensorField); + + #undef setFieldDispatch + #define setFieldDispatch(FieldType) \ + { \ + /* FieldType */ \ + const auto* ptr = driver.isResultType<FieldType>(); \ + \ + if (ptr) \ + { \ + /* driver.getResult<FieldType>(correctPatches), */ \ + \ + setField \ + ( \ + fieldName, \ + pointMesh::New(mesh), \ + *ptr, \ + conditionField, \ + dims, \ + valuePatches, \ + ctrl \ + ); \ + return; \ + } \ + } \ + + setFieldDispatch(pointScalarField); + setFieldDispatch(pointVectorField); + setFieldDispatch(pointTensorField); + setFieldDispatch(pointSymmTensorField); + setFieldDispatch(pointSphericalTensorField); + + #undef setFieldDispatch + + // Nothing dispatched? + + FatalErrorInFunction + << "Expression evaluates to an unsupported type: " + << driver.resultType() << nl << nl + << "Expression " << expression << nl << endl + << exit(FatalError); +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +int main(int argc, char *argv[]) +{ + argList::noFunctionObjects(true); + + // No -constant, no special treatment for 0/ + timeSelector::addOptions(false); + + argList::addOption + ( + "dict", + "file", + "Alternative dictionary for setExprFieldsDict" + ); + + argList::addBoolOption + ( + "dry-run", + "Evaluate but do not write" + ); + + argList::addBoolOption + ( + "verbose", + "Additional verbosity", + true // Advanced option + ); + + argList::addOption + ( + "field", + "name", + "The field to overwrite command-line operation)", + true // Advanced option + ); + argList::addOption + ( + "expression", + "expr", + "The expression to evaluate (command-line operation)", + true // Advanced option + ); + argList::addOption + ( + "condition", + "logic", + "The logical condition when to apply the expression" + " (command-line operation)", + true // Advanced option + ); + argList::addOption + ( + "dimension", + "dims", + "The dimensions to apply for created fields" + " (command-line operation)", + true // Advanced option + ); + argList::addBoolOption + ( + "debug-parser", + "Additional debugging information", + true // Advanced option + ); + argList::addBoolOption + ( + "no-variable-cache", + "Disable caching of expression variables", + true // Advanced option + ); + argList::addBoolOption + ( + "create", + "Create a new field (command-line operation)", + true // Advanced option + ); + argList::addBoolOption + ( + "keepPatches", + "Leave patches unaltered" + " (command-line operation)", + true // Advanced option + ); + argList::addOption + ( + "value-patches", + "(patches)", + "A list of patches that receive a fixed value" + " (command-line operation)", + true // Advanced option + ); + argList::addBoolOption + ( + "dummy-phi", + "(command-line operation)", + true // Advanced option + ); + + // Future? + #if 0 + argList::addBoolOption + ( + "noCorrectPatches", + "" + ); + argList::addBoolOption + ( + "correctResultBoundaryFields", + "", + true + ); + #endif + + #include "addRegionOption.H" + #include "setRootCase.H" + + #include "createTime.H" + + const bool dryrun = args.found("dry-run"); + const bool verbose = args.found("verbose"); + + const word dictName("setExprFieldsDict"); + + instantList times = timeSelector::select0(runTime, args); + + if (times.size() < 1) + { + FatalErrorInFunction + << "No times selected." << exit(FatalError); + } + + // Disable dimension checking during operation + dimensionSet::debug = false; + + #include "createNamedMesh.H" + + autoPtr<surfaceScalarField> dummyPhi; + + autoPtr<IOdictionary> exprDictPtr; + + // Sort out conflicts + + const bool useCommandArgs = args.found("field"); + + if (useCommandArgs) + { + if (args.found("dict")) + { + FatalErrorInFunction + << "Cannot specify both dictionary and command-line arguments" + << nl + << endl; + } + + if (args.found("create") && args.found("keepPatches")) + { + FatalErrorInFunction + << "Cannot specify both 'create' and 'keepPatches'" << nl + << endl; + } + } + else + { + // Carp about inapplicable options + + wordHashSet badOptions + ({ + "create", "keepPatches", "valuePatches", + "dimension", "condition", "expression" + }); + + badOptions.retain(args.options()); + + if (!badOptions.empty()) + { + FatalErrorInFunction + << "Using a dictionary. Cannot specify command options:" << nl + << nl + << flatOutput(badOptions.sortedToc()) << nl + << endl; + } + + #include "setSystemMeshDictionaryIO.H" + exprDictPtr.reset(new IOdictionary(dictIO)); + } + + + forAll(times, timei) + { + runTime.setTime(times[timei], timei); + + Info<< "\nTime = " << runTime.timeName() << endl; + + mesh.readUpdate(); + + if (args.found("dummy-phi") && !dummyPhi.valid()) + { + Info<< "Adding a dummy phi" << endl; + dummyPhi.reset + ( + new surfaceScalarField + ( + IOobject + ( + "phi", + mesh.thisDb().time().constant(), + mesh.thisDb(), + IOobject::NO_READ, + IOobject::NO_WRITE + ), + mesh, + dimensionedScalar(Zero) + ) + ); + } + + if (args.found("withFunctionObjects")) + { + runTime.functionObjects().start(); + } + + if (args.found("field")) + { + const word fieldName(args.get<word>("field")); + + Info<< "Using command-line options for " + << fieldName << nl << endl; + + setExprFieldsControl ctrl; + + ctrl.dryRun = dryrun; + ctrl.debugParsing = args.found("debug-parser"); + ctrl.cacheVariables = !args.found("no-variable-caching"); + + ctrl.createNew = args.found("create"); + ctrl.keepPatches = args.found("keepPatches"); + ctrl.correctPatches = !args.found("noCorrectPatches"); + ctrl.correctBCs = args.found("correctResultBoundaryFields"); + ctrl.useDimension = args.found("dimension"); + + expressions::exprString + expression + ( + args.opt("expression"), + dictionary::null + ); + + expressions::exprString condition; + if (args.found("condition")) + { + args.readIfPresent("condition", condition); + } + + dimensionSet dims; + + if (ctrl.useDimension) + { + ITstream is(args.lookup("dimension")); + is >> dims; + } + + evaluate + ( + mesh, + fieldName, + expression, + condition, + dictionary::null, + dims, + args.getList<word>("valuePatches", false), + + ctrl + ); + } + else if (exprDictPtr.valid()) + { + const dictionary& exprDict = exprDictPtr(); + + // Read set construct info from dictionary + PtrList<entry> actions(exprDict.lookup("expressions")); + + for (const entry& dEntry : actions) + { + if (!dEntry.isDict()) + { + Info<< "Ignore non-dictionary entry: " + << dEntry.keyword() << nl; + continue; + } + + const dictionary& dict = dEntry.dict(); + + setExprFieldsControl ctrl; + + ctrl.dryRun = dryrun; + ctrl.debugParsing = args.found("debug-parser"); + ctrl.cacheVariables = !args.found("no-variable-caching"); + + ctrl.createNew = dict.getOrDefault("create", false); + ctrl.keepPatches = dict.getOrDefault("keepPatches", false); + ctrl.correctPatches = !args.found("noCorrectPatches"); + ctrl.correctBCs = args.found("correctResultBoundaryFields"); + + if (ctrl.createNew && ctrl.keepPatches) + { + FatalIOErrorInFunction(dict) + << "Cannot specify both 'create' and 'keepPatches'" + << nl << endl + << exit(FatalIOError); + } + + // Local override + dict.readIfPresent + ( + "correctResultBoundaryFields", + ctrl.correctBCs + ); + + + const word fieldName(dict.get<word>("field")); + + expressions::exprString expression + ( + dict.get<string>("expression"), + dict + ); + + expressions::exprString condition; + + if (dict.found("condition")) + { + condition = + expressions::exprString + ( + dict.get<string>("condition"), + dict + ); + } + + ctrl.useDimension = dict.found("dimension"); + + dimensionSet dims; + if (ctrl.useDimension) + { + dict.lookup("dimension") >> dims; + } + + wordList valuePatches; + dict.readIfPresent("valuePatches", valuePatches); + + if (verbose && !timei) + { + // Report once + Info<< "Processing" << dict << nl; + } + + evaluate + ( + mesh, + fieldName, + expression, + condition, + dict, + dims, + valuePatches, + + ctrl + ); + } + } + else if (exprDictPtr.valid()) + { + FatalErrorInFunction + << "No command-line or dictionary??" << nl << endl + << exit(FatalError); + } + } + + Info<< "\nEnd\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/applications/utilities/preProcessing/setExprFields/setExprFieldsDict b/applications/utilities/preProcessing/setExprFields/setExprFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..2e06d9a26e68afb3aa9611eb1ae267a712b10dd1 --- /dev/null +++ b/applications/utilities/preProcessing/setExprFields/setExprFieldsDict @@ -0,0 +1,52 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setExprFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +expressions +( + T + { + field T; + dimensions [0 0 0 1 0 0 0]; + + constants + { + centre (0.21 0 0.01); + } + + variables + ( + "radius = 0.1" + ); + + condition + #{ + // Within the radius + (mag(pos() - $[(vector)constants.centre]) < radius) + + // but only +ve y! + && pos((pos() - $[(vector)constants.centre]).y()) > 0 + #}; + + expression + #{ + 300 + + 200 * (1 - mag(pos() - $[(vector)constants.centre]) / radius) + #}; + } +); + + +// ************************************************************************* // diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index 18d5b7c57beebdd0c2c9f9706fcef392d6faacf1..8ad81a5a0435b4e9be0c99baf4dd1080d411cfe8 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -250,6 +250,35 @@ $(constraintFvsPatchFields)/wedge/wedgeFvsPatchFields.C fields/volFields/volFields.C fields/surfaceFields/surfaceFields.C +expr = expressions +$(expr)/base/exprDriverWriter.C + +$(expr)/base/fvExprDriver.C +$(expr)/base/fvExprDriverFields.C +$(expr)/base/fvExprDriverIO.C +$(expr)/base/fvExprDriverNew.C + +patchExpr = $(expr)/patch +$(patchExpr)/patchExpr.C +$(patchExpr)/patchExprDriver.C +$(patchExpr)/patchExprDriverFields.C +$(patchExpr)/patchExprLemonParser.lyy-m4 +$(patchExpr)/patchExprScanner.cc + +volumeExpr = $(expr)/volume +$(volumeExpr)/volumeExpr.C +$(volumeExpr)/volumeExprDriver.C +$(volumeExpr)/volumeExprDriverFields.C +$(volumeExpr)/volumeExprLemonParser.lyy-m4 +$(volumeExpr)/volumeExprScanner.cc + +fieldExpr = $(expr)/fields +$(fieldExpr)/base/patchExprFieldBase.C +$(fieldExpr)/fvPatchFields/exprFixedValueFvPatchFields.C +$(fieldExpr)/fvPatchFields/exprMixedFvPatchFields.C +$(fieldExpr)/pointPatchFields/exprValuePointPatchFields.C + + fvMatrices/fvMatrices.C fvMatrices/fvScalarMatrix/fvScalarMatrix.C fvMatrices/solvers/MULES/MULES.C diff --git a/src/finiteVolume/expressions/base/exprDriverWriter.C b/src/finiteVolume/expressions/base/exprDriverWriter.C new file mode 100644 index 0000000000000000000000000000000000000000..eb2aa82b82bd59d57626a17e2593dc2bee11341a --- /dev/null +++ b/src/finiteVolume/expressions/base/exprDriverWriter.C @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprDriverWriter.H" +#include "fvExprDriver.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + + defineTypeName(exprDriverWriter); + +} // namespace expressions +} // namespace Foam + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::exprDriverWriter::exprDriverWriter +( + const word& name, + fvExprDriver& driver +) +: + regIOobject + ( + IOobject + ( + name, + driver.mesh().time().timeName(), + "expressions", + driver.mesh().time(), + IOobject::READ_IF_PRESENT, + IOobject::AUTO_WRITE + ) + ), + driver_(driver) +{ + if (headerOk()) + { + readData(readStream("exprDriverWriter", true)); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::expressions::exprDriverWriter::readData(Istream& is) +{ + dictionary dict(is); + + // driver_.readDict(is); + + driver_.getData(dict); + + return !is.bad(); +} + + +bool Foam::expressions::exprDriverWriter::writeData(Ostream& os) const +{ + // driver_.writeDict(os); + + dictionary dict; + driver_.prepareData(dict); + dict.write(os, false); + + return os.good(); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/exprDriverWriter.H b/src/finiteVolume/expressions/base/exprDriverWriter.H new file mode 100644 index 0000000000000000000000000000000000000000..10fe296e1f3959d9ac50e9738b8f66ddf966916a --- /dev/null +++ b/src/finiteVolume/expressions/base/exprDriverWriter.H @@ -0,0 +1,109 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2011-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::exprDriverWriter + +Description + Registered input/output for an expressions::fvExprDriver + +SourceFiles + exprDriverWriter.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_exprDriverWriter_H +#define expressions_exprDriverWriter_H + +#include "fvExprDriver.H" +#include "regIOobject.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +/*---------------------------------------------------------------------------*\ + Class exprDriverWriter Declaration +\*---------------------------------------------------------------------------*/ + +class exprDriverWriter +: + public regIOobject +{ + // Private Data + + //- The driver to read/write + fvExprDriver& driver_; + + + // Private Member Functions + + //- No null constructor + exprDriverWriter() = delete; + + //- No copy construct + exprDriverWriter(const exprDriverWriter&) = delete; + + //- No copy assignment + void operator=(const exprDriverWriter&) = delete; + + +public: + + //- Runtime type information + TypeNameNoDebug("exprDriverWriter"); + + + // Constructors + + //- Construct for named driver + exprDriverWriter(const word& name, fvExprDriver& driver); + + + //- Destructor + virtual ~exprDriverWriter() = default; + + + // Member Functions + + virtual bool readData(Istream& is); + virtual bool writeData(Ostream& os) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriver.C b/src/finiteVolume/expressions/base/fvExprDriver.C new file mode 100644 index 0000000000000000000000000000000000000000..1e6055daddfb71ce7687f48ade8172821885bb16 --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriver.C @@ -0,0 +1,765 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "fvExprDriver.H" +#include "exprDriverWriter.H" +#include "expressionEntry.H" +#include "exprResultGlobals.H" + +#include "cellSet.H" +#include "faceSet.H" +#include "pointSet.H" +#include "stringOps.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + + defineTypeNameAndDebug(fvExprDriver, 0); + defineRunTimeSelectionTable(fvExprDriver, dictionary); + defineRunTimeSelectionTable(fvExprDriver, idName); + +} // End namespace expressions +} // End namespace Foam + +// Currently not working? +bool Foam::expressions::fvExprDriver::cacheSets_ = true; + +const Foam::fvMesh* Foam::expressions::fvExprDriver::defaultMeshPtr_ = nullptr; + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +const Foam::fvMesh& Foam::expressions::fvExprDriver::defaultMesh() +{ + if (!defaultMeshPtr_) + { + FatalErrorInFunction + << "No default mesh set" << nl + << "Try the 'fvExprDriverFunctionObject' as a workaround" + << endl + << abort(FatalError); + } + + return *defaultMeshPtr_; +} + + +const Foam::fvMesh* Foam::expressions::fvExprDriver::resetDefaultMesh +( + const fvMesh& mesh, + const bool force +) +{ + const fvMesh* ptr = defaultMeshPtr_; + + if (force || (ptr != nullptr)) + { + defaultMeshPtr_ = &mesh; + } + + return ptr; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::fvExprDriver::fvExprDriver +( + bool cacheReadFields, + bool searchInMemory, + bool searchFiles, + const dictionary& dict +) +: + expressions::exprDriver + ( + cacheReadFields, + searchInMemory, + searchFiles, + dict + ), + globalScopes_(), + delayedVariables_(), + storedVariables_(), + specialVariablesIndex_(-1), + otherMeshName_(), + libs_(), + writer_(nullptr) +{} + + +Foam::expressions::fvExprDriver::fvExprDriver +( + const fvExprDriver& rhs +) +: + expressions::exprDriver(rhs), + globalScopes_(rhs.globalScopes_), + delayedVariables_(rhs.delayedVariables_), + storedVariables_(rhs.storedVariables_), + specialVariablesIndex_(rhs.specialVariablesIndex_), + otherMeshName_(), + libs_(), + writer_(nullptr) +{} + + +Foam::expressions::fvExprDriver::fvExprDriver +( + const dictionary& dict +) +: + fvExprDriver + ( + dict.lookupOrDefault("cacheReadFields", false), + dict.lookupOrDefault("searchInMemory", true), + dict.lookupOrDefault("searchFiles", false), + dict + ) +{ + readDict(dict); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::expressions::fvExprDriver::~fvExprDriver() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::expressions::fvExprDriver::readDict +( + const dictionary& dict +) +{ + expressions::exprDriver::readDict(dict); + + // wordList plugins; + // if (dict.readIfPresent("functionPlugins", plugins)) + // { + // for (const word& plugin : plugins) + // { + // libs_.open("libswak" + plugin + "FunctionPlugin.so"); + // } + // } + + dict.readIfPresent("globalScopes", globalScopes_); + + const entry* eptr = nullptr; + + // Special variables + + if + ( + // storedVariables + (eptr = dict.findEntry("storedVariables", keyType::LITERAL)) + != nullptr + ) + { + ITstream& is = eptr->stream(); + + if (writer_.valid() && storedVariables_.size()) + { + WarningInFunction + // << "Context: " << driverContext_ << nl + << "The 'storedVariables' was already read." + << " No update from " << is + << endl; + } + else + { + storedVariables_ = List<exprResultStored>(is); + + // Check for excess tokens + dict.checkITstream(is, "storedVariables"); + } + } + + if + ( + // delayedVariables + (eptr = dict.findEntry("delayedVariables", keyType::LITERAL)) + != nullptr + ) + { + ITstream& is = eptr->stream(); + + if (writer_.valid() && delayedVariables_.size()) + { + WarningInFunction + // << "Context: " << driverContext_ << nl + << "Seems like 'delayedVariables' was already read." + << " No update from " << is + << endl; + } + else + { + List<exprResultDelayed> inputs(is); + + // Check for excess tokens + dict.checkITstream(is, "delayedVariables"); + + for (auto& var : inputs) + { + delayedVariables_.insert(var.name(), var); + } + } + } + + return true; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +const Foam::Time& Foam::expressions::fvExprDriver::runTime() const +{ + return this->mesh().time(); +} + + +Foam::word Foam::expressions::fvExprDriver::timeName() const +{ + return runTime().timeName(); +} + + +Foam::scalar Foam::expressions::fvExprDriver::timeValue() const +{ + return runTime().value(); +} + + +void Foam::expressions::fvExprDriver::updateSpecialVariables(bool force) +{ + const bool updated = this->update(); + + const label eventIndex = mesh().time().timeIndex(); + const scalar eventTime = mesh().time().value(); + + DebugInfo + << "fvExprDriver::updateSpecialVariables(force=" + << force << ") Updated: " << updated << endl; + + if (specialVariablesIndex_ < 0) + { + DebugInfo + << "First update: " << eventIndex << endl; + + specialVariablesIndex_ = eventIndex; + + for (exprResultStored& v : storedVariables_) + { + DebugInfo + << v.name() << " = " << v.initialValueExpression() + << " (has value " + << v.hasValue() << ")" << endl; + + if (!v.hasValue()) + { + DebugInfo + << "First value: " << v.initialValueExpression() + << " -> " << v.name() << endl; + + parse(v.initialValueExpression()); + v = result_; + DebugInfo + << "Parser size: " << this->size() << nl + << "Calculated: " << result_ << nl + << "Stored: " << v << nl; + } + } + } + + if (force || specialVariablesIndex_ != eventIndex) + { + DebugInfo + << "Store variables: " << force << ' ' + << specialVariablesIndex_ << ' ' + << eventIndex << endl; + + for (exprResultStored& v : storedVariables_) + { + if (variables_.found(v.name())) + { + DebugInfo + << "Storing variable: " << v.name() << " " + << variables_[v.name()] << endl; + + v = variables_[v.name()]; + } + } + specialVariablesIndex_ = eventIndex; + } + + forAllIters(delayedVariables_, iter) + { + DebugInfo + << "Updating delayed variable " << iter().name() << endl; + + if (!iter().updateReadValue(eventTime)) + { + const exprString& expr = iter().startupValueExpression(); + + DebugInfo + << "Evaluate: " << expr << endl; + + parse(expr); + iter().setReadValue(result_); + + DebugInfo + << "Value " << iter() << nl + << "Type " << iter().valueType() << "(" + << result_.valueType() << ")" << endl; + } + else + { + DebugInfo + << iter().name() << " updated without problem" << endl; + } + } +} + + +void Foam::expressions::fvExprDriver::clearVariables() +{ + DebugInfo + << "Clearing variables" << endl; + + const scalar eventTime = mesh().time().value(); + + (void)this->update(); + + updateSpecialVariables(); + variables_.clear(); + for (exprResultStored& v : storedVariables_) + { + variables_.insert(v.name(), v); + } + + addVariables(variableStrings_, false); + + forAllIters(delayedVariables_, iter) + { + iter().storeValue(eventTime); + } +} + + +void Foam::expressions::fvExprDriver::evaluateVariable +( + const word& varName, + const expressions::exprString& expr +) +{ + const regIOobject* objPtr = mesh().findObject<regIOobject>(varName); + + if (!allowShadowing_ && objPtr) + { + WarningInFunction + // << "Context: " << driverContext_ << nl + << "Field '" << varName << "' (type " << objPtr->headerClassName() + << ") is shadowed by a variable of the same name." << nl + << "This may lead to trouble" << nl + << "If this is OK set 'allowShadowing'" + << " in the relevant parser" << nl + << endl; + } + + parse(expr); + result_.testIfSingleValue(); + + DebugInfo + << "Evaluating: " << expr << " -> " << varName << endl + << result_; + + + // Assign + if (delayedVariables_.found(varName)) + { + // Avoid potential conflicts? + variables_.erase(varName); + + DebugInfo + << varName << " is delayed" << endl; + + // Copy assignment + delayedVariables_[varName] = result_; + } + else + { + // Overwrite with a copy + variables_.set(varName, exprResult(result_)); + } +} + + +void Foam::expressions::fvExprDriver::evaluateVariableRemote +( + string remote, + const word& varName, + const expressions::exprString& expr +) +{ + DebugInfo + << "Evaluating remote " << remote.c_str() + << " : " << expr << " -> " << varName << endl; + + word driverType("patch"); // default is patch + word identName, regionName; + + const auto slashPos = remote.find('/'); + if (slashPos != std::string::npos) + { + regionName = word::validate(remote.substr(slashPos+1)); + remote.resize(slashPos); + } + + const auto quotePos = remote.find('\''); + if (quotePos != std::string::npos) + { + driverType = word::validate(remote.substr(0, quotePos)); + identName = word::validate(remote.substr(quotePos+1)); + } + else + { + identName = word::validate(remote); + } + + if + ( + driverType == "patch" + && + ( + identName.empty() + || identName == "volume" + || identName == "internalField" + ) + ) + { + driverType = "internalField"; + } + + const fvMesh* pRegion = &(this->mesh()); + + if (!regionName.empty()) + { + pRegion = pRegion->time().cfindObject<fvMesh>(regionName); + + if (!pRegion) + { + FatalErrorInFunction + << "Cannot resolve mesh region: " << regionName << nl + << exit(FatalError); + } + } + + DebugInfo + << "Call other with (" + << driverType << ", " << identName << ", " << regionName << ")\n"; + + autoPtr<fvExprDriver> otherDriver = + fvExprDriver::New(driverType, identName, *pRegion); + + otherDriver->setSearchBehaviour(*this); + otherDriver->setGlobalScopes(this->globalScopes_); + + otherDriver->parse(expr); + + exprResult otherResult(this->getRemoteResult(*otherDriver)); + + // Check / re-check for uniform. Not normally needed + if (!otherResult.isUniform()) + { + otherResult.testIfSingleValue(); + } + + DebugInfo + << "Remote result: " << otherResult << nl; + + // Assign + if (delayedVariables_.found(varName)) + { + // Avoid potential conflicts? + variables_.erase(varName); + + DebugInfo + << varName << " is delayed - setting" << nl; + + // Move assignment + delayedVariables_[varName] = std::move(otherResult); + } + else + { + // Overwrite with a copy + variables_.set(varName, std::move(otherResult)); + } +} + + +const Foam::fvMesh& +Foam::expressions::fvExprDriver::regionMesh +( + const dictionary& dict, + const fvMesh& mesh, + bool readIfNecessary +) +{ + word regionName; + + if (!dict.readIfPresent("region", regionName)) + { + DebugInFunction << "Using original mesh " << nl; + return mesh; + } + + DebugInFunction << "Using mesh " << regionName << endl; + + fvMesh* meshPtr = mesh.time().getObjectPtr<fvMesh>(regionName); + + if (!meshPtr && readIfNecessary) + { + WarningInFunction + << "Region " << regionName + << " not in memory. Loading it" << endl; + + meshPtr = new fvMesh + ( + IOobject + ( + regionName, + mesh.time().constant(), + mesh.time(), + IOobject::MUST_READ + ) + ); + + meshPtr->polyMesh::store(); + } + + if (!meshPtr) + { + FatalErrorInFunction + << "No mesh region loaded: " << regionName + << endl; + } + + return *meshPtr; +} + + +Foam::word Foam::expressions::fvExprDriver::getTypeOfField +( + const word& fieldName +) const +{ + return getHeaderClassName(this->mesh(), fieldName); +} + + +Foam::word Foam::expressions::fvExprDriver::getFieldClassName +( + const word& name +) const +{ + if (searchInMemory()) + { + const regIOobject* ioptr = this->mesh().findObject<regIOobject>(name); + + if (ioptr) + { + return ioptr->type(); + } + } + + if (searchFiles()) + { + return getHeaderClassName(this->mesh(), name); + } + + return word::null; +} + + +Foam::topoSetSource::sourceType +Foam::expressions::fvExprDriver::topoSetType(const word& setName) const +{ + IOobject io(topoSet::findIOobject(mesh(), setName)); + + if (cellSet::typeName == io.headerClassName()) + { + return topoSetSource::sourceType::CELLSET_SOURCE; + } + if (faceSet::typeName == io.headerClassName()) + { + return topoSetSource::sourceType::FACESET_SOURCE; + } + if (pointSet::typeName == io.headerClassName()) + { + return topoSetSource::sourceType::POINTSET_SOURCE; + } + + return topoSetSource::sourceType::UNKNOWN_SOURCE; +} + + +Foam::topoSetSource::sourceType +Foam::expressions::fvExprDriver::topoZoneType(const word& setName) const +{ + if (mesh().cellZones().findZoneID(setName) >= 0) + { + return topoSetSource::sourceType::CELLZONE_SOURCE; + } + + if (mesh().faceZones().findZoneID(setName) >= 0) + { + return topoSetSource::sourceType::FACEZONE_SOURCE; + } + + if (mesh().pointZones().findZoneID(setName) >= 0) + { + return topoSetSource::sourceType::POINTZONE_SOURCE; + } + + return topoSetSource::sourceType::UNKNOWN_SOURCE; +} + + +Foam::topoSetSource::sourceType +Foam::expressions::fvExprDriver::topoSourceType(const word& setName) const +{ + auto setType = topoZoneType(setName); + + if (topoSetSource::sourceType::UNKNOWN_SOURCE == setType) + { + setType = topoSetType(setName); + } + + return setType; +} + + + +bool Foam::expressions::fvExprDriver::isCellSet(const word& setName) const +{ + return + ( + topoSetSource::sourceType::CELLSET_SOURCE + == topoSetType(setName) + ); +} + + +bool Foam::expressions::fvExprDriver::isFaceSet(const word& setName) const +{ + return + ( + topoSetSource::sourceType::FACESET_SOURCE + == topoSetType(setName) + ); +} + + +bool Foam::expressions::fvExprDriver::isPointSet(const word& setName) const +{ + return + ( + topoSetSource::sourceType::POINTSET_SOURCE + == topoSetType(setName) + ); +} + + +bool Foam::expressions::fvExprDriver::isCellZone(const word& name) const +{ + return (mesh().cellZones().findZoneID(name) >= 0); +} + + +bool Foam::expressions::fvExprDriver::isFaceZone(const word& name) const +{ + return (mesh().faceZones().findZoneID(name) >= 0); +} + + +bool Foam::expressions::fvExprDriver::isPointZone(const word& name) const +{ + return (mesh().pointZones().findZoneID(name) >= 0); +} + + +const Foam::expressions::exprResult& +Foam::expressions::fvExprDriver::lookupGlobal +( + const word& name +) const +{ + return exprResultGlobals::New(this->mesh()).get(name, globalScopes_); +} + + +bool Foam::expressions::fvExprDriver::hasDataToWrite() const +{ + return (!storedVariables_.empty() || !delayedVariables_.empty()); +} + + +void Foam::expressions::fvExprDriver::getData +( + const dictionary& dict +) +{ + dict.readIfPresent("storedVariables", storedVariables_); +} + + +void Foam::expressions::fvExprDriver::prepareData +( + dictionary& dict +) const +{ + auto& driver = const_cast<fvExprDriver&>(*this); + + (void)driver.update(); + + if (storedVariables_.size()) + { + driver.updateSpecialVariables(true); + + dict.add("storedVariables", storedVariables_); + } +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriver.H b/src/finiteVolume/expressions/base/fvExprDriver.H new file mode 100644 index 0000000000000000000000000000000000000000..4104d079640eb93b5264bb4f221a4e565c71cdb4 --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriver.H @@ -0,0 +1,646 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2010-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::fvExprDriver + +Description + Base driver for parsing value expressions associated with an fvMesh. + + Largely based on code and ideas from swak4foam + + Properties + \table + Property | Description | Required | Default + variables | List of variables for expressions | no | () + delayedVariables | List of delayed variables | no | () + storedVariables | List of stored variables | no | () + globalScopes | Scopes for global variables | no | () + allowShadowing | Allow variables to shadow field names | no | false + \endtable + + Debug Properties + \table + Property | Description | Required | Default + debugBaseDriver | Debug level (int) for base driver | no | + debugScanner | Add debug for scanner | no | false + debugParser | Add debug for parser | no | false + \endtable + +SourceFiles + fvExprDriverI.H + fvExprDriver.C + fvExprDriverFields.C + fvExprDriverIO.C + fvExprDriverNew.C + fvExprDriverTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_fvExprDriver_H +#define expressions_fvExprDriver_H + +#include "exprDriver.H" +#include "exprResultDelayed.H" +#include "exprResultStored.H" +#include "pointMesh.H" +#include "volFields.H" +#include "topoSetSource.H" +#include "dlLibraryTable.H" +#include "runTimeSelectionTables.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +// Forward Declarations +class exprDriverWriter; + +/*---------------------------------------------------------------------------*\ + Class fvExprDriver Declaration +\*---------------------------------------------------------------------------*/ + +class fvExprDriver +: + public expressions::exprDriver +{ + // Static Data + + //- Pointer to the "default" mesh + static const fvMesh *defaultMeshPtr_; + + //- Cache cellSets, faceSets insted of reading from disc each time + static bool cacheSets_; + + + // Protected Data + + // Stored Data + + //- The scopes for global variables + List<word> globalScopes_; + + //- The (delayed) variables table + HashTable<exprResultDelayed> delayedVariables_; + + //- Stored expressions. Read from dictionary and updated as required + List<exprResultStored> storedVariables_; + + //- Time index when handling special variables + label specialVariablesIndex_; + + //- The name of the other mesh (if it is to be required) + word otherMeshName_; + + //- Additional libraries + dlLibraryTable libs_; + + //- Writing and restoring + autoPtr<exprDriverWriter> writer_; + + + // Private Member Functions + + //- Read the IOobject and return the headerClassName + static word getHeaderClassName + ( + const polyMesh& mesh, + const word& name + ); + + //- Read the set IOobject and return its headerClassName + static word getSetClassName + ( + const polyMesh& mesh, + const word& name + ); + + + //- No copy assignment + void operator=(const fvExprDriver&) = delete; + + +protected: + + // Static Member Functions + + //- Determine mesh or region mesh as specified in the dictionary + //- with the keyword "region" + static const fvMesh& regionMesh + ( + const dictionary& dict, + const fvMesh& mesh, + bool readIfNecessary + ); + + //- Default boundary type is calculated + template<class T> + static inline word defaultBoundaryType(const T&) + { + return "calculated"; + } + + //- Default boundary type for volume fields is zeroGradient + template<class Type> + static inline word defaultBoundaryType + ( + const GeometricField<Type, fvPatchField, volMesh>& + ) + { + return "zeroGradient"; + } + + + //- Apply correctBoundaryConditions (volume fields only) + template<class T> + static inline void correctField(T&) {} + + template<class Type> + static inline void correctField + ( + GeometricField<Type, fvPatchField, volMesh>& fld + ) + { + fld.correctBoundaryConditions(); + } + + + // Protected Member Functions + + // Mesh related + + //- The mesh we are attached to + virtual const fvMesh& mesh() const = 0; + + + // Variables + + //- Define scopes for global variables + void setGlobalScopes(const wordUList& scopes) + { + globalScopes_ = scopes; + } + + //- Non-const access to the named variable (sub-classes only) + inline virtual exprResult& variable(const word& name); + + //- Test existence of a global variable + template<class T> + bool isGlobalVariable + ( + const word& name, + bool isPointVal, + label expectedSize = -1 + ) const; + + //- Return the global variable if available or a null result + const exprResult& lookupGlobal(const word& name) const; + + + // Fields + + //- Test for the existence of a mesh field + template<class Type> + bool isField + ( + const word& name, + bool isPointVal = false, + label expectSize = -1 //!< ignored + ) const; + + + //- Retrieve field from memory or disk + template<class GeomField> + inline tmp<GeomField> getOrReadField + ( + const word& name, + bool mandatory = true, + bool getOldTime = false + ); + + //- Retrieve point field from memory or disk + template<class GeomField> + inline tmp<GeomField> getOrReadPointField + ( + const word& name, + bool mandatory = true, + bool getOldTime = false + ); + + //- Retrieve field from memory or disk (implementation) + template<class GeomField, class MeshRef> + tmp<GeomField> getOrReadFieldImpl + ( + const word& name, + const MeshRef& meshRef, + bool mandatory = true, + bool getOldTime = false + ); + + //- Helper function for getOrReadField + template<class GeomField, class MeshRef> + inline tmp<GeomField> readAndRegister + ( + const word& name, + const MeshRef& meshRef + ); + + //- Create a random field + // + // \param field the field to populate + // \param seed the seed value. If zero or negative, use as an offset + // to the current timeIndex + // \param gaussian generate a Gaussian distribution + void fill_random + ( + scalarField& field, + label seed = 0, + const bool gaussian = false + ) const; + + + // Sets + + //- The origin of the topoSet + enum SetOrigin { INVALID = 0, NEW, FILE, MEMORY, CACHE }; + + //- Get topoSet + template<class T> + autoPtr<T> getTopoSet + ( + const fvMesh& mesh, + const word& setName, + SetOrigin& origin + ) const; + + //- Update topoSet + template<class T> + inline bool updateSet + ( + autoPtr<T>& setPtr, + const word& setName, + SetOrigin origin + ) const; + + + // Updating + + //- Examine current variable values and update stored variables + virtual void updateSpecialVariables(bool force=false); + + //- Do we need a data file to be written + virtual bool hasDataToWrite() const; + + //- Prepare/update special variables and add to dictionary, + //- normally via the reader/writer + virtual void prepareData(dictionary& dict) const; + + //- Read data from dictionary, normally via the reader/writer + virtual void getData(const dictionary& dict); + + +public: + + // Friends + friend class exprDriverWriter; + + + // Static Member Functions + + //- Get the default mesh, if one is defined + static const fvMesh& defaultMesh(); + + //- Set the default mesh (if not already set) + static const fvMesh* resetDefaultMesh + ( + const fvMesh& mesh, + const bool force = false //!< Force reset, even if already set + ); + + + //- Runtime type information + TypeName("fvExprDriver"); + + + // Run-time selection + + declareRunTimeSelectionTable + ( + autoPtr, + fvExprDriver, + dictionary, + ( + const dictionary& dict, + const fvMesh& mesh + ), + (dict,mesh) + ); + + declareRunTimeSelectionTable + ( + autoPtr, + fvExprDriver, + idName, + ( + const word& ident, + const fvMesh& mesh + ), + (ident, mesh) + ); + + + // Constructors + + //- Null constructor, and null construct with search preferences + explicit fvExprDriver + ( + bool cacheReadFields = false, + bool searchInMemory = true, + bool searchFiles = false, + const dictionary& dict = dictionary::null + ); + + //- Copy construct + fvExprDriver(const fvExprDriver&); + + //- Construct from a dictionary + explicit fvExprDriver(const dictionary& dict); + + + //- Return a reference to the selected value driver + static autoPtr<fvExprDriver> New + ( + const dictionary& dict, + const fvMesh& mesh + ); + + //- Return a reference to the selected value driver + static autoPtr<fvExprDriver> New + ( + const dictionary& dict + ); + + //- Return a reference to the selected value driver + static autoPtr<fvExprDriver> New + ( + const word& type, + const word& id, + const fvMesh& mesh + ); + + //- Clone + virtual autoPtr<fvExprDriver> clone() const = 0; + + + //- Destructor + virtual ~fvExprDriver(); + + + // Public Member Functions + + //- The underlying field size for the expression + virtual label size() const = 0; + + //- The underlying point field size for the expression + virtual label pointSize() const = 0; + + + // Mesh Related + + //- The Time associated with the mesh + const Time& runTime() const; + + //- The current time name + virtual word timeName() const; + + //- The current time value + virtual scalar timeValue() const; + + + // General Controls + + //- Status of cache-sets (static variable) + bool cacheSets() const { return cacheSets_; } + + + // Variables + + //- Clear temporary variables and resets from expression strings + virtual void clearVariables(); + + //- True if named variable exists + inline virtual bool hasVariable(const word& name) const; + + //- Return const-access to the named variable + inline virtual const exprResult& variable(const word& name) const; + + //- Test for existence of a local/global variable or a field + template<class Type> + inline bool isVariableOrField + ( + const word& name, + bool isPointVal = false, + label expectSize = -1 + ) const; + + //- Retrieve local/global variable as a tmp field + // + // \param name The name of the local/global field + // \param expectSize The size check on the variable, -1 to ignore + // \param mandatory A missing variable is Fatal, or return + // an invalid tmp + template<class Type> + tmp<Field<Type>> getVariable + ( + const word& name, + label expectSize, + const bool mandatory = true + ) const; + + + //- Lookup the field class name (memory or read from disk) + // + // Return empty if the name cannot be resolved. + word getFieldClassName(const word& name) const; + + + // Types + + //- Return cell/face/point set type or unknown + topoSetSource::sourceType topoSetType(const word& name) const; + + //- Return cell/face/point zone type or unknown + topoSetSource::sourceType topoZoneType(const word& name) const; + + //- Return cell/face/point zone/set type or unknown + topoSetSource::sourceType topoSourceType(const word& name) const; + + //- Read and return labels associated with the topo set + labelList getTopoSetLabels + ( + const word& name, + enum topoSetSource::sourceType setType + ) const; + + //- Test if name is a known cellZone + bool isCellZone(const word& name) const; + + //- Test if name is a known faceZone + bool isFaceZone(const word& name) const; + + //- Test if name is a known pointZone + bool isPointZone(const word& name) const; + + //- Test if name is a known cellSet + bool isCellSet(const word& name) const; + + //- Test if name is a known faceSet + bool isFaceSet(const word& name) const; + + //- Test if name is a known pointSet + bool isPointSet(const word& name) const; + + + // Evaluation + + //- Evaluate the expression + //- and save as the specified named variable + virtual void evaluateVariable + ( + const word& varName, + const expressions::exprString& expr + ); + + //- Evaluate an expression on a remote + //- and save as the specified named variable + // + // The fully qualified form of the remote is given as follows + // \verbatim + // type'name/region + // \endverbatim + // + // If not specified, the default type is "patch", which means the + // following are equivalent + // \verbatim + // patch'name/region + // name/region + // \endverbatim + // + // If region is identical to the current region, it can be omitted: + // \verbatim + // patch'name + // name (default is patch) + // \endverbatim + virtual void evaluateVariableRemote + ( + string remote, + const word& varName, + const expressions::exprString& expr + ); + + + // Fields + + //- Test existence of a local/global variable + template<class Type> + inline bool isVariable + ( + const word& name, + bool isPointVal = false, + label expectSize = -1 + ) const; + + //- Test if specified field can be found in memory or disk + template<class Type> + bool foundField(const word& name) const; + + //- Read the IOobject for fieldName and return its headerClassName + // Empty if the field could not be found. + word getTypeOfField(const word& fieldName) const; + + + // Handling remote data (future) + + // //- Access the other mesh name (future) + // const word& otherMeshName() const { return otherMeshName_; } + // + // //- Access the other mesh name (future) + // word& otherMeshName() { return otherMeshName_; } + + + // Reading + + //- Read variables, tables etc. + // Also usable for objects not constructed from a dictionary. + virtual bool readDict(const dictionary& dict); + + + // Writing + + //- Write "variables", "storedVariables", "delayedVariables", + //- "globalScopes" if they are present. + Ostream& writeCommon(Ostream& os, bool debug=false) const; + + //- Create a writer for this object + void createWriterAndRead(const word& name); + + //- Write data if apropriate + //- Should enable exact restarts + void tryWrite() const; + + + // Plugins (future) + + /// //- Tests for a plugin-function + /// virtual bool hasPlugin(const word& name) = 0; + /// + /// //- Return a new plugin-function + /// virtual autoPtr<CommonPluginFunction> + /// getPlugin(const word& name) = 0; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "fvExprDriverI.H" + +#ifdef NoRepository + #include "fvExprDriverTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverFields.C b/src/finiteVolume/expressions/base/fvExprDriverFields.C new file mode 100644 index 0000000000000000000000000000000000000000..d2610385a81c7bd8d2ca029a7a4fdae78e5982f0 --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverFields.C @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "fvExprDriver.H" +#include "Time.H" + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::expressions::fvExprDriver::fill_random +( + scalarField& field, + label seed, + const bool gaussian +) const +{ + exprDriver::fill_random + ( + field, (seed <= 0 ? (runTime().timeIndex() - seed) : seed), + gaussian + ); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverI.H b/src/finiteVolume/expressions/base/fvExprDriverI.H new file mode 100644 index 0000000000000000000000000000000000000000..004871bc5d310cd04c59ff8e6c2b7b9623b04561 --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverI.H @@ -0,0 +1,179 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "Time.H" + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline bool Foam::expressions::fvExprDriver::hasVariable +( + const word& name +) const +{ + return delayedVariables_.found(name) || variables_.found(name); +} + + +inline const Foam::expressions::exprResult& +Foam::expressions::fvExprDriver::variable +( + const word& name +) const +{ + if (delayedVariables_.found(name)) + { + return delayedVariables_[name]; + } + + return variables_[name]; +} + + +inline Foam::expressions::exprResult& +Foam::expressions::fvExprDriver::variable +( + const word& name +) +{ + if (delayedVariables_.found(name)) + { + return delayedVariables_[name]; + } + + return variables_[name]; +} + + +template<class Type> +inline bool Foam::expressions::fvExprDriver::isVariable +( + const word& name, + bool isPointVal, + label expectedSize +) const +{ + return + ( + this->isLocalVariable<Type>(name, isPointVal, expectedSize) + || this->isGlobalVariable<Type>(name, isPointVal, expectedSize) + ); +} + + +template<class Type> +inline bool Foam::expressions::fvExprDriver::isVariableOrField +( + const word& name, + bool isPointVal, + label expectedSize +) +const +{ + return + ( + this->isVariable<Type>(name, isPointVal, expectedSize) + || this->isField<Type>(name, isPointVal) + ); +} + + +template<class GeomField> +inline Foam::tmp<GeomField> +Foam::expressions::fvExprDriver::getOrReadField +( + const word& name, + bool mandatory, + bool getOldTime +) +{ + return this->getOrReadFieldImpl<GeomField> + ( + name, + this->mesh(), + mandatory, + getOldTime + ); +} + + +template<class GeomField> +inline Foam::tmp<GeomField> +Foam::expressions::fvExprDriver::getOrReadPointField +( + const word& name, + bool mandatory, + bool getOldTime +) +{ + return this->getOrReadFieldImpl<GeomField> + ( + name, + pointMesh::New(this->mesh()), + mandatory, + getOldTime + ); +} + + +template<class GeomField, class Mesh> +inline Foam::tmp<GeomField> +Foam::expressions::fvExprDriver::readAndRegister +( + const word& name, + const Mesh& meshRef +) +{ + GeomField* ptr = new GeomField + ( + IOobject + ( + name, + meshRef.thisDb().time().timeName(), + meshRef.thisDb(), + IOobject::MUST_READ, + IOobject::NO_WRITE, + false // Unregistered + ), + meshRef + ); + + if (cacheReadFields()) + { + DebugInfo + << "Registering a copy of " << name << " with mesh" << nl; + + // This is clunky + ptr->checkIn(); + return tmp<GeomField>(regIOobject::store(ptr)); + } + + return tmp<GeomField>(ptr); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverIO.C b/src/finiteVolume/expressions/base/fvExprDriverIO.C new file mode 100644 index 0000000000000000000000000000000000000000..3a25df5bdb6d4ec33f824fee81699a4141c01f95 --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverIO.C @@ -0,0 +1,280 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "fvExprDriver.H" +#include "exprDriverWriter.H" +#include "cellSet.H" +#include "faceSet.H" +#include "pointSet.H" + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +Foam::labelList Foam::expressions::fvExprDriver::getTopoSetLabels +( + const word& name, + enum topoSetSource::sourceType setType +) const +{ + // Zones first - they are cheap to handle (no IO) + + switch (setType) + { + case topoSetSource::sourceType::CELLZONE_SOURCE: + { + const auto& zones = mesh().cellZones(); + const word& zoneTypeName = cellZone::typeName; + + const label zoneID = zones.findZoneID(name); + if (zoneID < 0) + { + FatalErrorInFunction + << "No " << zoneTypeName << " named " + << name << "found. Has zones: " << zones.names() << endl + << exit(FatalError); + } + + return zones[zoneID]; + break; + } + + case topoSetSource::sourceType::FACEZONE_SOURCE: + { + const auto& zones = mesh().faceZones(); + const word& zoneTypeName = faceZone::typeName; + + const label zoneID = zones.findZoneID(name); + if (zoneID < 0) + { + FatalErrorInFunction + << "No " << zoneTypeName << " named " + << name << "found. Has zones: " << zones.names() << endl + << exit(FatalError); + } + + return zones[zoneID]; + break; + } + + case topoSetSource::sourceType::POINTZONE_SOURCE: + { + const auto& zones = mesh().pointZones(); + const word& zoneTypeName = pointZone::typeName; + + const label zoneID = zones.findZoneID(name); + if (zoneID < 0) + { + FatalErrorInFunction + << "No " << zoneTypeName << " named " + << name << "found. Has zones: " << zones.names() << endl + << exit(FatalError); + } + + return zones[zoneID]; + break; + } + + default: + break; + } + + + IOobject io(topoSet::findIOobject(mesh(), name)); + + switch (setType) + { + case topoSetSource::sourceType::CELLSET_SOURCE: + { + typedef cellSet classType; + + if (classType::typeName != io.headerClassName()) + { + FatalErrorInFunction + << "Error reading " << classType::typeName + << " <" << name << "> : found " + << io.headerClassName() << nl + << exit(FatalError); + } + + classType set(io); + return set.sortedToc(); + break; + } + + case topoSetSource::sourceType::FACESET_SOURCE: + { + typedef faceSet classType; + + if (classType::typeName != io.headerClassName()) + { + FatalErrorInFunction + << "Error reading " << classType::typeName + << " <" << name << "> : found " + << io.headerClassName() << nl + << exit(FatalError); + } + + classType set(io); + return set.sortedToc(); + break; + } + + case topoSetSource::sourceType::POINTSET_SOURCE: + { + typedef pointSet classType; + + if (classType::typeName != io.headerClassName()) + { + FatalErrorInFunction + << "Error reading " << classType::typeName + << " <" << name << "> : found " + << io.headerClassName() << nl + << exit(FatalError); + } + + classType set(io); + return set.sortedToc(); + break; + } + + default: + { + FatalErrorInFunction + << "Unexpected sourceType: " << int(setType) << nl + << " for set <" << name << ">" << nl + << exit(FatalError); + break; + } + } + + return labelList::null(); +} + + +Foam::word Foam::expressions::fvExprDriver::getHeaderClassName +( + const polyMesh& mesh, + const word& name +) +{ + IOobject io + ( + name, + mesh.time().timeName(), + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ); + io.typeHeaderOk<IOobject>(false); + + DebugInfo + << "Registry: " << mesh.path() + << " Name: " << name + << " Time: " << mesh.time().timeName() + << " Path: " << io.localFilePath(io.headerClassName()) + << " Class: " << io.headerClassName() << endl; + + return io.headerClassName(); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::Ostream& Foam::expressions::fvExprDriver::writeCommon +( + Ostream& os, + bool debug +) const +{ + // Write "variables", even if empty + writeVariableStrings(os, "variables"); + + if (debug) + { + os.writeEntry("variableValues", variables_); + } + + if (!storedVariables_.empty() || !delayedVariables_.empty()) + { + const_cast<fvExprDriver&> + ( + *this + ).updateSpecialVariables(true); + } + + if (!storedVariables_.empty()) + { + os.writeEntry("storedVariables", storedVariables_); + } + + if (!delayedVariables_.empty()) + { + List<exprResultDelayed> list(delayedVariables_.size()); + + auto outIter = list.begin(); + + forAllConstIters(delayedVariables_, iter) + { + *outIter = *iter; + ++outIter; + } + + os.writeEntry("delayedVariables", list); + } + + if (!globalScopes_.empty()) + { + os.writeEntry("globalScopes", globalScopes_); + } + + // writeTable(os, "timelines", lines_); + // writeTable(os, "lookuptables", lookup_); + // writeTable(os, "lookuptables2D", lookup2D_); + + return os; +} + + +void Foam::expressions::fvExprDriver::createWriterAndRead(const word& name) +{ + if (hasDataToWrite() && !writer_.valid()) + { + writer_.set(new exprDriverWriter(name + "_" + this->type(), *this)); + } +} + + +void Foam::expressions::fvExprDriver::tryWrite() const +{ + if (writer_.valid() && mesh().time().outputTime()) + { + writer_->write(); + } +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverNew.C b/src/finiteVolume/expressions/base/fvExprDriverNew.C new file mode 100644 index 0000000000000000000000000000000000000000..f2abd79e7be305ec1cc5c32ad93b7729ab86caeb --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverNew.C @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "fvExprDriver.H" + +// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * // + +Foam::autoPtr<Foam::expressions::fvExprDriver> +Foam::expressions::fvExprDriver::New +( + const dictionary& dict +) +{ + return fvExprDriver::New + ( + dict, + defaultMesh() + ); +} + + +Foam::autoPtr<Foam::expressions::fvExprDriver> +Foam::expressions::fvExprDriver::New +( + const dictionary& dict, + const fvMesh& mesh +) +{ + const word driverType(dict.get<word>("valueType")); + + auto cstrIter = dictionaryConstructorTablePtr_->cfind(driverType); + + if (!cstrIter.found()) + { + FatalIOErrorInLookup + ( + dict, + "valueType", + driverType, + *dictionaryConstructorTablePtr_ + ) << exit(FatalIOError); + } + + DebugInFunction << "Creating driver of type " << driverType << endl; + + resetDefaultMesh(mesh, false); // lazy + + return autoPtr<fvExprDriver>(cstrIter()(dict, mesh)); +} + + +Foam::autoPtr<Foam::expressions::fvExprDriver> +Foam::expressions::fvExprDriver::New +( + const word& driverType, + const word& id, + const fvMesh& mesh +) +{ + auto cstrIter = idNameConstructorTablePtr_->cfind(driverType); + + if (!cstrIter.found()) + { + FatalErrorInLookup + ( + "valueType", + driverType, + *idNameConstructorTablePtr_ + ) << exit(FatalError); + } + + DebugInFunction << "Creating driver of type " << driverType << endl; + + resetDefaultMesh(mesh, false); // lazy + + return autoPtr<fvExprDriver>(cstrIter()(id, mesh)); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/base/fvExprDriverTemplates.C b/src/finiteVolume/expressions/base/fvExprDriverTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..70eda6a08d82f0099279dc00e98f6101d9ffcb24 --- /dev/null +++ b/src/finiteVolume/expressions/base/fvExprDriverTemplates.C @@ -0,0 +1,626 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2010-2018 Bernhard Gschaider <bgschaid@hfd-research.com> + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "surfaceMesh.H" +#include "fvsPatchField.H" +#include "pointPatchField.H" + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<class Type> +bool Foam::expressions::fvExprDriver::isGlobalVariable +( + const word& name, + bool isPointVal, + label expectedSize +) const +{ + DebugInfo + << "Looking for global" << (isPointVal ? " point" : "") + << " field name:" << name; + + const exprResult& result = lookupGlobal(name); + + DebugInfo + << " - found (" << result.valueType() << ' ' << result.isPointValue() << ')'; + + + bool good = (result.isType<Type>() && result.isPointValue(isPointVal)); + + // Do size checking if requested + if (good && expectedSize >= 0) + { + good = (result.size() == expectedSize); + reduce(good, andOp<bool>()); + + if (debug && !good) + { + Info<< " size is"; + } + } + + DebugInfo << (good ? " good" : " bad") << endl; + + return good; +} + + +template<class Type> +Foam::tmp<Foam::Field<Type>> +Foam::expressions::fvExprDriver::getVariable +( + const word& name, + label expectedSize, + const bool mandatory +) const +{ + tmp<Field<Type>> tresult; + + bool isSingleValue = false; + + if (hasVariable(name) && variable(name).isType<Type>()) + { + isSingleValue = variable(name).isUniform(); + tresult = variable(name).cref<Type>().clone(); + } + else if (isGlobalVariable<Type>(name, false)) + { + const exprResult& var = lookupGlobal(name); + + isSingleValue = var.isUniform(); + + tresult = var.cref<Type>().clone(); + } + + if (tresult.valid()) + { + if + ( + expectedSize < 0 + || returnReduce((tresult->size() == expectedSize), andOp<bool>()) + ) + { + return tresult; + } + + if (!isSingleValue) + { + WarningInFunction + << "Variable " << name + << " is not a single value and does not fit the size " + << expectedSize << ". Using average" << endl; + } + + return tmp<Field<Type>>::New(expectedSize, gAverage(tresult())); + } + + if (mandatory) + { + FatalErrorInFunction + << "Variable (" << name << ") not found." << nl + << exit(FatalError); + } + + return nullptr; +} + + +template<class Type> +bool Foam::expressions::fvExprDriver::foundField +( + const word& name +) const +{ + if (debug) + { + Info<< "fvExprDriver::foundField. Name: " << name + << " Type: " << Type::typeName + << " registry:" << searchInMemory() + << " disk:" << searchFiles() << endl; + } + + // if (std::is_void<Type>::value) ... + + if (searchInMemory()) + { + const regIOobject* ioptr = + this->mesh().findObject<regIOobject>(name); + + if (this->mesh().foundObject<Type>(name)) + { + if (debug) + { + Info<< "Found registered: " << name << endl; + } + return true; + } + + if (debug) + { + Info<< "Registered " << name; + + if (ioptr) + { + Info<< " type:" << ioptr->headerClassName(); + } + Info<< ", not type:" << Type::typeName << nl; + } + } + + + if (searchFiles() && getTypeOfField(name) == Type::typeName) + { + if (debug) + { + Info<< "Found file: " << name << nl; + } + return true; + } + else + { + if (debug) + { + Info<< name << " not found" << endl; + } + } + + return false; +} + + +template<class Type> +bool Foam::expressions::fvExprDriver::isField +( + const word& name, + bool isPointVal, + label +) const +{ + if (debug) + { + Info<< "fvExprDriver::isField <" << name << '>' << endl; + } + + typedef GeometricField<Type, fvPatchField, volMesh> vfieldType; + typedef GeometricField<Type, fvsPatchField, surfaceMesh> sfieldType; + typedef GeometricField<Type, pointPatchField, pointMesh> pfieldType; + + return + ( + isPointVal + ? this->foundField<pfieldType>(name) + : + ( + this->foundField<vfieldType>(name) + || this->foundField<sfieldType>(name) + ) + ); +} + + +template<class GeomField, class Mesh> +Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl +( + const word& name, + const Mesh& meshRef, + bool mandatory, + bool getOldTime +) +{ + typedef typename GeomField::value_type Type; + + if (debug) + { + Info<< "fvExprDriver::getOrReadField <" << name + << "> Type: " << GeomField::typeName << endl; + } + + tmp<GeomField> tfield; + + if + ( + (hasVariable(name) && variable(name).isType<Type>()) + || isGlobalVariable<Type>(name, false) + ) + { + if (debug) + { + Info<< "Getting " << name << " from variables" << endl; + } + + if (debug) + { + Info<< "Creating field " << name << " of type " + << GeomField::typeName << nl; + } + + tfield.reset + ( + GeomField::New(name, meshRef, dimensioned<Type>(Zero)) + ); + + GeomField& fld = tfield.ref(); + + if (debug) + { + Info<< "New field: " << name << " ownedByRegistry" + << fld.ownedByRegistry() << endl; + } + + Field<Type> vals; + + if (hasVariable(name) && variable(name).isType<Type>()) + { + vals = variable(name).cref<Type>(); + } + else + { + vals = lookupGlobal(name).cref<Type>(); + } + + if (debug) + { + Pout<< "sizes: " << vals.size() << ' ' << fld.size() << endl; + } + + if (returnReduce((vals.size() == fld.size()), andOp<bool>())) + { + fld.primitiveFieldRef() = vals; + } + else + { + Type avg = gAverage(vals); + + bool noWarn = false; + + if (!noWarn) + { + MinMax<Type> range = gMinMax(vals); + + if (range.mag() > SMALL) + { + WarningInFunction + << "The min/max ranges differ " << range + << " - using average " << avg << nl; + } + } + + fld.primitiveFieldRef() = avg; + } + + correctField(fld); + + return tfield; + } + + + const objectRegistry& obr = meshRef.thisDb(); + + if (searchInMemory() && obr.foundObject<GeomField>(name)) + { + if (debug) + { + Info<< "Retrieve registered: " << name << nl; + } + + const GeomField& origFld = obr.lookupObject<GeomField>(name); + + // Avoid shadowing the original object + + tfield.reset + ( + GeomField::New(name + "_exprDriverCopy", origFld) + ); + + if (getOldTime) + { + if (debug) + { + Info<< "Getting oldTime of " << name << " has " + << origFld.nOldTimes() << endl; + } + + if (!origFld.nOldTimes() && this->prevIterIsOldTime()) + { + if (debug) + { + Info<< "No oldTime, using previous iteration" << endl; + } + tfield.ref().oldTime() = origFld.prevIter(); + } + } + } + else if (searchFiles() && getTypeOfField(name) == GeomField::typeName) + { + if (debug) + { + Info<< "Reading " << name << " from disc" << endl; + } + + tfield.reset + ( + this->readAndRegister<GeomField>(name, meshRef) + ); + // oldTime automatically read + } + + if (debug) + { + Info<< "field: valid()=" << tfield.valid() << endl; + } + + if (tfield.valid()) + { + GeomField& fld = tfield.ref(); + + if (debug) + { + Info<< "Valid " << name << " found. Removing dimensions" << nl; + } + + fld.dimensions().clear(); + + if (fld.nOldTimes()) + { + if (debug) + { + Info<< "Removing dimensions of oldTime of " << name + << " has " << fld.nOldTimes() << nl; + } + + // Switch dimension checking off + const int oldDebug = dimensionSet::debug; + dimensionSet::debug = 0; + + // go through ALL old times + GeomField* fp = &(fld); + + while (fp->nOldTimes()) + { + fp = &(fp->oldTime()); + fp->dimensions().clear(); + } + + // Restore old value of dimension checking + dimensionSet::debug = oldDebug; + } + } + else if (mandatory) + { + FatalErrorInFunction + << "Could not find field " << name + << " in registry or on file-system" << nl + << exit(FatalError); + } + + return tfield; +} + + +template<class T> +Foam::autoPtr<T> Foam::expressions::fvExprDriver::getTopoSet +( + const fvMesh& mesh, + const word& name, + SetOrigin& origin +) const +{ + // Avoid possible name clashes + const word regName = name + "RegisteredNameFor" + T::typeName; + + if (debug) + { + Info<< "Looking for " << T::typeName << " named " << name; + + Info<< " or registered as " << regName << " with mesh " + << "Caching:" << cacheSets() + << " Found:" << (mesh.foundObject<T>(name)) + << " Found registered:" << mesh.foundObject<T>(regName) + << endl; + } + + + origin = SetOrigin::INVALID; + autoPtr<T> setPtr; + + if + ( + !cacheSets() + || + ( + !mesh.thisDb().foundObject<T>(regName) + && !mesh.thisDb().foundObject<T>(name) + ) + ) + { + if (debug) + { + Info<< "Constructing new " << T::typeName << ' ' << name << nl; + + if (debug > 1) + { + Pout<< mesh.thisDb().names(); + } + } + + origin = SetOrigin::FILE; + setPtr.reset(new T(mesh, name, IOobject::MUST_READ)); + + if (cacheSets()) + { + if (debug) + { + Info<< "Registering a copy of " << name << " with mesh" << nl; + } + + autoPtr<T> toCache(new T(mesh, regName, *setPtr)); + toCache->store(toCache); + } + } + else + { + const T* ptr = mesh.thisDb().findObject<T>(name); + + if (ptr) + { + if (debug) + { + Info<< "Getting existing " << name << endl; + } + + origin = SetOrigin::MEMORY; + setPtr.reset(new T(mesh, name, *ptr)); + } + else + { + if (debug) + { + Info<< "Getting existing " << regName << endl; + } + + origin = SetOrigin::CACHE; + setPtr.reset(new T(mesh, name, mesh.lookupObject<T>(regName))); + } + } + + + return setPtr; +} + + +template<class T> +bool Foam::expressions::fvExprDriver::updateSet +( + autoPtr<T>& setPtr, + const word& name, + SetOrigin origin +) const +{ + const label oldSize = setPtr->size(); + + bool updated = false; + const polyMesh& mesh = dynamic_cast<const polyMesh&>(setPtr->db()); + + if (debug) + { + Info<< "UpdateSet: " << setPtr->name() << " Id: " << name + << " Origin: " << int(origin) << endl; + } + + switch (origin) + { + case SetOrigin::FILE: + { + IOobject header + ( + name, + mesh.time().timeName(), + polyMesh::meshSubDir/"sets", + mesh, + IOobject::MUST_READ, + IOobject::NO_WRITE + ); + + if (header.typeHeaderOk<T>()) + { + if (debug) + { + Pout<< "Rereading from " + << header.localFilePath(T::typeName) << endl; + } + setPtr.reset(new T(header)); + updated = true; + } + break; + } + + case SetOrigin::NEW: + case SetOrigin::MEMORY: + case SetOrigin::CACHE: + { + if (origin == SetOrigin::NEW) + { + WarningInFunction + << "State NEW shouldn't exist" + << endl; + } + + word sName = name; + + const T* ptr = mesh.thisDb().findObject<T>(name); + + if (ptr) + { + if (debug) + { + Info<< "Found " << name + << " and rereading it" << endl; + } + + setPtr.reset(new T(mesh, name, *ptr)); + } + else + { + FatalErrorInFunction + << name << " Not found" << endl + << "In registry: " << mesh.thisDb().names() << endl + << exit(FatalError); + } + updated = true; + break; + } + + case INVALID: + { + FatalErrorInFunction + << T::typeName << ' ' << name << " is invalid" << endl + << exit(FatalError); + break; + } + + default: + { + if (debug) + { + Info<< "Origin " << int(origin) << " not implemented" << endl; + } + break; + } + } + + if (debug) + { + Pout<< name << " old size " << oldSize << " new: " + << setPtr->size() << endl; + } + + return updated; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/base/patchExprFieldBase.C b/src/finiteVolume/expressions/fields/base/patchExprFieldBase.C new file mode 100644 index 0000000000000000000000000000000000000000..a00d9b115ddd053d7ec8a49bd77b819f9535da43 --- /dev/null +++ b/src/finiteVolume/expressions/fields/base/patchExprFieldBase.C @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2011-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "patchExprFieldBase.H" +#include "facePointPatch.H" +#include "fvMesh.H" +#include "fvPatch.H" +#include "pointMesh.H" + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +const Foam::fvPatch& +Foam::expressions::patchExprFieldBase::getFvPatch(const facePointPatch& pp) +{ + const polyMesh& pmesh = pp.boundaryMesh().mesh().mesh(); + + const fvMesh* meshptr = isA<fvMesh>(pmesh); + + if (!meshptr) + { + FatalErrorInFunction + << "Point patch not attached to a base fvMesh, " + << "cannot use patch expressions" << nl << endl + << exit(FatalError); + } + + return meshptr->boundary()[pp.index()]; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::patchExprFieldBase::patchExprFieldBase() +: + patchExprFieldBase(false) +{} + + +Foam::expressions::patchExprFieldBase::patchExprFieldBase +( + bool allowGradient +) +: + debug_(false), + allowGradient_(allowGradient), + evalOnConstruct_(false), + valueExpr_(), + gradExpr_(), + fracExpr_() +{} + + +Foam::expressions::patchExprFieldBase::patchExprFieldBase +( + const dictionary& dict, + bool allowGradient, + bool isPointVal +) +: + debug_(dict.lookupOrDefault("debug", false)), + allowGradient_(allowGradient), + evalOnConstruct_(dict.lookupOrDefault<bool>("evalOnConstruct", false)), + valueExpr_(), + gradExpr_(), + fracExpr_() +{ + if (debug_) + { + Info<< "Expression BC with " << dict << nl; + } + + string expr; + + if (dict.readIfPresent("valueExpr", expr)) + { + valueExpr_ = expressions::exprString(expr, dict); + } + else + { + // No value expression - same as Zero + if (debug_) + { + Info<< "No valueExpr" << nl; + } + } + + if (allowGradient) + { + if (dict.readIfPresent("gradientExpr", expr)) + { + gradExpr_ = expressions::exprString(expr, dict); + } + else + { + // No gradient expression - same as Zero + + if (debug_) + { + Info<< "No gradientExpr" << nl; + } + } + + if (dict.readIfPresent("fractionExpr", expr)) + { + if (!expr.empty() && expr != "0") + { + if (isPointVal) + { + expr = "toPoint(" + expr + ")"; + } + + fracExpr_ = expressions::exprString(expr, dict); + } + } + else + { + // No fraction expression - same as 1 (one) + // Mixed BC may elect to simply ignore gradient expression + } + } +} + + +Foam::expressions::patchExprFieldBase::patchExprFieldBase +( + const patchExprFieldBase& rhs +) +: + debug_(rhs.debug_), + allowGradient_(rhs.allowGradient_), + evalOnConstruct_(rhs.evalOnConstruct_), + valueExpr_(rhs.valueExpr_), + gradExpr_(rhs.gradExpr_), + fracExpr_(rhs.fracExpr_) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::expressions::patchExprFieldBase::write(Ostream& os) const +{ + os.writeEntryIfDifferent<bool>("evalOnConstruct", false, evalOnConstruct_); + + // Do not emit debug_ value + + if (!valueExpr_.empty()) + { + os.writeEntry("valueExpr", valueExpr_); + } + if (!gradExpr_.empty()) + { + os.writeEntry("gradientExpr", gradExpr_); + } + if (!fracExpr_.empty()) + { + os.writeEntry("fractionExpr", fracExpr_); + } +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/base/patchExprFieldBase.H b/src/finiteVolume/expressions/fields/base/patchExprFieldBase.H new file mode 100644 index 0000000000000000000000000000000000000000..5c802b10aa5e13952af01febf009fd4040472680 --- /dev/null +++ b/src/finiteVolume/expressions/fields/base/patchExprFieldBase.H @@ -0,0 +1,131 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2011-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::patchExprFieldBase + +Description + Base class for managing patches with expressions. + The expected input supports values, gradients and mixed conditions + +Usage + \table + Property | Description | Required | Default + valueExpr | expression for fixed value | no | 0 + gradientExpr | expression for patch normal gradient | no | 0 + fractionExpr | expression for value fraction weight | no | 1 + \endtable + +SourceFiles + patchExprFieldBase.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_patchExprFieldBase_H +#define expressions_patchExprFieldBase_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "dictionary.H" +#include "exprString.H" + +namespace Foam +{ + +// Forward Declarations +class facePointPatch; +class fvPatch; + +namespace expressions +{ + +/*---------------------------------------------------------------------------*\ + Class patchExprFieldBase Declaration +\*---------------------------------------------------------------------------*/ + +class patchExprFieldBase +{ +protected: + + // Protected Data + + bool debug_; + bool allowGradient_; + + //- Slightly dodgy concept here + bool evalOnConstruct_; + + // The expressions + expressions::exprString valueExpr_; + expressions::exprString gradExpr_; + expressions::exprString fracExpr_; + + +public: + + // Static Methods + + //- Find (guess) fvPatch from a pointPatch + static const fvPatch& getFvPatch(const facePointPatch& fp); + + + // Constructors + + //- Null constructor + patchExprFieldBase(); + + //- Construct with specified gradient handling + explicit patchExprFieldBase(bool allowGradient); + + //- Construct from dictionary + explicit patchExprFieldBase + ( + const dictionary& dict, + bool allowGradient = false, + bool isPointVal = false + ); + + //- Copy constructor + patchExprFieldBase(const patchExprFieldBase& rhs); + + + // Member Functions + + //- Write + void write(Ostream& os) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchField.C b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchField.C new file mode 100644 index 0000000000000000000000000000000000000000..35eab824d214d988887a7c7873365ed12697e255 --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchField.C @@ -0,0 +1,215 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2009-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprFixedValueFvPatchField.H" + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<class Type> +void Foam::exprFixedValueFvPatchField<Type>::setDebug() +{ + if (expressions::patchExprFieldBase::debug_ && !debug) + { + debug = 1; + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template<class Type> +Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField +( + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF +) +: + fixedValueFvPatchField<Type>(p, iF), + expressions::patchExprFieldBase(false), + driver_(this->patch()) +{} + + +template<class Type> +Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField +( + const exprFixedValueFvPatchField<Type>& ptf, + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF, + const fvPatchFieldMapper& mapper +) +: + fixedValueFvPatchField<Type>(ptf, p, iF, mapper), + expressions::patchExprFieldBase(ptf), + driver_(this->patch(), ptf.driver_) +{ + setDebug(); + DebugInFunction << nl; +} + + +template<class Type> +Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField +( + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF, + const dictionary& dict, + const bool valueRequired +) +: + fixedValueFvPatchField<Type>(p, iF), + expressions::patchExprFieldBase(dict), + driver_(this->patch(), dict) +{ + setDebug(); + DebugInFunction << nl; + + // Basic sanity + if (this->valueExpr_.empty()) + { + FatalIOErrorInFunction(dict) + << "The valueExpr was not defined!" << nl + << exit(FatalIOError); + } + + driver_.readDict(dict); + + if (dict.found("value")) + { + fvPatchField<Type>::operator= + ( + Field<Type>("value", dict, p.size()) + ); + } + else + { + (*this) == this->patchInternalField(); + + WarningInFunction + << "No value defined for " + << this->internalField().name() << " on " + << this->patch().name() << " - setting to internalField value " + << nl; + } + + if (this->evalOnConstruct_) + { + // For potentialFoam or other solvers that don't evaluate + this->evaluate(); + } +} + + +template<class Type> +Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField +( + const exprFixedValueFvPatchField<Type>& ptf +) +: + fixedValueFvPatchField<Type>(ptf), + expressions::patchExprFieldBase(ptf), + driver_(this->patch(), ptf.driver_) +{ + setDebug(); + DebugInFunction << nl; +} + + +template<class Type> +Foam::exprFixedValueFvPatchField<Type>::exprFixedValueFvPatchField +( + const exprFixedValueFvPatchField<Type>& ptf, + const DimensionedField<Type, volMesh>& iF +) +: + fixedValueFvPatchField<Type>(ptf, iF), + expressions::patchExprFieldBase(ptf), + driver_(this->patch(), ptf.driver_) +{ + setDebug(); + DebugInFunction << nl; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +void Foam::exprFixedValueFvPatchField<Type>::updateCoeffs() +{ + if (debug) + { + InfoInFunction + << "Value: " << this->valueExpr_ << nl + << "Variables: "; + driver_.writeVariableStrings(Info) << endl; + } + + if (this->updated()) + { + return; + } + + DebugInFunction + << "updating" << nl; + + // Expression evaluation + { + driver_.clearVariables(); + + if (this->valueExpr_.empty()) + { + (*this) == Zero; + } + else + { + tmp<Field<Type>> tresult(driver_.evaluate<Type>(this->valueExpr_)); + + if (debug) + { + Info<< "Evaluated: " << tresult(); + } + + (*this) == tresult; + } + } + + fixedValueFvPatchField<Type>::updateCoeffs(); +} + + +template<class Type> +void Foam::exprFixedValueFvPatchField<Type>::write(Ostream& os) const +{ + fixedValueFvPatchField<Type>::write(os); + expressions::patchExprFieldBase::write(os); + + // driver_.writeCommon(os, this->debug_ || debug); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchField.H b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchField.H new file mode 100644 index 0000000000000000000000000000000000000000..a1282f9542ad98e469868e784d408bee7179f4fb --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchField.H @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2009-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::exprFixedValueFvPatchField + +Description + A fixed value boundary condition with expressions. + +Usage + \table + Property | Description | Required | Default + value | fixed value | yes | + valueExpr | expression for fixed value | yes | + \endtable + +SourceFiles + exprFixedValueFvPatchField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef exprFixedValueFvPatchField_H +#define exprFixedValueFvPatchField_H + +#include "fixedValueFvPatchField.H" +#include "patchExprFieldBase.H" +#include "patchExprDriver.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class exprFixedValueFvPatchField Declaration +\*---------------------------------------------------------------------------*/ + +template<class Type> +class exprFixedValueFvPatchField +: + public fixedValueFvPatchField<Type>, + public expressions::patchExprFieldBase +{ +protected: + + // Protected Data + + //- The expression driver + expressions::patchExpr::parseDriver driver_; + + + // Protected Member Functions + + //- Set debug ON if "debug" is enabled + void setDebug(); + + +public: + + //- Runtime type information + TypeName("exprFixedValue"); + + + // Constructors + + //- Construct from patch and internal field + exprFixedValueFvPatchField + ( + const fvPatch& p, + const DimensionedField<Type, volMesh>& + ); + + //- Construct from patch, internal field and dictionary + exprFixedValueFvPatchField + ( + const fvPatch&, + const DimensionedField<Type, volMesh>&, + const dictionary& dict, + const bool valueRequired=true + ); + + //- Construct by mapping given exprFixedValueFvPatchField + //- onto a new patch + exprFixedValueFvPatchField + ( + const exprFixedValueFvPatchField<Type>&, + const fvPatch&, + const DimensionedField<Type, volMesh>&, + const fvPatchFieldMapper& + ); + + //- Construct as copy + exprFixedValueFvPatchField + ( + const exprFixedValueFvPatchField<Type>& + ); + + + //- Construct and return a clone + virtual tmp<fvPatchField<Type>> clone() const + { + return tmp<fvPatchField<Type>> + ( + new exprFixedValueFvPatchField<Type>(*this) + ); + } + + //- Construct as copy setting internal field reference + exprFixedValueFvPatchField + ( + const exprFixedValueFvPatchField<Type>&, + const DimensionedField<Type, volMesh>& + ); + + //- Construct and return a clone setting internal field reference + virtual tmp<fvPatchField<Type>> clone + ( + const DimensionedField<Type, volMesh>& iF + ) const + { + return tmp<fvPatchField<Type>> + ( + new exprFixedValueFvPatchField<Type>(*this, iF) + ); + } + + + // Member Functions + + //- Update the coefficients associated with the patch field + virtual void updateCoeffs(); + + //- Write + virtual void write(Ostream& os) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "exprFixedValueFvPatchField.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFields.C b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFields.C new file mode 100644 index 0000000000000000000000000000000000000000..5695a23af92259cdd71a90f05bb6c0ddf6d2264d --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFields.C @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprFixedValueFvPatchFields.H" +#include "volFields.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +makePatchFields(exprFixedValue); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFields.H b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFields.H new file mode 100644 index 0000000000000000000000000000000000000000..cab541738ed23f8bbd6e25bd6d90bb2a47c5fbf9 --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFields.H @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#ifndef exprFixedValueFvPatchFields_H +#define exprFixedValueFvPatchFields_H + +#include "exprFixedValueFvPatchField.H" +#include "fieldTypes.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +makePatchTypeFieldTypedefs(exprFixedValue); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFieldsFwd.H b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFieldsFwd.H new file mode 100644 index 0000000000000000000000000000000000000000..375adc50be8bbbf94d455c65895f751c6b80f510 --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprFixedValueFvPatchFieldsFwd.H @@ -0,0 +1,52 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#ifndef exprFixedValueFvPatchFieldsFwd_H +#define exprFixedValueFvPatchFieldsFwd_H + +#include "fieldTypes.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class Type> class exprFixedValueFvPatchField; + +makePatchTypeFieldTypedefs(exprFixedValue); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchField.C b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchField.C new file mode 100644 index 0000000000000000000000000000000000000000..c145744333a94b4c0205dec91235149e10b78f4a --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchField.C @@ -0,0 +1,309 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2009-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. +\*---------------------------------------------------------------------------*/ + +#include "exprMixedFvPatchField.H" + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<class Type> +void Foam::exprMixedFvPatchField<Type>::setDebug() +{ + if (expressions::patchExprFieldBase::debug_ && !debug) + { + debug = 1; + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template<class Type> +Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField +( + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF +) +: + mixedFvPatchField<Type>(p, iF), + expressions::patchExprFieldBase(true), // allowGradient + driver_(this->patch()) +{ + this->refValue() = Zero; + this->refGrad() = Zero; + this->valueFraction() = scalar(1); +} + + +template<class Type> +Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField +( + const exprMixedFvPatchField<Type>& ptf, + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF, + const fvPatchFieldMapper& mapper +) +: + mixedFvPatchField<Type>(ptf, p, iF, mapper), + expressions::patchExprFieldBase(ptf), + driver_(this->patch(), ptf.driver_) +{ + setDebug(); + DebugInFunction << nl; +} + + +template<class Type> +Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField +( + const fvPatch& p, + const DimensionedField<Type, volMesh>& iF, + const dictionary& dict +) +: + mixedFvPatchField<Type>(p, iF), + expressions::patchExprFieldBase(dict, true), + driver_(this->patch(), dict) +{ + setDebug(); + DebugInFunction << nl; + + // Basic sanity checks + if (this->valueExpr_.empty() && this->gradExpr_.empty()) + { + if (this->valueExpr_.empty()) + { + FatalIOErrorInFunction(dict) + << "The valueExpr was not defined!" << nl + << exit(FatalIOError); + } + if (this->gradExpr_.empty()) + { + FatalIOErrorInFunction(dict) + << "The gradientExpr was not defined!" << nl + << exit(FatalIOError); + } + } + + + driver_.readDict(dict); + + // Similar to fvPatchField constructor, which we have bypassed + dict.readIfPresent("patchType", this->patchType()); + + if (dict.found("refValue")) + { + this->refValue() = Field<Type>("refValue", dict, p.size()); + } + else + { + this->refValue() = this->patchInternalField(); + } + + if (dict.found("value")) + { + fvPatchField<Type>::operator= + ( + Field<Type>("value", dict, p.size()) + ); + + if (!dict.found("refValue")) + { + // Ensure refValue has a sensible value for the "update" below + this->refValue() = Field<Type>("value", dict, p.size()); + } + } + else + { + fvPatchField<Type>::operator=(this->refValue()); + + WarningInFunction + << "No value defined for " + << this->internalField().name() + << " on " << this->patch().name() << " therefore using " + << "the internal field next to the patch" + << endl; + } + + + if (dict.found("refGradient")) + { + this->refGrad() = Field<Type>("refGradient", dict, p.size()); + } + else + { + this->refGrad() = Zero; + } + + if (dict.found("valueFraction")) + { + this->valueFraction() = Field<scalar>("valueFraction", dict, p.size()); + } + else + { + this->valueFraction() = 1; + } + + + if (this->evalOnConstruct_) + { + // For potentialFoam or other solvers that don't evaluate + this->evaluate(); + } + else + { + // Emulate mixedFvPatchField<Type>::evaluate, + // but avoid our own updateCoeffs + if (!this->updated()) + { + this->mixedFvPatchField<Type>::updateCoeffs(); + } + + Field<Type>::operator= + ( + this->valueFraction()*this->refValue() + + + (1.0 - this->valueFraction())* + ( + this->patchInternalField() + + this->refGrad()/this->patch().deltaCoeffs() + ) + ); + + fvPatchField<Type>::evaluate(); + } +} + + +template<class Type> +Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField +( + const exprMixedFvPatchField<Type>& ptf +) +: + mixedFvPatchField<Type>(ptf), + expressions::patchExprFieldBase(ptf), + driver_(this->patch(), ptf.driver_) +{ + setDebug(); + DebugInFunction << nl; +} + + +template<class Type> +Foam::exprMixedFvPatchField<Type>::exprMixedFvPatchField +( + const exprMixedFvPatchField<Type>& ptf, + const DimensionedField<Type, volMesh>& iF +) +: + mixedFvPatchField<Type>(ptf, iF), + expressions::patchExprFieldBase(ptf), + driver_(this->patch(), ptf.driver_) +{ + setDebug(); + DebugInFunction << nl; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +void Foam::exprMixedFvPatchField<Type>::updateCoeffs() +{ + if (debug) + { + InfoInFunction + << "Value: " << this->valueExpr_ << nl + << "Gradient: " << this->gradExpr_ << nl + << "Fraction: " << this->fracExpr_ << nl + << "Variables: "; + + driver_.writeVariableStrings(Info) << endl; + } + + if (this->updated()) + { + return; + } + + DebugInFunction << " - updating" << nl; + + + // Expression evaluation + { + driver_.clearVariables(); + + if (this->valueExpr_.empty()) + { + this->refValue() = Zero; + } + else + { + this->refValue() = driver_.evaluate<Type>(this->valueExpr_); + } + + bool evalGrad = !this->gradExpr_.empty(); + + if (this->fracExpr_.empty() || this->fracExpr_ == "1") + { + evalGrad = false; + this->valueFraction() = scalar(1); + } + else if (this->fracExpr_ == "0") + { + this->valueFraction() = Zero; + } + else + { + this->valueFraction() = driver_.evaluate<scalar>(this->fracExpr_); + } + + if (evalGrad) + { + this->refGrad() = driver_.evaluate<Type>(this->gradExpr_); + } + else + { + this->refGrad() = Zero; + } + } + + mixedFvPatchField<Type>::updateCoeffs(); +} + + +template<class Type> +void Foam::exprMixedFvPatchField<Type>::write(Ostream& os) const +{ + mixedFvPatchField<Type>::write(os); + expressions::patchExprFieldBase::write(os); + + // driver_.writeCommon(os, this->debug_ || debug); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchField.H b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchField.H new file mode 100644 index 0000000000000000000000000000000000000000..53cd1bb75a67afa45d04f67290b2596bcbbef561 --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchField.H @@ -0,0 +1,172 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2009-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::exprMixedFvPatchField + +Description + A mixed boundary condition with expressions. + +Usage + \table + Property | Description | Required | Default + valueExpr | expression for fixed value | no | 0 + gradientExpr | expression for patch normal gradient | no | 0 + fractionExpr | expression for value weighting | no | 1 + \endtable + +SourceFiles + exprMixedFvPatchField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef exprMixedFvPatchField_H +#define exprMixedFvPatchField_H + +#include "mixedFvPatchField.H" +#include "patchExprFieldBase.H" +#include "patchExprDriver.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class exprMixedFvPatchField Declaration +\*---------------------------------------------------------------------------*/ + +template<class Type> +class exprMixedFvPatchField +: + public mixedFvPatchField<Type>, + public expressions::patchExprFieldBase +{ +protected: + + // Protected Data + + //- The expression driver + expressions::patchExpr::parseDriver driver_; + + + // Protected Member Functions + + //- Set debug ON if "debug" is enabled + void setDebug(); + + +public: + + //- Runtime type information + TypeName("exprMixed"); + + + // Constructors + + //- Construct from patch and internal field + exprMixedFvPatchField + ( + const fvPatch& p, + const DimensionedField<Type, volMesh>& + ); + + //- Construct from patch, internal field and dictionary + exprMixedFvPatchField + ( + const fvPatch&, + const DimensionedField<Type, volMesh>&, + const dictionary& dict + ); + + //- Construct by mapping given exprMixedFvPatchField onto a new patch + exprMixedFvPatchField + ( + const exprMixedFvPatchField<Type>&, + const fvPatch&, + const DimensionedField<Type, volMesh>&, + const fvPatchFieldMapper& + ); + + //- Construct as copy + exprMixedFvPatchField + ( + const exprMixedFvPatchField<Type>& + ); + + //- Construct and return a clone + virtual tmp<fvPatchField<Type>> clone() const + { + return tmp<fvPatchField<Type>> + ( + new exprMixedFvPatchField<Type>(*this) + ); + } + + //- Construct as copy setting internal field reference + exprMixedFvPatchField + ( + const exprMixedFvPatchField<Type>&, + const DimensionedField<Type, volMesh>& + ); + + //- Construct and return a clone setting internal field reference + virtual tmp<fvPatchField<Type> > clone + ( + const DimensionedField<Type, volMesh>& iF + ) const + { + return tmp<fvPatchField<Type>> + ( + new exprMixedFvPatchField<Type>(*this, iF) + ); + } + + + // Member Functions + + //- Update the coefficients associated with the patch field + virtual void updateCoeffs(); + + //- Write + virtual void write(Ostream& os) const; +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository + #include "exprMixedFvPatchField.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFields.C b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFields.C new file mode 100644 index 0000000000000000000000000000000000000000..730fee6baa92632203cb6a48f1c7ba7cd8f74491 --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFields.C @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprMixedFvPatchFields.H" +#include "volFields.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +makePatchFields(exprMixed); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFields.H b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFields.H new file mode 100644 index 0000000000000000000000000000000000000000..40531f0295a2c90ad287b3c27b62f05eff595c6b --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFields.H @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#ifndef exprMixedFvPatchFields_H +#define exprMixedFvPatchFields_H + +#include "exprMixedFvPatchField.H" +#include "fieldTypes.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +makePatchTypeFieldTypedefs(exprMixed); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFieldsFwd.H b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFieldsFwd.H new file mode 100644 index 0000000000000000000000000000000000000000..2db491b761a34d881d13dcf68b66e48ab37a8d0b --- /dev/null +++ b/src/finiteVolume/expressions/fields/fvPatchFields/exprMixedFvPatchFieldsFwd.H @@ -0,0 +1,52 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#ifndef exprMixedFvPatchFieldsFwd_H +#define exprMixedFvPatchFieldsFwd_H + +#include "fieldTypes.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template<class Type> class exprMixedFvPatchField; + +makePatchTypeFieldTypedefs(exprMixed); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchField.C b/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchField.C new file mode 100644 index 0000000000000000000000000000000000000000..34585032cfd8a3dedf224154a69ff7892797e747 --- /dev/null +++ b/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchField.C @@ -0,0 +1,219 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2010-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprValuePointPatchField.H" +#include "pointPatchFieldMapper.H" +#include "typeInfo.H" +#include "facePointPatch.H" + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +template<class Type> +Foam::exprValuePointPatchField<Type>::exprValuePointPatchField +( + const pointPatch& p, + const DimensionedField<Type, pointMesh>& iF +) +: + valuePointPatchField<Type>(p, iF), + expressions::patchExprFieldBase(false), + driver_ + ( + expressions::patchExprFieldBase::getFvPatch + ( + dynamicCast<const facePointPatch>(this->patch()) + ) + ) +{} + + +template<class Type> +Foam::exprValuePointPatchField<Type>::exprValuePointPatchField +( + const exprValuePointPatchField<Type>& ptf, + const pointPatch& p, + const DimensionedField<Type, pointMesh>& iF, + const pointPatchFieldMapper& mapper +) +: + valuePointPatchField<Type>(ptf, p, iF, mapper), + expressions::patchExprFieldBase(ptf), + driver_ + ( + expressions::patchExprFieldBase::getFvPatch + ( + dynamicCast<const facePointPatch>(this->patch()) + ), + ptf.driver_ + ) +{} + + +template<class Type> +Foam::exprValuePointPatchField<Type>::exprValuePointPatchField +( + const pointPatch& p, + const DimensionedField<Type, pointMesh>& iF, + const dictionary& dict +) +: + valuePointPatchField<Type>(p, iF), + expressions::patchExprFieldBase(dict, false, true), + driver_ + ( + expressions::patchExprFieldBase::getFvPatch + ( + dynamicCast<const facePointPatch>(this->patch()) + ), + dict + ) +{ + // Basic sanity + if (this->valueExpr_.empty()) + { + FatalIOErrorInFunction(dict) + << "The valueExpr was not defined!" << nl + << exit(FatalIOError); + } + + driver_.readDict(dict); + + if (dict.found("value")) + { + Field<Type>::operator= + ( + Field<Type>("value", dict, p.size()) + ); + } + else + { + WarningInFunction + << "No value defined for " + << this->internalField().name() + << " on " << this->patch().name() + << endl; + } + + if (this->evalOnConstruct_) + { + // For potentialFoam or other solvers that don't evaluate + this->evaluate(); + } +} + + +template<class Type> +Foam::exprValuePointPatchField<Type>::exprValuePointPatchField +( + const exprValuePointPatchField<Type>& ptf, + const DimensionedField<Type, pointMesh>& iF +) +: + valuePointPatchField<Type>(ptf, iF), + expressions::patchExprFieldBase(ptf), + driver_ + ( + expressions::patchExprFieldBase::getFvPatch + ( + dynamicCast<const facePointPatch>(this->patch()) + ), + ptf.driver_ + ) +{} + + +template<class Type> +Foam::exprValuePointPatchField<Type>::exprValuePointPatchField +( + const exprValuePointPatchField<Type>& ptf +) +: + valuePointPatchField<Type>(ptf), + expressions::patchExprFieldBase(ptf), + driver_ + ( + expressions::patchExprFieldBase::getFvPatch + ( + dynamicCast<const facePointPatch>(this->patch()) + ), + ptf.driver_ + ) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +void Foam::exprValuePointPatchField<Type>::updateCoeffs() +{ + if (debug) + { + InfoInFunction + << "Value: " << this->valueExpr_ << nl + << "Variables: "; + driver_.writeVariableStrings(Info) << endl; + } + + if (this->updated()) + { + return; + } + + // Expression evaluation + { + driver_.clearVariables(); + + if (this->valueExpr_.empty()) + { + (*this) == Zero; + } + else + { + Field<Type>::operator= + ( + driver_.evaluate<Type>(this->valueExpr_, true) + ); + } + } + + valuePointPatchField<Type>::updateCoeffs(); +} + + +template<class Type> +void Foam::exprValuePointPatchField<Type>::write(Ostream& os) const +{ + valuePointPatchField<Type>::write(os); + expressions::patchExprFieldBase::write(os); + + this->writeEntry("value",os); + + // driver_.writeCommon(os,this->debug_ || debug); +} + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchField.H b/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchField.H new file mode 100644 index 0000000000000000000000000000000000000000..3844e0cf54be92930e3821506e7881bf73e7fcfc --- /dev/null +++ b/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchField.H @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Original code Copyright (C) 2010-2018 Bernhard Gschaider + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::exprValuePointPatchField + +Description + A fixed value point boundary condition with expressions. + +Usage + \table + Property | Description | Required | Default + value | fixed value | yes | + valueExpr | expression for fixed value | yes | + \endtable + +SourceFiles + exprValuePointPatchField.C + +\*---------------------------------------------------------------------------*/ + +#ifndef exprValuePointPatchField_H +#define exprValuePointPatchField_H + +#include "valuePointPatchField.H" +#include "patchExprFieldBase.H" +#include "patchExprDriver.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class exprValuePointPatchField Declaration +\*---------------------------------------------------------------------------*/ + +template<class Type> +class exprValuePointPatchField +: + public valuePointPatchField<Type>, + public expressions::patchExprFieldBase +{ +protected: + + // Protected Data + + //- The expression driver + expressions::patchExpr::parseDriver driver_; + + +public: + + //- Runtime type information + TypeName("exprValue"); + + + // Constructors + + //- Construct from patch and internal field + exprValuePointPatchField + ( + const pointPatch&, + const DimensionedField<Type, pointMesh>& + ); + + //- Construct from patch, internal field and dictionary + exprValuePointPatchField + ( + const pointPatch&, + const DimensionedField<Type, pointMesh>&, + const dictionary& + ); + + //- Construct by mapping given patchField<Type> onto a new patch + exprValuePointPatchField + ( + const exprValuePointPatchField<Type>&, + const pointPatch&, + const DimensionedField<Type, pointMesh>&, + const pointPatchFieldMapper& + ); + + //- Construct as copy setting internal field reference + exprValuePointPatchField + ( + const exprValuePointPatchField<Type>&, + const DimensionedField<Type, pointMesh>& + ); + + //- Construct as copy + exprValuePointPatchField + ( + const exprValuePointPatchField<Type>& + ); + + + //- Construct and return a clone + virtual autoPtr<pointPatchField<Type> > clone() const + { + return autoPtr<pointPatchField<Type>> + ( + new exprValuePointPatchField<Type> + ( + *this + ) + ); + } + + + //- Construct and return a clone setting internal field reference + virtual autoPtr<pointPatchField<Type>> clone + ( + const DimensionedField<Type, pointMesh>& iF + ) const + { + return autoPtr<pointPatchField<Type>> + ( + new exprValuePointPatchField<Type> + ( + *this, + iF + ) + ); + } + + + // Member Functions + + //- Update the patch field + virtual void updateCoeffs(); + + //- Write + virtual void write(Ostream& os) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#ifdef NoRepository +# include "exprValuePointPatchField.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchFields.C b/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchFields.C new file mode 100644 index 0000000000000000000000000000000000000000..e9cca570dd01603e881dfa283d9a1cefcc7c66ea --- /dev/null +++ b/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchFields.C @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "exprValuePointPatchFields.H" +#include "pointPatchFields.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +makePointPatchFields(exprValue); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchFields.H b/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchFields.H new file mode 100644 index 0000000000000000000000000000000000000000..b0035fcac80d18a491fbef43037df5849c3d439d --- /dev/null +++ b/src/finiteVolume/expressions/fields/pointPatchFields/exprValuePointPatchFields.H @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#ifndef exprValuePointPatchFields_H +#define exprValuePointPatchFields_H + +#include "exprValuePointPatchField.H" +#include "fieldTypes.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +makePointPatchFieldTypedefs(exprValue); + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/createCode b/src/finiteVolume/expressions/patch/createCode new file mode 100755 index 0000000000000000000000000000000000000000..3aab7655b89ed0cd452a64bb15b3b7e0b0c43f4c --- /dev/null +++ b/src/finiteVolume/expressions/patch/createCode @@ -0,0 +1,13 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +# Manually create ragel scanner and lemon parser header + +prefix=patchExpr + +"${WM_PROJECT_DIR:?}/wmake/scripts/makeParser" \ + -prefix="$prefix" \ + -scanner=Scanner.rl \ + -parser=LemonParser.lyy-m4 \ + "$@" + +#------------------------------------------------------------------------------ diff --git a/src/finiteVolume/expressions/patch/patchExpr.C b/src/finiteVolume/expressions/patch/patchExpr.C new file mode 100644 index 0000000000000000000000000000000000000000..e5a4c54ccc5390dac7ddc5ab63eb8fa1ecfefa99 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExpr.C @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "patchExprFwd.H" +#include "defineDebugSwitch.H" + +// * * * * * * * * * * * * * * * * Globals * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ + +defineDebugSwitchWithName(patchExpr, "patchExpr", 0); +registerDebugSwitchWithName(patchExpr, patchExpr, "patchExpr"); + +} // End namespace expressions +} // End namespace Foam + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprDriver.C b/src/finiteVolume/expressions/patch/patchExprDriver.C new file mode 100644 index 0000000000000000000000000000000000000000..5f22efe3e0dec4ec842c3992fb2bda09424560f8 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprDriver.C @@ -0,0 +1,188 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "patchExprDriver.H" +#include "patchExprScanner.H" +#include "error.H" +#include "fvPatch.H" +#include "fvMesh.H" +#include "className.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ +namespace patchExpr +{ + +defineTypeNameAndDebug(parseDriver, 0); + +addNamedToRunTimeSelectionTable +( + fvExprDriver, + parseDriver, + dictionary, + patch +); + +addNamedToRunTimeSelectionTable +( + fvExprDriver, + parseDriver, + idName, + patch +); + +} // End namespace patchExpr +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + static label getPatchID(const fvMesh& mesh, const word& patchName) + { + const auto& bMesh = mesh.boundaryMesh(); + + const label patchId = bMesh.findPatchID(patchName); + + if (patchId < 0) + { + FatalErrorInFunction + << "No patch " << patchName << " found in " + << flatOutput(bMesh.names()) << nl + << exit(FatalError); + } + return patchId; + } + + + static inline const fvPatch& findFvPatch + ( + const fvMesh& mesh, + const word& patchName + ) + { + return mesh.boundary()[getPatchID(mesh, patchName)]; + } + +} // End namespace Foam + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +const Foam::fvPatch& Foam::expressions::patchExpr::parseDriver::getFvPatch +( + const fvMesh& fvm, + const dictionary& dict +) +{ + return findFvPatch + ( + regionMesh(dict, fvm, true), + dict.get<word>("patch") + ); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::patchExpr::parseDriver::parseDriver(const fvPatch& p) +: + parsing::genericRagelLemonDriver(), + expressions::fvExprDriver(), + patch_(p) +{} + + +Foam::expressions::patchExpr::parseDriver::parseDriver +( + const fvPatch& p, + const dictionary& dict +) +: + parsing::genericRagelLemonDriver(), + expressions::fvExprDriver(dict), + patch_(p) +{} + + +Foam::expressions::patchExpr::parseDriver::parseDriver +( + const fvPatch& p, + const parseDriver& driver_ +) +: + parsing::genericRagelLemonDriver(), + expressions::fvExprDriver(driver_), + patch_(p) +{} + + +Foam::expressions::patchExpr::parseDriver::parseDriver +( + const word& patchName, + const fvMesh& mesh +) +: + parseDriver(findFvPatch(mesh, patchName)) +{} + + +Foam::expressions::patchExpr::parseDriver::parseDriver +( + const dictionary& dict, + const fvMesh& mesh +) +: + parseDriver(getFvPatch(mesh, dict), dict) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +unsigned Foam::expressions::patchExpr::parseDriver::parse +( + const std::string& expr, + size_t pos, + size_t len +) +{ + scanner scan(this->debugScanner()); + + scan.process(expr, pos, len, *this); + + return 0; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprDriver.H b/src/finiteVolume/expressions/patch/patchExprDriver.H new file mode 100644 index 0000000000000000000000000000000000000000..294c902cf41ab8e90cb31f3d5c698a2468797697 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprDriver.H @@ -0,0 +1,305 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::patchExpr::parseDriver + +Description + Driver for patch expressions + + In addition to the standard mathematical functions, operations and + logical and relational operations, the volume expression support the + following driver-specific functions: + + Functions + \table + Function | Description | Number of arguments | + vol | The cell volumes | 0 | + pos | The face centres | 0 | + pts | The face points | 0 | + area | The face area magnitudes | 0 | + weightAverage| Area weighted average | 1 | + weightSum | Area weighted sum | 1 | + face | The face areaNormal vectors | 0 | + point | A point-field point value | 1 | + faceToPoint | Interpolate face values onto points | 1 | + pointToFace | Interpolate point values onto faces | 1 | + rand | Random field | 0/1 | + \endtable + +SourceFiles + patchExprDriver.C + patchExprDriverFields.C + patchExprDriverTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_patchExprDriver_H +#define expressions_patchExprDriver_H + +#include "patchExprFwd.H" +#include "fvExprDriver.H" +#include "Enum.H" +#include "volFields.H" +#include "surfaceFields.H" +#include "pointFields.H" +#include "genericRagelLemonDriver.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ +namespace patchExpr +{ + +/*---------------------------------------------------------------------------*\ + Class parseDriver Declaration +\*---------------------------------------------------------------------------*/ + +class parseDriver +: + public parsing::genericRagelLemonDriver, + public expressions::fvExprDriver +{ + // Private Member Functions + + static const fvPatch& getFvPatch + ( + const fvMesh& fvm, + const dictionary& dict + ); + + +protected: + + // Protected Data + + //- The referenced patch + const fvPatch& patch_; + + + // Protected Member Functions + + // No copy copy construct + parseDriver(const parseDriver&) = delete; + + // No copy assignment + void operator=(const parseDriver&) = delete; + + +public: + + ClassName("patchExpr::driver"); + + // Constructors + + //- Construct for specified patch + explicit parseDriver(const fvPatch& p); + + //- Construct for specified patch with given dictionary + parseDriver(const fvPatch& p, const dictionary& dict); + + //- Construct for specified patch with copy of driver context + parseDriver(const fvPatch& p, const parseDriver& driver_); + + //- Construct with patchName for the given mesh + parseDriver(const word& patchName, const fvMesh& mesh); + + //- Construct with "patch" (mandatory) and "region" (optional) + //- specified in dictionary + parseDriver(const dictionary& dict, const fvMesh& mesh); + + //- Clone + virtual autoPtr<expressions::fvExprDriver> clone() const + { + return autoPtr<expressions::fvExprDriver> + ( + new parseDriver(this->patch_, *this) + ); + } + + + //- Destructor + virtual ~parseDriver() = default; + + + // Public Member Functions + + //- The mesh we are attached to + virtual const fvMesh& mesh() const + { + return patch_.boundaryMesh().mesh(); + } + + //- The underlying field size for the expression + virtual label size() const + { + return patch_.patch().size(); + } + + //- The underlying point field size for the expression + virtual label pointSize() const + { + return patch_.patch().nPoints(); + } + + //- Field size associated with different geometric field types + inline label size(const FieldAssociation geoType) const; + + + // Evaluation + + //- Perform parsing on (sub) string + using genericRagelLemonDriver::content; + + //- Execute the parser + virtual unsigned parse + ( + const std::string& expr, + size_t pos = 0, + size_t len = std::string::npos + ); + + + // Field Information + + // Fields + + //- Set result + template<class Type> + void setResult(Field<Type>* ptr, bool pointVal = false) + { + result().setResult<Type>(ptr, pointVal); + } + + + //- Retrieve variable as field if possible. + // Test tmp for validity to determine success of the operation. + template<class Type> + tmp<Field<Type>> getVariableIfAvailable(const word& fldName) const; + + //- Retrieve field (vol field) + template<class Type> + tmp<Field<Type>> + getVolField(const word& fldName); + + //- Retrieve field (surface field) + template<class Type> + tmp<Field<Type>> + getSurfaceField(const word& fldName); + + //- Retrieve field (point field) + template<class Type> + tmp<Field<Type>> + getPointField(const word& fldName); + + //- Return named field + template<class Type> + tmp<Field<Type>> getField(const word& fldName); + + + // Field "shape" conversions + + //- Interpolate face to point + template<class Type> + tmp<Field<Type>> faceToPoint(const Field<Type>& field) const; + + //- Interpolate point to face values + template<class Type> + tmp<Field<Type>> pointToFace(const Field<Type>& field) const; + + + // Custom Field Functions + + //- The area-weighted average of a field + template<class Type> + Type areaAverage(const Field<Type>& fld) const + { + return weightedAverage(patch_.magSf(), fld); + } + + //- The area-weighted sum of a field + template<class Type> + Type areaSum(const Field<Type>& fld) const + { + return weightedSum(patch_.magSf(), fld); + } + + //- The face area magnitudes [magSf] - (swak = area) + tmp<scalarField> field_faceArea() const; + + //- The face centres - (swak = pos) + tmp<vectorField> field_faceCentre() const; + + //- The face areas with their vector direction [Sf] - (swak = face) + tmp<vectorField> field_areaNormal() const; + + //- The patch point locations - (swak = pts) + tmp<vectorField> field_pointField() const; + + //- A uniform random field + tmp<scalarField> field_rand(label seed=0, bool gaussian=false) const; + + //- A Gaussian random field + tmp<scalarField> field_randGaussian(label seed=0) const + { + return field_rand(seed, true); + } +}; + + +// Template specializations + +//- Retrieve field (surface field: bool) +template<> +tmp<Field<bool>> parseDriver::getSurfaceField<bool>(const word& fldName); + +//- Retrieve field (point field: bool) +template<> +tmp<Field<bool>> parseDriver::getPointField<bool>(const word& fldName); + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace patchExpr +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "patchExprDriverI.H" + +#ifdef NoRepository + #include "patchExprDriverTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprDriverFields.C b/src/finiteVolume/expressions/patch/patchExprDriverFields.C new file mode 100644 index 0000000000000000000000000000000000000000..690a4c2376170a5471a645f7f6ac7a46ad43503f --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprDriverFields.C @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "patchExprDriver.H" +#include "fvPatch.H" +#include "error.H" + +// * * * * * * * * * * * * Template Specializations * * * * * * * * * * * * // + +template<> +Foam::tmp<Foam::Field<bool>> +Foam::expressions::patchExpr::parseDriver::getSurfaceField<bool> +( + const word& name +) +{ + return getVariable<bool>(name, this->size()); +} + + +template<> +Foam::tmp<Foam::Field<bool>> +Foam::expressions::patchExpr::parseDriver::getPointField<bool> +( + const word& name +) +{ + return getVariable<bool>(name, this->pointSize()); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::tmp<Foam::scalarField> +Foam::expressions::patchExpr::parseDriver::field_faceArea() const +{ + return patch_.magSf(); +} + + +Foam::tmp<Foam::vectorField> +Foam::expressions::patchExpr::parseDriver::field_faceCentre() const +{ + return patch_.Cf(); +} + + +Foam::tmp<Foam::vectorField> +Foam::expressions::patchExpr::parseDriver::field_areaNormal() const +{ + return patch_.Sf(); +} + + +Foam::tmp<Foam::vectorField> +Foam::expressions::patchExpr::parseDriver::field_pointField() const +{ + return patch_.patch().localPoints(); +} + + +Foam::tmp<Foam::scalarField> +Foam::expressions::patchExpr::parseDriver::field_rand +( + label seed, + bool gaussian +) const +{ + auto tresult = tmp<scalarField>::New(this->size()); + fill_random(tresult.ref(), seed, gaussian); + + return tresult; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprDriverI.H b/src/finiteVolume/expressions/patch/patchExprDriverI.H new file mode 100644 index 0000000000000000000000000000000000000000..b4ae95c4ea0162912e1eea94275b249383d301ce --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprDriverI.H @@ -0,0 +1,50 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline Foam::label Foam::expressions::patchExpr::parseDriver::size +( + const FieldAssociation geoType +) const +{ + switch (geoType) + { + case FieldAssociation::POINT_DATA : + return patch_.patch().nPoints(); + break; + case FieldAssociation::SURFACE_DATA : + return patch_.patch().size(); + break; + default: + break; + } + return 0; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C b/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..7fafffbc50361f3f4da81b646492776c47741e90 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C @@ -0,0 +1,228 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "primitivePatchInterpolation.H" + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template<class Type> +Foam::tmp<Foam::Field<Type>> +Foam::expressions::patchExpr::parseDriver::getVariableIfAvailable +( + const word& name +) const +{ + bool isPointVal = false; + bool isUniformVal = false; + + tmp<Field<Type>> tfield; + + if (hasVariable(name) && variable(name).isType<Type>()) + { + const expressions::exprResult& var = variable(name); + + isPointVal = var.isPointValue(); + isUniformVal = var.isUniform(); + + tfield = var.cref<Type>().clone(); + } + else if (isGlobalVariable<Type>(name, false)) + { + const expressions::exprResult& var = lookupGlobal(name); + + isUniformVal = var.isUniform(); + + tfield = var.cref<Type>().clone(); + } + + if (tfield.valid()) + { + const label fldLen = tfield().size(); + const label len = (isPointVal ? this->pointSize() : this->size()); + + if (returnReduce((fldLen == len), andOp<bool>())) + { + return tfield; + } + + if (!isUniformVal) + { + WarningInFunction + << "Variable " << name + << " does not fit the size and is not a uniform value." << nl + << "Using average value" << endl; + } + + return tmp<Field<Type>>::New(this->size(), gAverage(tfield)); + } + + return tfield; +} + + +template<class Type> +Foam::tmp<Foam::Field<Type>> +Foam::expressions::patchExpr::parseDriver::getVolField(const word& name) +{ + return getField<Type>(name); +} + + +template<class Type> +Foam::tmp<Foam::Field<Type>> +Foam::expressions::patchExpr::parseDriver::getSurfaceField(const word& name) +{ + return getField<Type>(name); +} + + +template<class Type> +Foam::tmp<Foam::Field<Type>> +Foam::expressions::patchExpr::parseDriver::getPointField(const word& name) +{ + return getField<Type>(name); +} + + +template<class Type> +Foam::tmp<Foam::Field<Type>> +Foam::expressions::patchExpr::parseDriver::getField(const word& name) +{ + tmp<Field<Type>> tfield = getVariableIfAvailable<Type>(name); + + if (tfield.valid()) + { + return tfield; + } + + + typedef GeometricField<Type, fvPatchField, volMesh> vfieldType; + typedef GeometricField<Type, fvsPatchField, surfaceMesh> sfieldType; + typedef GeometricField<Type, pointPatchField, pointMesh> pfieldType; + + const objectRegistry& obr = this->mesh().thisDb(); + + const vfieldType* vfield = obr.findObject<vfieldType>(name); + const sfieldType* sfield = obr.findObject<sfieldType>(name); + const pfieldType* pfield = obr.findObject<pfieldType>(name); + + // Local, temporary storage + tmp<vfieldType> t_vfield; + tmp<sfieldType> t_sfield; + tmp<pfieldType> t_pfield; + + if (searchFiles() && !vfield && !sfield && !pfield) + { + const word fldType = this->getTypeOfField(name); + + if (fldType == vfieldType::typeName) + { + t_vfield = this->readAndRegister<vfieldType>(name, mesh()); + vfield = t_vfield.get(); + } + else if (fldType == sfieldType::typeName) + { + t_sfield = this->readAndRegister<sfieldType>(name, mesh()); + sfield = t_sfield.get(); + } + else if (fldType == pfieldType::typeName) + { + t_pfield = this->readAndRegister<pfieldType> + ( + name, + pointMesh::New(mesh()) + ); + pfield = t_pfield.get(); + } + } + + const label patchIndex = patch_.index(); + + if (vfield) + { + return tmp<Field<Type>>::New + ( + vfield->boundaryField()[patchIndex] + ); + } + + if (sfield) + { + return tmp<Field<Type>>::New + ( + sfield->boundaryField()[patchIndex] + ); + } + + if (pfield) + { + return pfield->boundaryField()[patchIndex].patchInternalField(); + } + + + FatalErrorInFunction + << "No field '" << name << "' of type " + << pTraits<Type>::typeName << nl << nl + << vfieldType::typeName << " Fields: " + << flatOutput(obr.sortedNames<vfieldType>()) << nl + << sfieldType::typeName << " Fields: " + << flatOutput(obr.sortedNames<sfieldType>()) << nl + << pfieldType::typeName << " Fields: " + << flatOutput(obr.sortedNames<pfieldType>()) << nl + << exit(FatalError); + + return tmp<Field<Type>>::New(); +} + + +template<class Type> +Foam::tmp<Foam::Field<Type>> +Foam::expressions::patchExpr::parseDriver::faceToPoint +( + const Field<Type>& field +) const +{ + primitivePatchInterpolation interp(patch_.patch()); + + return interp.pointToFaceInterpolate(field); +} + + +template<class Type> +Foam::tmp<Foam::Field<Type>> +Foam::expressions::patchExpr::parseDriver::pointToFace +( + const Field<Type>& field +) const +{ + primitivePatchInterpolation interp(patch_.patch()); + + return interp.faceToPointInterpolate(field); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprFwd.H b/src/finiteVolume/expressions/patch/patchExprFwd.H new file mode 100644 index 0000000000000000000000000000000000000000..5682b896fbf6286a68bb8cb68f845ac174d283b1 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprFwd.H @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Namespace + Foam::expressions::patchExpr + +Description + Namespace for patch expressions parsing and evaluation + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_patchExprFwd_H +#define expressions_patchExprFwd_H + +namespace Foam +{ +namespace expressions +{ +namespace patchExpr +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Forward Declarations +class parser; +class scanner; +class parseDriver; +union scanToken; + +//- Static debugging option +extern int debug; + + +//- The field association for patch expressions (mutually exclusive) +enum FieldAssociation : unsigned char +{ + NO_DATA = 0, //!< No data + POINT_DATA = 1, //!< Point data + SURFACE_DATA = 2 //!< Surface data +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace patchExpr + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- Typedef for patchExpr parseDriver +typedef patchExpr::parseDriver patchExprDriver; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprLemonParser.h b/src/finiteVolume/expressions/patch/patchExprLemonParser.h new file mode 100644 index 0000000000000000000000000000000000000000..8a84326c4dd20a35dbfb0ef4cbf29d37b1eb8a67 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprLemonParser.h @@ -0,0 +1,110 @@ +#define TOK_QUESTION 1 +#define TOK_COLON 2 +#define TOK_LOR 3 +#define TOK_LAND 4 +#define TOK_BIT_XOR 5 +#define TOK_BIT_AND 6 +#define TOK_EQUAL 7 +#define TOK_NOT_EQUAL 8 +#define TOK_LESS_EQ 9 +#define TOK_GREATER_EQ 10 +#define TOK_LESS 11 +#define TOK_GREATER 12 +#define TOK_PLUS 13 +#define TOK_MINUS 14 +#define TOK_TIMES 15 +#define TOK_DIVIDE 16 +#define TOK_PERCENT 17 +#define TOK_NEGATE 18 +#define TOK_NOT 19 +#define TOK_DOT 20 +#define TOK_NUMBER 21 +#define TOK_ZERO 22 +#define TOK_PI 23 +#define TOK_LPAREN 24 +#define TOK_RPAREN 25 +#define TOK_DEG_TO_RAD 26 +#define TOK_RAD_TO_DEG 27 +#define TOK_TIME 28 +#define TOK_SCALAR_ID 29 +#define TOK_SSCALAR_ID 30 +#define TOK_MIN 31 +#define TOK_COMMA 32 +#define TOK_MAX 33 +#define TOK_SUM 34 +#define TOK_AVERAGE 35 +#define TOK_EXP 36 +#define TOK_LOG 37 +#define TOK_LOG10 38 +#define TOK_SQR 39 +#define TOK_SQRT 40 +#define TOK_CBRT 41 +#define TOK_SIN 42 +#define TOK_COS 43 +#define TOK_TAN 44 +#define TOK_ASIN 45 +#define TOK_ACOS 46 +#define TOK_ATAN 47 +#define TOK_SINH 48 +#define TOK_COSH 49 +#define TOK_TANH 50 +#define TOK_POW 51 +#define TOK_ATAN2 52 +#define TOK_POS 53 +#define TOK_NEG 54 +#define TOK_POS0 55 +#define TOK_NEG0 56 +#define TOK_SIGN 57 +#define TOK_FLOOR 58 +#define TOK_CEIL 59 +#define TOK_ROUND 60 +#define TOK_HYPOT 61 +#define TOK_RAND 62 +#define TOK_VECTOR_ID 63 +#define TOK_SVECTOR_ID 64 +#define TOK_SPH_TENSOR_ID 65 +#define TOK_SSPH_TENSOR_ID 66 +#define TOK_SYM_TENSOR_ID 67 +#define TOK_SSYM_TENSOR_ID 68 +#define TOK_UNIT_TENSOR 69 +#define TOK_TENSOR_ID 70 +#define TOK_STENSOR_ID 71 +#define TOK_LTRUE 72 +#define TOK_LFALSE 73 +#define TOK_BOOL 74 +#define TOK_SBOOL_ID 75 +#define TOK_FACE_AREA 76 +#define TOK_FACE_EXPR 77 +#define TOK_WEIGHT_AVERAGE 78 +#define TOK_WEIGHT_SUM 79 +#define TOK_POINT_EXPR 80 +#define TOK_PSCALAR_ID 81 +#define TOK_PVECTOR_ID 82 +#define TOK_PSPH_TENSOR_ID 83 +#define TOK_PSYM_TENSOR_ID 84 +#define TOK_PTENSOR_ID 85 +#define TOK_PBOOL_ID 86 +#define TOK_POINTS 87 +#define TOK_MAG 88 +#define TOK_MAGSQR 89 +#define TOK_VECTOR 90 +#define TOK_TENSOR 91 +#define TOK_SYM_TENSOR 92 +#define TOK_SPH_TENSOR 93 +#define TOK_CMPT_X 94 +#define TOK_CMPT_Y 95 +#define TOK_CMPT_Z 96 +#define TOK_CMPT_XX 97 +#define TOK_CMPT_XY 98 +#define TOK_CMPT_XZ 99 +#define TOK_CMPT_YX 100 +#define TOK_CMPT_YY 101 +#define TOK_CMPT_YZ 102 +#define TOK_CMPT_ZX 103 +#define TOK_CMPT_ZY 104 +#define TOK_CMPT_ZZ 105 +#define TOK_CMPT_II 106 +#define TOK_TRANSPOSE 107 +#define TOK_DIAG 108 +#define TOK_POINT_TO_FACE 109 +#define TOK_FACE_TO_POINT 110 diff --git a/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4 b/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4 new file mode 100644 index 0000000000000000000000000000000000000000..477cc7ea463aff567511c1f85e68a014c6d50eba --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4 @@ -0,0 +1,565 @@ +%include +{ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Lemon grammar for patch expressions. + + https://www.sqlite.org/src/doc/trunk/doc/lemon.html + + See detailed notes in the field expression parser. + +\*---------------------------------------------------------------------------*/ +} // %include + +/* + * include[patchExprLemonParserMacros.m4] + *include(`patchExprLemonParserMacros.m4')dnl + !done in a comment since many editors have issues matching m4 quotes! + */ +%include +{ +#include "patchExprDriver.H" +#include "patchExprParser.H" +#include "patchExprScanner.H" +#include "unitConversion.H" +#include "error.H" +#include "volFields.H" +#include "exprOps.H" +#include "exprDriverOps.H" +#include "GeometricFieldOps.H" + +// Enable ParseTrace +#undef NDEBUG + +compiler_pragmas() + +// Local Functions + +tmp_management() + +} // %include + +// ------------------------------------------------------------------------- // + +%namespace {} + +// Use extra argument for the return value +%extra_context { Foam::expressions::patchExpr::parseDriver* driver } +%parse_failure { driver->reportFatal("Parse failure, giving up..."); } +%syntax_error { driver->reportFatal("Syntax error"); } + +%token_prefix TOK_ + +// Terminals +%token_type {Foam::expressions::patchExpr::scanToken*} +// Non-terminals +%type ivalue { Foam::label } +%type svalue { Foam::scalar } +%type ident { Foam::word* } + +// Face fields +declare_field(lfield, Foam::boolField, bool, newField, getSurfaceField) +declare_field(sfield, Foam::scalarField, Foam::scalar, newField, getField) +declare_field(vfield, Foam::vectorField, Foam::vector, newField, getField) +declare_field(hfield, Foam::sphericalTensorField, Foam::sphericalTensor, newField, getField) +declare_field(yfield, Foam::symmTensorField, Foam::symmTensor, newField, getField) +declare_field(tfield, Foam::tensorField, Foam::tensor, newField, getField) + +// Point fields +declare_field(plfield, Foam::boolField, bool, newPointField, getPointField) +declare_field(psfield, Foam::scalarField, Foam::scalar, newPointField, getPointField) +declare_field(pvfield, Foam::vectorField, Foam::vector, newPointField, getPointField) +declare_field(phfield, Foam::sphericalTensorField, Foam::sphericalTensor, newPointField, getPointField) +declare_field(pyfield, Foam::symmTensorField, Foam::symmTensor, newPointField, getPointField) +declare_field(ptfield, Foam::tensorField, Foam::tensor, newPointField, getPointField) + + +// For each rule action with code, destruction must be done by that code block +// Lemon does not generate a destructor for that. +// So do not use Lemon destructors for anything. + +operator_precedence() + +%start_symbol evaluate + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +/*---------------------------------------------------------------------------*\ + * Productions (scalar) +\*---------------------------------------------------------------------------*/ + +svalue (lhs) ::= NUMBER (a) . { lhs = (a)->svalue; } // From scanToken +svalue (lhs) ::= ZERO . { lhs = Foam::Zero; } +svalue (lhs) ::= PI LPAREN RPAREN . { lhs = Foam::constant::mathematical::pi; } +svalue (lhs) ::= DEG_TO_RAD LPAREN RPAREN . { lhs = Foam::degToRad(); } +svalue (lhs) ::= RAD_TO_DEG LPAREN RPAREN . { lhs = Foam::radToDeg(); } +svalue (lhs) ::= TIME LPAREN RPAREN . { lhs = driver->timeValue(); } + + +/* * * * * * * * * * * * * * * * * Face Fields * * * * * * * * * * * * * * * *\ +dnl +define([_logic_], [lfield])dnl +define([_scalar_], [sfield])dnl +define([_vector_], [vfield])dnl +define([_sphTensor_], [hfield])dnl +define([_symTensor_], [yfield])dnl +define([_tensor_], [tfield])dnl +dnl +\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*---------------------------------------------------------------------------*\ + * Productions (scalarField) +dnl +define([_target_], [sfield])dnl +define([_value_type_], [Foam::scalar])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_field_from_value(_target_, svalue) +rule_get_field(_target_, SCALAR_ID) +rule_get_field(_target_, SSCALAR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_scalar_operations() +rules_scalar_functions() + +// Non-standard but manage via FieldOps::assign +rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<Foam::scalar>()) +rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<Foam::scalar>()) +rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<Foam::scalar>()) + +// Non-standard but works directly for scalarField +rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot) + + +// Other functions + +_target_ (lhs) ::= RAND LPAREN RPAREN. +{ + lhs = driver->field_rand().ptr(); +} + +_target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN. +{ + // Call with -ve seed to signal use of time index as seed + lhs = driver->field_rand(std::round(-(seed)->svalue)).ptr(); +} + + +/*---------------------------------------------------------------------------*\ + * Productions (vectorField) +dnl +define([_target_], [vfield])dnl +define([_value_type_], [Foam::vector])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, VECTOR_ID) +rule_get_field(_target_, SVECTOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_vector_operations() +rules_vector_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (sphericalTensorField) +dnl +define([_target_], [hfield])dnl +define([_value_type_], [Foam::sphericalTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, SPH_TENSOR_ID) +rule_get_field(_target_, SSPH_TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_sphTensor_operations() +rules_sphTensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (symmTensorField) +dnl +define([_target_], [yfield])dnl +define([_value_type_], [Foam::symmTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, SYM_TENSOR_ID) +rule_get_field(_target_, SSYM_TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_symTensor_operations() +rules_symTensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (tensorField) +dnl +define([_target_], [tfield])dnl +define([_value_type_], [Foam::tensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } +tfield (lhs) ::= UNIT_TENSOR . { lhs = _new_tfield(Foam::tensor::I); } + +rule_get_field(_target_, TENSOR_ID) +rule_get_field(_target_, STENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_tensor_operations() +rules_tensor_functions() + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +/*---------------------------------------------------------------------------*\ + * Logic field productions (boolField) +dnl +define([_target_], [lfield])dnl +define([_value_type_], [bool])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } +_logic_ (lhs) ::= LTRUE . { lhs = _new_lfield(_logic_true_); } +_logic_ (lhs) ::= LFALSE . { lhs = _new_lfield(_logic_false_); } + +rule_cast_logical(_target_, _target_) +rule_cast_logical(_target_, _scalar_, Foam::scalar) + +dnl/* Handling of named logic fields not really tested (disable in scanner) */ +rule_get_field(_target_, SBOOL_ID) +rules_logical_operations(_logic_, _value_type_) + + +/*---------------------------------------------------------------------------*\ + * General Surface-related productions +\*---------------------------------------------------------------------------*/ + +rules_driver_surface_functions() + + +/* * * * * * * * * * * * * * * * Point Fields * * * * * * * * * * * * * * * *\ +dnl +define([_logic_], [plfield])dnl +define([_scalar_], [psfield])dnl +define([_vector_], [pvfield])dnl +define([_sphTensor_], [phfield])dnl +define([_symTensor_], [pyfield])dnl +define([_tensor_], [ptfield])dnl +dnl +\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + + +/*---------------------------------------------------------------------------*\ + * Productions (point scalarField) +dnl +define([_target_], [psfield])dnl +define([_value_type_], [Foam::scalar])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ } + +rule_field_from_value(_target_, svalue, POINT_EXPR) +rule_get_field(_target_, PSCALAR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_scalar_operations() +rules_scalar_functions() + +// Non-standard but manage via FieldOps::assign +rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp<Foam::scalar>()) +rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp<Foam::scalar>()) +rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp<Foam::scalar>()) + +// Non-standard but works directly for scalarField +rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot) + + +/*---------------------------------------------------------------------------*\ + * Productions (point vectorField) +dnl +define([_target_], [pvfield])dnl +define([_value_type_], [Foam::vector])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ } + +rule_get_field(_target_, PVECTOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_vector_operations() +rules_vector_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (point sphericalTensorField) +dnl +define([_target_], [phfield])dnl +define([_value_type_], [Foam::sphericalTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ } + +rule_get_field(_target_, PSPH_TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_sphTensor_operations() +rules_sphTensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (point symmTensorField) +dnl +define([_target_], [pyfield])dnl +define([_value_type_], [Foam::symmTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ } + +rule_get_field(_target_, PSYM_TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_symTensor_operations() +rules_symTensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (point tensorField) +dnl +define([_target_], [ptfield])dnl +define([_value_type_], [Foam::tensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ } + +rule_get_field(_target_, PTENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_tensor_operations() +rules_tensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Logic field productions (point boolField) +dnl +define([_target_], [plfield])dnl +define([_value_type_], [bool])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ } +_logic_ (lhs) ::= POINT_EXPR LPAREN LTRUE RPAREN . { lhs = _new_plfield(_logic_true_); } +_logic_ (lhs) ::= POINT_EXPR LPAREN LFALSE RPAREN . { lhs = _new_plfield(_logic_false_); } + +rule_cast_logical(_target_, _target_) +rule_cast_logical(_target_, _scalar_, Foam::scalar) + +dnl/* Handling of named logic fields not really tested (disable in scanner) */ +rule_get_field(_target_, PBOOL_ID) +rules_logical_operations(_logic_, _value_type_) + + +/*---------------------------------------------------------------------------*\ + * General Point-related productions +\*---------------------------------------------------------------------------*/ + +rules_driver_point_functions() + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +/*---------------------------------------------------------------------------*\ + * Face field composition +\*---------------------------------------------------------------------------*/ + +rule_mag_logical(sfield, lfield) +rules_mag_functions(sfield, sfield) +rules_mag_functions(sfield, vfield) +rules_mag_functions(sfield, tfield) +rules_mag_functions(sfield, yfield) +rules_mag_functions(sfield, hfield) + +rule_vector_zip(vfield, sfield, VECTOR) +rule_tensor_zip(tfield, sfield, TENSOR) +rule_symTensor_zip(yfield, sfield, SYM_TENSOR) +rule_sphTensor_zip(hfield, sfield, SPH_TENSOR) + +rule_vector_components(sfield, vfield) +rule_tensor_components(sfield, tfield) +rule_symTensor_components(sfield, yfield) +rule_sphTensor_components(sfield, hfield) + +rule_tensor_transpose(tfield) +rule_symTensor_transpose(yfield) +rule_sphTensor_transpose(hfield) + +rule_tensor_unzipDiag(vfield, yfield) +rule_tensor_unzipAll(vfield, tfield) + +rule_pointToFace(sfield, psfield) +rule_pointToFace(vfield, pvfield) +rule_pointToFace(tfield, ptfield) +rule_pointToFace(yfield, pyfield) +rule_pointToFace(hfield, phfield) + + +/*---------------------------------------------------------------------------*\ + * Point field composition +\*---------------------------------------------------------------------------*/ + +rule_mag_logical(psfield, plfield) +rules_mag_functions(psfield, psfield) +rules_mag_functions(psfield, pvfield) +rules_mag_functions(psfield, ptfield) +rules_mag_functions(psfield, pyfield) +rules_mag_functions(psfield, phfield) + +rule_vector_zip(pvfield, psfield, VECTOR) +rule_tensor_zip(ptfield, psfield, TENSOR) +rule_symTensor_zip(pyfield, psfield, SYM_TENSOR) +rule_sphTensor_zip(phfield, psfield, SPH_TENSOR) + +rule_vector_components(psfield, pvfield) +rule_tensor_components(psfield, ptfield) +rule_symTensor_components(psfield, pyfield) +rule_sphTensor_components(psfield, phfield) + +rule_tensor_transpose(ptfield) +rule_symTensor_transpose(pyfield) +rule_sphTensor_transpose(phfield) + +rule_tensor_unzipDiag(pvfield, pyfield) +rule_tensor_unzipAll(pvfield, ptfield) + +rule_faceToPoint(psfield, sfield) +rule_faceToPoint(pvfield, vfield) +rule_faceToPoint(ptfield, tfield) +rule_faceToPoint(pyfield, yfield) +rule_faceToPoint(phfield, hfield) + + +// ************************************************************************* // + +dnl/* Standard m4 quoting +changequote([`],['])dnl +dnl*/ + +%code +{ + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::expressions::patchExpr::parser::stop() +{ + if (lemon_) + { + ParseFree(lemon_, ::operator delete); + #ifndef NDEBUG + ParseTrace(nullptr, nullptr); + #endif + lemon_ = nullptr; + } +} + + +void Foam::expressions::patchExpr::parser::start(parseDriver& driver_) +{ + this->stop(); + lemon_ = ParseAlloc(::operator new, &driver_); + + if (debug || driver_.debugParser()) + { + #ifndef NDEBUG + ParseTrace(stderr, const_cast<char*>(prompt_)); + #endif + } +} + + +void Foam::expressions::patchExpr::parser::parse +( + int tokenId, + scanToken* tokenVal +) +{ + Parse(lemon_, tokenId, tokenVal); +} + + +Foam::word Foam::expressions::patchExpr::parser::nameOfToken +( + int tokenId +) const +{ + #ifndef NDEBUG + if + ( + tokenId > 0 + && unsigned(tokenId) < (sizeof(yyTokenName) / sizeof(char*)) + ) + { + return yyTokenName[tokenId]; + } + return "<invalid>"; + #else + return word(); + #endif +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End of %code + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprLemonParserMacros.m4 b/src/finiteVolume/expressions/patch/patchExprLemonParserMacros.m4 new file mode 100644 index 0000000000000000000000000000000000000000..aa183dfeb63014d38a4ee3da5ca7664e2ab3a1e7 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprLemonParserMacros.m4 @@ -0,0 +1,109 @@ +divert(-1)dnl +#-----------------------------------*- m4 -*----------------------------------- +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | www.openfoam.com +# \\/ M anipulation | +#------------------------------------------------------------------------------ +# Copyright (C) 2019 OpenCFD Ltd. +#------------------------------------------------------------------------------ +# License +# This file is part of OpenFOAM, licensed under GNU General Public License +# <http://www.gnu.org/licenses/>. +# +# Description +# Driver-specific m4/lemon macros for patch expressions. +# +#------------------------------------------------------------------------------ + +include(`m4/lemon/base-setup.m4')dnl +include([m4/lemon/operator-precedence.m4])dnl +dnl +include([m4/lemon/rules-standard.m4])dnl +include([m4/lemon/rules-operations.m4])dnl +include([m4/lemon/rules-functions.m4])dnl +include([m4/lemon/rules-components.m4])dnl +include([m4/lemon/rules-fields-components.m4])dnl +include([m4/lemon/rules-scalar-logic.m4])dnl +dnl +divert(-1)dnl + +use_bool_logic()dnl # Use boolField directly + +#------------------------------------------------------------------------------- +# Driver rules +#------------------------------------------------------------------------------- + +define([rules_driver_surface_functions], +[dnl +rule_driver_nullary(_scalar_, FACE_AREA, field_faceArea)dnl +rule_driver_nullary(_vector_, POS, field_faceCentre)dnl FACE_CENTRE +rule_driver_nullary(_vector_, FACE_EXPR, field_areaNormal)dnl +dnl +rule_driver_inplace_unary(_scalar_, WEIGHT_AVERAGE, areaAverage)dnl +rule_driver_inplace_unary(_vector_, WEIGHT_AVERAGE, areaAverage)dnl +rule_driver_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, areaAverage)dnl +rule_driver_inplace_unary(_symTensor_, WEIGHT_AVERAGE, areaAverage)dnl +rule_driver_inplace_unary(_tensor_, WEIGHT_AVERAGE, areaAverage)dnl +dnl +rule_driver_inplace_unary(_scalar_, WEIGHT_SUM, areaSum)dnl +rule_driver_inplace_unary(_vector_, WEIGHT_SUM, areaSum)dnl +rule_driver_inplace_unary(_sphTensor_, WEIGHT_SUM, areaSum)dnl +rule_driver_inplace_unary(_symTensor_, WEIGHT_SUM, areaSum)dnl +rule_driver_inplace_unary(_tensor_, WEIGHT_SUM, areaSum)dnl +dnl +]) + +define([rules_driver_point_functions], +[dnl +rule_driver_nullary(_vector_, POINTS, field_pointField)dnl +dnl +dnl NB use non-driver versions for points - ie, unweighted +dnl +rule_inplace_unary(_scalar_, WEIGHT_AVERAGE, Foam::gAverage)dnl +rule_inplace_unary(_vector_, WEIGHT_AVERAGE, Foam::gAverage)dnl +rule_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl +rule_inplace_unary(_symTensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl +rule_inplace_unary(_tensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl +dnl +rule_inplace_unary(_scalar_, WEIGHT_SUM, Foam::gSum)dnl +rule_inplace_unary(_vector_, WEIGHT_SUM, Foam::gSum)dnl +rule_inplace_unary(_sphTensor_, WEIGHT_SUM, Foam::gSum)dnl +rule_inplace_unary(_symTensor_, WEIGHT_SUM, Foam::gSum)dnl +rule_inplace_unary(_tensor_, WEIGHT_SUM, Foam::gSum)dnl +dnl +]) + + +#------------------------------------------------------------------------------ +# rule_faceToPoint(out, in) +# rule_pointToFace(out, in) +# +# Description +# Production rules for driver faceToPoint, pointToFace, +# methods +#------------------------------------------------------------------------------ + +define([rule_faceToPoint], +[rule_driver_unary($1, $2, FACE_TO_POINT, faceToPoint)]) + +define([rule_pointToFace], +[rule_driver_unary($1, $2, POINT_TO_FACE, pointToFace)]) + + +#------------------------------------------------------------------------------ +# Standard rules for fields: declaration, new/get, driver functions etc. + +include([m4/lemon/rules-fields.m4])dnl +divert(-1)dnl + + +#------------------------------------------------------------------------------ + +# Additional safety measures + +undefine([substr])dnl # Avoid collision with C/C++ naming + +#------------------------------------------------------------------------------ +divert(0)dnl diff --git a/src/finiteVolume/expressions/patch/patchExprParser.H b/src/finiteVolume/expressions/patch/patchExprParser.H new file mode 100644 index 0000000000000000000000000000000000000000..a59fcdcca693b4c9f99b2cbe9061dc5cac317460 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprParser.H @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::patchExpr::parser + +Description + Lemon parser interface for patch expressions grammar + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_patchExprParser_H +#define expressions_patchExprParser_H + +#include "patchExprFwd.H" + +namespace Foam +{ +namespace expressions +{ +namespace patchExpr +{ + +/*---------------------------------------------------------------------------*\ + Class parser Declaration +\*---------------------------------------------------------------------------*/ + +class parser +{ + // Private Data + + //- Prompt for parser tracing + static constexpr const char* const prompt_ = "patchExpr:"; + + //- The lemon parser (demand-driven) + void* lemon_; + + +public: + + //- Local object debugging + int debug; + + + // Constructors + + //- Construct null + parser() : lemon_(nullptr), debug(patchExpr::debug) {} + + + //- Destructor, deletes parser backend + ~parser() + { + stop(); + } + + + // Member Functions + + //- Start parsing, with the given driver context + void start(parseDriver& driver_); + + //- Stop parsing, freeing the allocated parser + void stop(); + + //- Push token/value to parser + void parse(int tokenId, scanToken* tokenVal); + + //- Return the text name corresponding to the tokenId + word nameOfToken(int tokenId) const; +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace patchExpr +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprScanner.H b/src/finiteVolume/expressions/patch/patchExprScanner.H new file mode 100644 index 0000000000000000000000000000000000000000..3003b749bfea5f5ac959cc0d40a53bd22b1d2f5d --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprScanner.H @@ -0,0 +1,162 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::expressions::patchExpr::scanner + +Description + Ragel lexer/scanner interface for patch expressions. + +Note + Ragel code generated with the ./createCode script. + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_patchExprScanner_H +#define expressions_patchExprScanner_H + +#include "patchExprFwd.H" +#include "scalar.H" + +namespace Foam +{ +namespace expressions +{ +namespace patchExpr +{ + +/*---------------------------------------------------------------------------*\ + Class scanToken Declaration +\*---------------------------------------------------------------------------*/ + +union scanToken +{ + Foam::label ivalue; + Foam::scalar svalue; + Foam::word* name; + + //- Null construct, bit-wise zero for union content + scanToken() : ivalue(0) {} +}; + + +/*---------------------------------------------------------------------------*\ + Class scanner Declaration +\*---------------------------------------------------------------------------*/ + +class scanner +{ + // Private Data + + //- Wrapped lemon parser + parser* parser_; + + // Ragel code state, action + int cs, act; + + + // Private Member Functions + + //- Dispatch .method to parser (if known) or Fatal + bool dispatch_method + ( + const parseDriver& driver_, + scanToken& scanTok, + word&& ident + ) const; + + //- Dispatch identifier to parser (if possible) or Fatal + bool dispatch_ident + ( + const parseDriver& driver_, + scanToken& scanTok, + word&& ident + ) const; + + +public: + + //- Local debugging + int debug; + + + // Constructors + + //- Construct null, optionally setting debugging + explicit scanner(bool withDebug = false) + : + parser_(nullptr), + debug(patchExpr::debug) + { + if (withDebug) + { + debug |= 4; + } + } + + + //- Destructor, deletes parser + ~scanner(); + + + // Member Functions + + //- Evaluate sub-string + bool process + ( + const std::string& str, size_t pos, size_t len, + parseDriver& driver_ + ); + + //- Evaluate sub-string + bool process + ( + const std::string& str, size_t pos, + parseDriver& driver_ + ) + { + return process(str, pos, std::string::npos, driver_); + } + + //- Evaluate string + bool process(const std::string& str, parseDriver& driver_) + { + return process(str, 0, std::string::npos, driver_); + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace patchExpr +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprScanner.cc b/src/finiteVolume/expressions/patch/patchExprScanner.cc new file mode 100644 index 0000000000000000000000000000000000000000..98fe2225e1150dd27267fe061cc7910b89b24b4a --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprScanner.cc @@ -0,0 +1,3836 @@ + +#line 1 "patchExprScanner.rl" +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Ragel lexer interface for lemon grammar for patch expressions + +\*---------------------------------------------------------------------------*/ + +#include "patchExprScanner.H" +#include "patchExprDriver.H" +#include "patchExprLemonParser.h" +#include "patchExprParser.H" +#include "Enum.H" +#include "macros.H" + +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Wold-style-cast" + +// Debugging to stderr +#undef DebugInfo +#define DebugInfo if (debug) InfoErr + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + +//- Paste token prefix +#define TOKEN_OF(T) TOK_##T + +//- An {int, c_str} enum pairing +#define TOKEN_PAIR(Name,T) { TOKEN_OF(T), Name } + +#undef HAS_LOOKBEHIND_TOKENS + +// Special handling of predefined method types. Eg, .x(), .y(), ... +static const Enum<int> fieldMethodEnums +({ + TOKEN_PAIR("x", CMPT_X), + TOKEN_PAIR("y", CMPT_Y), + TOKEN_PAIR("z", CMPT_Z), + TOKEN_PAIR("xx", CMPT_XX), + TOKEN_PAIR("xy", CMPT_XY), + TOKEN_PAIR("xz", CMPT_XZ), + TOKEN_PAIR("yx", CMPT_YX), + TOKEN_PAIR("yy", CMPT_YY), + TOKEN_PAIR("yz", CMPT_YZ), + TOKEN_PAIR("zx", CMPT_ZX), + TOKEN_PAIR("zy", CMPT_ZY), + TOKEN_PAIR("zz", CMPT_ZZ), + TOKEN_PAIR("ii", CMPT_II), + TOKEN_PAIR("diag", DIAG), /* tensors only */ + TOKEN_PAIR("T", TRANSPOSE), /* tensors only */ +}); + +// Known field-token types +static const Enum<int> fieldTokenEnums +({ +#ifdef TOK_SCALAR_ID + TOKEN_PAIR(volScalarField::typeName.c_str(), SCALAR_ID), + TOKEN_PAIR(volVectorField::typeName.c_str(), VECTOR_ID), + TOKEN_PAIR(volTensorField::typeName.c_str(), TENSOR_ID), + TOKEN_PAIR(volSymmTensorField::typeName.c_str(), SYM_TENSOR_ID), + TOKEN_PAIR(volSphericalTensorField::typeName.c_str(), SPH_TENSOR_ID), +#else +#error TOK_SCALAR_ID not defined +#endif +#ifdef TOK_SSCALAR_ID + TOKEN_PAIR(surfaceScalarField::typeName.c_str(), SSCALAR_ID), + TOKEN_PAIR(surfaceVectorField::typeName.c_str(), SVECTOR_ID), + TOKEN_PAIR(surfaceTensorField::typeName.c_str(), STENSOR_ID), + TOKEN_PAIR(surfaceSymmTensorField::typeName.c_str(), SSYM_TENSOR_ID), + TOKEN_PAIR(surfaceSphericalTensorField::typeName.c_str(), SSPH_TENSOR_ID), +#else +#error TOK_SSCALAR_ID not defined +#endif +#ifdef TOK_PSCALAR_ID + TOKEN_PAIR(pointScalarField::typeName.c_str(), PSCALAR_ID), + TOKEN_PAIR(pointVectorField::typeName.c_str(), PVECTOR_ID), + TOKEN_PAIR(pointTensorField::typeName.c_str(), PTENSOR_ID), + TOKEN_PAIR(pointSymmTensorField::typeName.c_str(), PSYM_TENSOR_ID), + TOKEN_PAIR(pointSphericalTensorField::typeName.c_str(), PSPH_TENSOR_ID), +#else +#warning TOK_PSCALAR_ID not defined +#endif +}); + + +// Simple compile-time function name declarations. +// Useful for handling driver-specific dispatching, or functions that +// are not universally available. +static const Enum<int> funcTokenEnums +({ +#ifdef TOK_FLOOR + TOKEN_PAIR("floor", FLOOR), + TOKEN_PAIR("ceil", CEIL), + TOKEN_PAIR("round", ROUND), +#endif +#ifdef TOK_HYPOT /* Can use hypot? */ + TOKEN_PAIR("hypot", HYPOT), +#endif + + // Already parsed as function: TOKEN_PAIR("pos", FACE_CENTRE), + + TOKEN_PAIR("point", POINT_EXPR), // Point value + TOKEN_PAIR("face", FACE_EXPR), // Face areaNormal + + TOKEN_PAIR("faceToPoint", FACE_TO_POINT), + TOKEN_PAIR("pointToFace", POINT_TO_FACE), + + TOKEN_PAIR("area", FACE_AREA), + TOKEN_PAIR("pts", POINTS), +}); + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Classifying token type based on an identifier name is indeed ugly. +// +// 1) +// Handle special cases (eg, cellSet,...) first that have been tagged +// as expected content with the stashed "look-behind" token. +// Handle not-found errors here directly. +// +// 2) +// Fallback to determining which field-type (volScalarField etc) the name +// corresponds to. +// Handle not-found errors by return -1. +// +static int driverTokenType +( + const expressions::patchExpr::parseDriver& driver_, + const word& ident +) +{ +#if 0 + // Get stashed "look-behind" to decide what type of identifier we expect + const int lookBehind = driver_.resetStashedTokenId(); + + if (lookBehind && lookBehindTokenEnums.found(lookBehind)) + { + bool good = false; + + switch (lookBehind) + { + case TOK_CSET : good = driver_.isCellSet(ident); break; + case TOK_FSET : good = driver_.isFaceSet(ident); break; + case TOK_PSET : good = driver_.isPointSet(ident); break; + case TOK_CZONE : good = driver_.isCellZone(ident); break; + case TOK_FZONE : good = driver_.isFaceZone(ident); break; + case TOK_PZONE : good = driver_.isPointZone(ident); break; + } + + if (good) + { + return TOK_IDENTIFIER; + } + + // Fatal + driver_.reportFatal + ( + "Error no " + lookBehindTokenEnums.get(lookBehind) + ": " + ident + ); + + return -2; // Extra safety + } +#endif + + // Face variables + #ifdef TOK_SSCALAR_ID + { + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable<Type>(ident, false)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_SSCALAR_ID, scalar); + checkFieldToken(TOK_SVECTOR_ID, vector); + checkFieldToken(TOK_SSYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_SSPH_TENSOR_ID, sphericalTensor); + checkFieldToken(TOK_STENSOR_ID, tensor); + + // Not tested: checkFieldToken(TOK_SBOOL_ID, bool); + } + #endif + + // Point variables + #ifdef TOK_PSCALAR_ID + { + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable<Type>(ident, true)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_PSCALAR_ID, scalar); + checkFieldToken(TOK_PVECTOR_ID, vector); + checkFieldToken(TOK_PTENSOR_ID, tensor); + checkFieldToken(TOK_PTENSOR_ID, tensor); + checkFieldToken(TOK_PSYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_PSPH_TENSOR_ID, sphericalTensor); + + // Not tested: checkFieldToken(TOK_PBOOL_ID, bool); + } + #endif + + #undef checkFieldToken + + // Check registered fields and/or disk-files + { + const word fieldType(driver_.getFieldClassName(ident)); + + int tokType = fieldTokenEnums.get(fieldType, -1); + + if (tokType > 0) + { + return tokType; + } + } + + return -1; +} + +} // End anonymous namespace + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// Ragel machine definition +// Ragel variables (p, pe, eof, cs, top, stack, ts, te, act) defined later... +// +// Can use 'variable p xxx;' etc to change these names + +#define EMIT_TOKEN(T) \ + driver_.parsePosition() = (ts-buf); \ + DebugInfo<< STRINGIFY(T) << ": " << driver_.parsePosition() << nl; \ + parser_->parse(TOKEN_OF(T), nullptr); \ + driver_.parsePosition() = (p-buf); + + + +#line 276 "patchExprScanner.cc" +static const int patchExpr_start = 11; +static const int patchExpr_first_final = 11; +static const int patchExpr_error = 0; + +static const int patchExpr_en_main = 11; + + +#line 414 "patchExprScanner.rl" + + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::expressions::patchExpr::scanner::~scanner() +{ + if (parser_) + { + delete parser_; + } +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +bool Foam::expressions::patchExpr::scanner::dispatch_method +( + const parseDriver& driver_, + scanToken& scanTok, + word&& ident +) const +{ + if (ident[0] == '.') + { + ident.erase(0, 1); + } + + DebugInfo + << "Method:" << ident + << " at " << driver_.parsePosition() << nl; + + const int methType = fieldMethodEnums.get(ident, -1); + + if (methType > 0) + { + // Dispatch '.' and "method" separately + parser_->parse(TOK_DOT, nullptr); + parser_->parse(methType, nullptr); + + return true; + } + + driver_.reportFatal("Unknown method: " + ident); + return false; +} + + +bool Foam::expressions::patchExpr::scanner::dispatch_ident +( + const parseDriver& driver_, + scanToken& scanTok, + word&& ident +) const +{ + int tokType = -1; + + const bool quoted = + ( + (ident.front() == '"' || ident.front() == '\'') + && (ident.front() == ident.back()) + ); + + if (quoted) + { + ident.erase(ident.size()-1); + ident.erase(0, 1); + } + else + { + // Check for function name + tokType = funcTokenEnums.get(ident, -1); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " function:" + << parser_->nameOfToken(tokType) << nl; + + parser_->parse(tokType, nullptr); + return true; + } + + #ifdef HAS_LOOKBEHIND_TOKENS + // Specials such "cset" also reset the look-behind + tokType = lookBehindTokenEnums.get(ident, -1); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " as look-behind:" + << parser_->nameOfToken(tokType) << nl; + + driver_.resetStashedTokenId(tokType); + parser_->parse(tokType, nullptr); + return true; + } + #endif + } + + + // Can also peek at stashed "look-behind" + // const int lookBehind = driver_.stashedTokenId(); + + tokType = driverTokenType(driver_, ident); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " token:" + << parser_->nameOfToken(tokType) << nl; + + scanTok.name = new Foam::word(std::move(ident)); + parser_->parse(tokType, &scanTok); + + return true; + } + + + // Not found? Attempt to strip off '.x' endings etc, + // but not when quoted + + const auto dot = ident.rfind('.'); + const int methType = + ( + quoted || dot == std::string::npos + ? -1 + : fieldMethodEnums.get(ident.substr(dot+1), -1) + ); + + if + ( + methType > 0 + && (tokType = driverTokenType(driver_, ident.substr(0, dot))) > 0 + ) + { + DebugInfo + << "Emit:" << ident.substr(0, dot).c_str() << " token:" + << parser_->nameOfToken(tokType) << " with " + << ident.substr(dot).c_str() << " token:" + << parser_->nameOfToken(methType) << nl; + + // The field (before the ".") + ident.erase(dot); + + scanTok.name = new Foam::word(std::move(ident)); + parser_->parse(tokType, &scanTok); + + // Dispatch '.' and "method" separately + parser_->parse(TOK_DOT, nullptr); + parser_->parse(methType, nullptr); + + return true; + } + + driver_.reportFatal + ( + "Object " + ident + " does not exist or wrong type" + ); + + return false; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::expressions::patchExpr::scanner::process +( + const std::string& str, + size_t strBeg, + size_t strLen, + parseDriver& driver_ +) +{ + // Save debug value + const int oldDebug = debug; + + if (driver_.debugScanner()) + { + debug |= 4; + } + + if (!parser_) + { + parser_ = new parser(); + } + + driver_.content(str, strBeg, strLen); + + size_t strEnd = str.length(); + + if (strBeg > str.length()) + { + strBeg = str.length(); + } + else if (strLen != std::string::npos) + { + strLen += strBeg; + + if (strLen < str.length()) + { + strEnd = strLen; + } + } + + + parser_->start(driver_); + + // Scan token type + scanToken scanTok; + + // Ragel token start/end (required naming) + const char* ts; + const char* te; + + // Local buffer data. + // - p, pe, eof are required Ragel naming + // - buf is our own naming + + const char* buf = &(str[strBeg]); + const char* eof = &(str[strEnd]); + const char* p = buf; + const char* pe = eof; + + // Initialize FSM variables + +#line 511 "patchExprScanner.cc" + { + cs = patchExpr_start; + ts = 0; + te = 0; + act = 0; + } + +#line 639 "patchExprScanner.rl" + /* ^^^ FSM initialization here ^^^ */; + + +#line 523 "patchExprScanner.cc" + { + if ( p == pe ) + goto _test_eof; + switch ( cs ) + { +tr2: +#line 298 "patchExprScanner.rl" + {te = p+1;{ + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + }} + goto st11; +tr4: +#line 298 "patchExprScanner.rl" + {te = p+1;{ + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + }} + goto st11; +tr5: +#line 276 "patchExprScanner.rl" + {{p = ((te))-1;}{ + 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); + }} + goto st11; +tr8: +#line 341 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(EQUAL); }} + goto st11; +tr9: +#line 395 "patchExprScanner.rl" + {{p = ((te))-1;}{ EMIT_TOKEN(TENSOR); }} + goto st11; +tr11: +#line 403 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(UNIT_TENSOR); }} + goto st11; +tr12: +#line 344 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LOR); }} + goto st11; +tr16: +#line 326 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(PERCENT); }} + goto st11; +tr19: +#line 327 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LPAREN); }} + goto st11; +tr20: +#line 328 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(RPAREN); }} + goto st11; +tr21: +#line 329 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(TIMES); }} + goto st11; +tr22: +#line 330 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(PLUS); }} + goto st11; +tr23: +#line 332 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(COMMA); }} + goto st11; +tr24: +#line 331 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(MINUS); }} + goto st11; +tr26: +#line 334 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(DIVIDE); }} + goto st11; +tr28: +#line 336 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(COLON); }} + goto st11; +tr32: +#line 335 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(QUESTION); }} + goto st11; +tr35: +#line 347 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(BIT_XOR); }} + goto st11; +tr52: +#line 320 "patchExprScanner.rl" + {te = p;p--;} + goto st11; +tr53: +#line 325 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(NOT); }} + goto st11; +tr54: +#line 342 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(NOT_EQUAL); }} + goto st11; +tr55: +#line 345 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(BIT_AND); }} + goto st11; +tr56: +#line 343 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LAND); }} + goto st11; +tr57: +#line 333 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(DOT); }} + goto st11; +tr60: +#line 276 "patchExprScanner.rl" + {te = p;p--;{ + 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); + }} + goto st11; +tr62: +#line 304 "patchExprScanner.rl" + {te = p;p--;{ + // 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); + }} + goto st11; +tr63: +#line 337 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(LESS); }} + goto st11; +tr64: +#line 338 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LESS_EQ); }} + goto st11; +tr65: +#line 339 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(GREATER); }} + goto st11; +tr66: +#line 340 "patchExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(GREATER_EQ); }} + goto st11; +tr67: +#line 298 "patchExprScanner.rl" + {te = p;p--;{ + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + }} + goto st11; +tr69: +#line 1 "NONE" + { switch( act ) { + case 26: + {{p = ((te))-1;} EMIT_TOKEN(PI); } + break; + case 27: + {{p = ((te))-1;} EMIT_TOKEN(DEG_TO_RAD); } + break; + case 28: + {{p = ((te))-1;} EMIT_TOKEN(RAD_TO_DEG); } + break; + case 29: + {{p = ((te))-1;} EMIT_TOKEN(EXP); } + break; + case 31: + {{p = ((te))-1;} EMIT_TOKEN(LOG10); } + break; + case 32: + {{p = ((te))-1;} EMIT_TOKEN(POW); } + break; + case 34: + {{p = ((te))-1;} EMIT_TOKEN(SQRT); } + break; + case 35: + {{p = ((te))-1;} EMIT_TOKEN(CBRT); } + break; + case 39: + {{p = ((te))-1;} EMIT_TOKEN(ASIN); } + break; + case 40: + {{p = ((te))-1;} EMIT_TOKEN(ACOS); } + break; + case 42: + {{p = ((te))-1;} EMIT_TOKEN(ATAN2); } + break; + case 43: + {{p = ((te))-1;} EMIT_TOKEN(SINH); } + break; + case 44: + {{p = ((te))-1;} EMIT_TOKEN(COSH); } + break; + case 45: + {{p = ((te))-1;} EMIT_TOKEN(TANH); } + break; + case 47: + {{p = ((te))-1;} EMIT_TOKEN(MAGSQR); } + break; + case 50: + {{p = ((te))-1;} EMIT_TOKEN(POS0); } + break; + case 51: + {{p = ((te))-1;} EMIT_TOKEN(NEG0); } + break; + case 52: + {{p = ((te))-1;} EMIT_TOKEN(SIGN); } + break; + case 53: + {{p = ((te))-1;} EMIT_TOKEN(MIN); } + break; + case 54: + {{p = ((te))-1;} EMIT_TOKEN(MAX); } + break; + case 55: + {{p = ((te))-1;} EMIT_TOKEN(AVERAGE); } + break; + case 56: + {{p = ((te))-1;} EMIT_TOKEN(SUM); } + break; + case 57: + {{p = ((te))-1;} EMIT_TOKEN(WEIGHT_AVERAGE); } + break; + case 58: + {{p = ((te))-1;} EMIT_TOKEN(WEIGHT_SUM); } + break; + case 59: + {{p = ((te))-1;} EMIT_TOKEN(RAND); } + break; + case 60: + {{p = ((te))-1;} EMIT_TOKEN(BOOL); } + break; + case 61: + {{p = ((te))-1;} EMIT_TOKEN(VECTOR); } + break; + case 63: + {{p = ((te))-1;} EMIT_TOKEN(SYM_TENSOR); } + break; + case 64: + {{p = ((te))-1;} EMIT_TOKEN(SPH_TENSOR); } + break; + case 65: + {{p = ((te))-1;} EMIT_TOKEN(ZERO); } + break; + case 66: + {{p = ((te))-1;} EMIT_TOKEN(LTRUE); } + break; + case 67: + {{p = ((te))-1;} EMIT_TOKEN(LFALSE); } + break; + case 69: + {{p = ((te))-1;} EMIT_TOKEN(TIME); } + break; + case 70: + {{p = ((te))-1;} + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + } + break; + } + } + goto st11; +tr83: +#line 369 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(ATAN); }} + goto st11; +tr98: +#line 365 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(COS); }} + goto st11; +tr115: +#line 358 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(LOG); }} + goto st11; +tr122: +#line 374 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(MAG); }} + goto st11; +tr129: +#line 378 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(NEG); }} + goto st11; +tr135: +#line 377 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(POS); }} + goto st11; +tr154: +#line 364 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(SIN); }} + goto st11; +tr170: +#line 361 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(SQR); }} + goto st11; +tr186: +#line 366 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(TAN); }} + goto st11; +tr192: +#line 395 "patchExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(TENSOR); }} + goto st11; +st11: +#line 1 "NONE" + {ts = 0;} + if ( ++p == pe ) + goto _test_eof11; +case 11: +#line 1 "NONE" + {ts = p;} +#line 870 "patchExprScanner.cc" + switch( (*p) ) { + case 32: goto st12; + case 33: goto st13; + case 34: goto st1; + case 37: goto tr16; + case 38: goto st14; + case 39: goto st3; + case 40: goto tr19; + case 41: goto tr20; + case 42: goto tr21; + case 43: goto tr22; + case 44: goto tr23; + case 45: goto tr24; + case 46: goto st15; + case 47: goto tr26; + case 58: goto tr28; + case 60: goto st20; + case 61: goto st7; + case 62: goto st21; + case 63: goto tr32; + case 90: goto st24; + case 94: goto tr35; + case 95: goto st22; + case 97: goto st27; + case 98: goto st40; + case 99: goto st43; + case 100: goto st48; + case 101: goto st55; + case 102: goto st57; + case 108: goto st61; + case 109: goto st65; + case 110: goto st71; + case 112: goto st74; + case 114: goto st77; + case 115: goto st85; + case 116: goto st113; + case 118: goto st125; + case 119: goto st130; + case 124: goto st10; + } + if ( (*p) < 48 ) { + if ( 9 <= (*p) && (*p) <= 13 ) + goto st12; + } else if ( (*p) > 57 ) { + if ( (*p) > 89 ) { + if ( 103 <= (*p) && (*p) <= 122 ) + goto st22; + } else if ( (*p) >= 65 ) + goto st22; + } else + goto tr27; + goto st0; +st0: +cs = 0; + goto _out; +st12: + if ( ++p == pe ) + goto _test_eof12; +case 12: + if ( (*p) == 32 ) + goto st12; + if ( 9 <= (*p) && (*p) <= 13 ) + goto st12; + goto tr52; +st13: + if ( ++p == pe ) + goto _test_eof13; +case 13: + if ( (*p) == 61 ) + goto tr54; + goto tr53; +st1: + if ( ++p == pe ) + goto _test_eof1; +case 1: + if ( (*p) == 34 ) + goto st0; + goto st2; +st2: + if ( ++p == pe ) + goto _test_eof2; +case 2: + if ( (*p) == 34 ) + goto tr2; + goto st2; +st14: + if ( ++p == pe ) + goto _test_eof14; +case 14: + if ( (*p) == 38 ) + goto tr56; + goto tr55; +st3: + if ( ++p == pe ) + goto _test_eof3; +case 3: + if ( (*p) == 39 ) + goto st0; + goto st4; +st4: + if ( ++p == pe ) + goto _test_eof4; +case 4: + if ( (*p) == 39 ) + goto tr4; + goto st4; +st15: + if ( ++p == pe ) + goto _test_eof15; +case 15: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr58; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st18; + } else + goto st18; + goto tr57; +tr58: +#line 1 "NONE" + {te = p+1;} + goto st16; +st16: + if ( ++p == pe ) + goto _test_eof16; +case 16: +#line 998 "patchExprScanner.cc" + switch( (*p) ) { + case 69: goto st5; + case 101: goto st5; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr58; + goto tr60; +st5: + if ( ++p == pe ) + goto _test_eof5; +case 5: + switch( (*p) ) { + case 43: goto st6; + case 45: goto st6; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto st17; + goto tr5; +st6: + if ( ++p == pe ) + goto _test_eof6; +case 6: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st17; + goto tr5; +st17: + if ( ++p == pe ) + goto _test_eof17; +case 17: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st17; + goto tr60; +st18: + if ( ++p == pe ) + goto _test_eof18; +case 18: + if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st18; + } else if ( (*p) >= 65 ) + goto st18; + goto tr62; +tr27: +#line 1 "NONE" + {te = p+1;} + goto st19; +st19: + if ( ++p == pe ) + goto _test_eof19; +case 19: +#line 1049 "patchExprScanner.cc" + switch( (*p) ) { + case 46: goto tr58; + case 69: goto st5; + case 101: goto st5; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr27; + goto tr60; +st20: + if ( ++p == pe ) + goto _test_eof20; +case 20: + if ( (*p) == 61 ) + goto tr64; + goto tr63; +st7: + if ( ++p == pe ) + goto _test_eof7; +case 7: + if ( (*p) == 61 ) + goto tr8; + goto st0; +st21: + if ( ++p == pe ) + goto _test_eof21; +case 21: + if ( (*p) == 61 ) + goto tr66; + goto tr65; +st22: + if ( ++p == pe ) + goto _test_eof22; +case 22: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +tr68: +#line 1 "NONE" + {te = p+1;} +#line 298 "patchExprScanner.rl" + {act = 70;} + goto st23; +tr72: +#line 1 "NONE" + {te = p+1;} +#line 400 "patchExprScanner.rl" + {act = 65;} + goto st23; +tr78: +#line 1 "NONE" + {te = p+1;} +#line 368 "patchExprScanner.rl" + {act = 40;} + goto st23; +tr80: +#line 1 "NONE" + {te = p+1;} +#line 367 "patchExprScanner.rl" + {act = 39;} + goto st23; +tr84: +#line 1 "NONE" + {te = p+1;} +#line 370 "patchExprScanner.rl" + {act = 42;} + goto st23; +tr89: +#line 1 "NONE" + {te = p+1;} +#line 386 "patchExprScanner.rl" + {act = 55;} + goto st23; +tr92: +#line 1 "NONE" + {te = p+1;} +#line 393 "patchExprScanner.rl" + {act = 60;} + goto st23; +tr96: +#line 1 "NONE" + {te = p+1;} +#line 363 "patchExprScanner.rl" + {act = 35;} + goto st23; +tr99: +#line 1 "NONE" + {te = p+1;} +#line 372 "patchExprScanner.rl" + {act = 44;} + goto st23; +tr106: +#line 1 "NONE" + {te = p+1;} +#line 355 "patchExprScanner.rl" + {act = 27;} + goto st23; +tr108: +#line 1 "NONE" + {te = p+1;} +#line 357 "patchExprScanner.rl" + {act = 29;} + goto st23; +tr112: +#line 1 "NONE" + {te = p+1;} +#line 402 "patchExprScanner.rl" + {act = 67;} + goto st23; +tr117: +#line 1 "NONE" + {te = p+1;} +#line 359 "patchExprScanner.rl" + {act = 31;} + goto st23; +tr121: +#line 1 "NONE" + {te = p+1;} +#line 385 "patchExprScanner.rl" + {act = 54;} + goto st23; +tr125: +#line 1 "NONE" + {te = p+1;} +#line 375 "patchExprScanner.rl" + {act = 47;} + goto st23; +tr126: +#line 1 "NONE" + {te = p+1;} +#line 384 "patchExprScanner.rl" + {act = 53;} + goto st23; +tr130: +#line 1 "NONE" + {te = p+1;} +#line 380 "patchExprScanner.rl" + {act = 51;} + goto st23; +tr131: +#line 1 "NONE" + {te = p+1;} +#line 354 "patchExprScanner.rl" + {act = 26;} + goto st23; +tr134: +#line 1 "NONE" + {te = p+1;} +#line 360 "patchExprScanner.rl" + {act = 32;} + goto st23; +tr136: +#line 1 "NONE" + {te = p+1;} +#line 379 "patchExprScanner.rl" + {act = 50;} + goto st23; +tr144: +#line 1 "NONE" + {te = p+1;} +#line 356 "patchExprScanner.rl" + {act = 28;} + goto st23; +tr145: +#line 1 "NONE" + {te = p+1;} +#line 390 "patchExprScanner.rl" + {act = 59;} + goto st23; +tr153: +#line 1 "NONE" + {te = p+1;} +#line 381 "patchExprScanner.rl" + {act = 52;} + goto st23; +tr155: +#line 1 "NONE" + {te = p+1;} +#line 371 "patchExprScanner.rl" + {act = 43;} + goto st23; +tr168: +#line 1 "NONE" + {te = p+1;} +#line 397 "patchExprScanner.rl" + {act = 64;} + goto st23; +tr171: +#line 1 "NONE" + {te = p+1;} +#line 362 "patchExprScanner.rl" + {act = 34;} + goto st23; +tr172: +#line 1 "NONE" + {te = p+1;} +#line 387 "patchExprScanner.rl" + {act = 56;} + goto st23; +tr180: +#line 1 "NONE" + {te = p+1;} +#line 396 "patchExprScanner.rl" + {act = 63;} + goto st23; +tr187: +#line 1 "NONE" + {te = p+1;} +#line 373 "patchExprScanner.rl" + {act = 45;} + goto st23; +tr195: +#line 1 "NONE" + {te = p+1;} +#line 404 "patchExprScanner.rl" + {act = 69;} + goto st23; +tr197: +#line 1 "NONE" + {te = p+1;} +#line 401 "patchExprScanner.rl" + {act = 66;} + goto st23; +tr202: +#line 1 "NONE" + {te = p+1;} +#line 394 "patchExprScanner.rl" + {act = 61;} + goto st23; +tr215: +#line 1 "NONE" + {te = p+1;} +#line 388 "patchExprScanner.rl" + {act = 57;} + goto st23; +tr217: +#line 1 "NONE" + {te = p+1;} +#line 389 "patchExprScanner.rl" + {act = 58;} + goto st23; +st23: + if ( ++p == pe ) + goto _test_eof23; +case 23: +#line 1304 "patchExprScanner.cc" + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr69; +st24: + if ( ++p == pe ) + goto _test_eof24; +case 24: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st25; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st25: + if ( ++p == pe ) + goto _test_eof25; +case 25: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st26; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st26: + if ( ++p == pe ) + goto _test_eof26; +case 26: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto tr72; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st27: + if ( ++p == pe ) + goto _test_eof27; +case 27: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st28; + case 115: goto st30; + case 116: goto st32; + case 118: goto st35; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st28: + if ( ++p == pe ) + goto _test_eof28; +case 28: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st29; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st29: + if ( ++p == pe ) + goto _test_eof29; +case 29: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto tr78; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st30: + if ( ++p == pe ) + goto _test_eof30; +case 30: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st31; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st31: + if ( ++p == pe ) + goto _test_eof31; +case 31: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr80; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st32: + if ( ++p == pe ) + goto _test_eof32; +case 32: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st33; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st33: + if ( ++p == pe ) + goto _test_eof33; +case 33: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st34; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st34: + if ( ++p == pe ) + goto _test_eof34; +case 34: + switch( (*p) ) { + case 46: goto tr68; + case 50: goto tr84; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr83; +st35: + if ( ++p == pe ) + goto _test_eof35; +case 35: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st36; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st36: + if ( ++p == pe ) + goto _test_eof36; +case 36: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st37; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st37: + if ( ++p == pe ) + goto _test_eof37; +case 37: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st38; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st38: + if ( ++p == pe ) + goto _test_eof38; +case 38: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st39; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st39: + if ( ++p == pe ) + goto _test_eof39; +case 39: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr89; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st40: + if ( ++p == pe ) + goto _test_eof40; +case 40: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st41; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st41: + if ( ++p == pe ) + goto _test_eof41; +case 41: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st42; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st42: + if ( ++p == pe ) + goto _test_eof42; +case 42: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto tr92; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st43: + if ( ++p == pe ) + goto _test_eof43; +case 43: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 98: goto st44; + case 111: goto st46; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st44: + if ( ++p == pe ) + goto _test_eof44; +case 44: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st45; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st45: + if ( ++p == pe ) + goto _test_eof45; +case 45: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto tr96; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st46: + if ( ++p == pe ) + goto _test_eof46; +case 46: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st47; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st47: + if ( ++p == pe ) + goto _test_eof47; +case 47: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr99; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr98; +st48: + if ( ++p == pe ) + goto _test_eof48; +case 48: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st49; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st49: + if ( ++p == pe ) + goto _test_eof49; +case 49: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st50; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st50: + if ( ++p == pe ) + goto _test_eof50; +case 50: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st51; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st51: + if ( ++p == pe ) + goto _test_eof51; +case 51: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st52; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st52: + if ( ++p == pe ) + goto _test_eof52; +case 52: + switch( (*p) ) { + case 46: goto tr68; + case 82: goto st53; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st53: + if ( ++p == pe ) + goto _test_eof53; +case 53: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st54; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st54: + if ( ++p == pe ) + goto _test_eof54; +case 54: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto tr106; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st55: + if ( ++p == pe ) + goto _test_eof55; +case 55: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 120: goto st56; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st56: + if ( ++p == pe ) + goto _test_eof56; +case 56: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 112: goto tr108; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st57: + if ( ++p == pe ) + goto _test_eof57; +case 57: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st58; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st58: + if ( ++p == pe ) + goto _test_eof58; +case 58: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto st59; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st59: + if ( ++p == pe ) + goto _test_eof59; +case 59: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st60; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st60: + if ( ++p == pe ) + goto _test_eof60; +case 60: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr112; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st61: + if ( ++p == pe ) + goto _test_eof61; +case 61: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st62; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st62: + if ( ++p == pe ) + goto _test_eof62; +case 62: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st63; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st63: + if ( ++p == pe ) + goto _test_eof63; +case 63: + switch( (*p) ) { + case 46: goto tr68; + case 49: goto st64; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr115; +st64: + if ( ++p == pe ) + goto _test_eof64; +case 64: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr117; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st65: + if ( ++p == pe ) + goto _test_eof65; +case 65: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st66; + case 105: goto st70; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st66: + if ( ++p == pe ) + goto _test_eof66; +case 66: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st67; + case 120: goto tr121; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st67: + if ( ++p == pe ) + goto _test_eof67; +case 67: + switch( (*p) ) { + case 46: goto tr68; + case 83: goto st68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr122; +st68: + if ( ++p == pe ) + goto _test_eof68; +case 68: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 113: goto st69; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st69: + if ( ++p == pe ) + goto _test_eof69; +case 69: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr125; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st70: + if ( ++p == pe ) + goto _test_eof70; +case 70: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr126; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st71: + if ( ++p == pe ) + goto _test_eof71; +case 71: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st72; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st72: + if ( ++p == pe ) + goto _test_eof72; +case 72: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st73; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st73: + if ( ++p == pe ) + goto _test_eof73; +case 73: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr130; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr129; +st74: + if ( ++p == pe ) + goto _test_eof74; +case 74: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto tr131; + case 111: goto st75; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st75: + if ( ++p == pe ) + goto _test_eof75; +case 75: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st76; + case 119: goto tr134; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st76: + if ( ++p == pe ) + goto _test_eof76; +case 76: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr136; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr135; +st77: + if ( ++p == pe ) + goto _test_eof77; +case 77: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st78; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st78: + if ( ++p == pe ) + goto _test_eof78; +case 78: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto st79; + case 110: goto st84; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st79: + if ( ++p == pe ) + goto _test_eof79; +case 79: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st80; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st80: + if ( ++p == pe ) + goto _test_eof80; +case 80: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st81; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st81: + if ( ++p == pe ) + goto _test_eof81; +case 81: + switch( (*p) ) { + case 46: goto tr68; + case 68: goto st82; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st82: + if ( ++p == pe ) + goto _test_eof82; +case 82: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st83; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st83: + if ( ++p == pe ) + goto _test_eof83; +case 83: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto tr144; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st84: + if ( ++p == pe ) + goto _test_eof84; +case 84: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto tr145; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st85: + if ( ++p == pe ) + goto _test_eof85; +case 85: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st86; + case 112: goto st89; + case 113: goto st102; + case 117: goto st104; + case 121: goto st105; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st86: + if ( ++p == pe ) + goto _test_eof86; +case 86: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st87; + case 110: goto st88; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st87: + if ( ++p == pe ) + goto _test_eof87; +case 87: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr153; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st88: + if ( ++p == pe ) + goto _test_eof88; +case 88: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr155; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr154; +st89: + if ( ++p == pe ) + goto _test_eof89; +case 89: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto st90; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st90: + if ( ++p == pe ) + goto _test_eof90; +case 90: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st91; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st91: + if ( ++p == pe ) + goto _test_eof91; +case 91: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st92; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st92: + if ( ++p == pe ) + goto _test_eof92; +case 92: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st93; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st93: + if ( ++p == pe ) + goto _test_eof93; +case 93: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st94; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st94: + if ( ++p == pe ) + goto _test_eof94; +case 94: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st95; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st95: + if ( ++p == pe ) + goto _test_eof95; +case 95: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto st96; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st96: + if ( ++p == pe ) + goto _test_eof96; +case 96: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st97; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st97: + if ( ++p == pe ) + goto _test_eof97; +case 97: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st98; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st98: + if ( ++p == pe ) + goto _test_eof98; +case 98: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st99; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st99: + if ( ++p == pe ) + goto _test_eof99; +case 99: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st100; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st100: + if ( ++p == pe ) + goto _test_eof100; +case 100: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st101; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st101: + if ( ++p == pe ) + goto _test_eof101; +case 101: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr168; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st102: + if ( ++p == pe ) + goto _test_eof102; +case 102: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st103; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st103: + if ( ++p == pe ) + goto _test_eof103; +case 103: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto tr171; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr170; +st104: + if ( ++p == pe ) + goto _test_eof104; +case 104: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto tr172; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st105: + if ( ++p == pe ) + goto _test_eof105; +case 105: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st106; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st106: + if ( ++p == pe ) + goto _test_eof106; +case 106: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st107; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st107: + if ( ++p == pe ) + goto _test_eof107; +case 107: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st108; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st108: + if ( ++p == pe ) + goto _test_eof108; +case 108: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st109; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st109: + if ( ++p == pe ) + goto _test_eof109; +case 109: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st110; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st110: + if ( ++p == pe ) + goto _test_eof110; +case 110: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st111; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st111: + if ( ++p == pe ) + goto _test_eof111; +case 111: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st112; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st112: + if ( ++p == pe ) + goto _test_eof112; +case 112: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr180; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st113: + if ( ++p == pe ) + goto _test_eof113; +case 113: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st114; + case 101: goto st116; + case 105: goto st121; + case 114: goto st123; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st114: + if ( ++p == pe ) + goto _test_eof114; +case 114: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st115; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st115: + if ( ++p == pe ) + goto _test_eof115; +case 115: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr187; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr186; +st116: + if ( ++p == pe ) + goto _test_eof116; +case 116: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st117; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st117: + if ( ++p == pe ) + goto _test_eof117; +case 117: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st118; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st118: + if ( ++p == pe ) + goto _test_eof118; +case 118: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st119; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st119: + if ( ++p == pe ) + goto _test_eof119; +case 119: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr191; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +tr191: +#line 1 "NONE" + {te = p+1;} + goto st120; +st120: + if ( ++p == pe ) + goto _test_eof120; +case 120: +#line 3071 "patchExprScanner.cc" + switch( (*p) ) { + case 46: goto tr68; + case 58: goto st8; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr192; +st8: + if ( ++p == pe ) + goto _test_eof8; +case 8: + if ( (*p) == 58 ) + goto st9; + goto tr9; +st9: + if ( ++p == pe ) + goto _test_eof9; +case 9: + if ( (*p) == 73 ) + goto tr11; + goto tr9; +st121: + if ( ++p == pe ) + goto _test_eof121; +case 121: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st122; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st122: + if ( ++p == pe ) + goto _test_eof122; +case 122: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr195; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st123: + if ( ++p == pe ) + goto _test_eof123; +case 123: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 117: goto st124; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st124: + if ( ++p == pe ) + goto _test_eof124; +case 124: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr197; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st125: + if ( ++p == pe ) + goto _test_eof125; +case 125: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st126; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st126: + if ( ++p == pe ) + goto _test_eof126; +case 126: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st127; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st127: + if ( ++p == pe ) + goto _test_eof127; +case 127: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto st128; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st128: + if ( ++p == pe ) + goto _test_eof128; +case 128: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st129; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st129: + if ( ++p == pe ) + goto _test_eof129; +case 129: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr202; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st130: + if ( ++p == pe ) + goto _test_eof130; +case 130: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st131; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st131: + if ( ++p == pe ) + goto _test_eof131; +case 131: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st132; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st132: + if ( ++p == pe ) + goto _test_eof132; +case 132: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st133; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st133: + if ( ++p == pe ) + goto _test_eof133; +case 133: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto st134; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st134: + if ( ++p == pe ) + goto _test_eof134; +case 134: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto st135; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st135: + if ( ++p == pe ) + goto _test_eof135; +case 135: + switch( (*p) ) { + case 46: goto tr68; + case 65: goto st136; + case 83: goto st142; + case 95: goto tr68; + } + if ( (*p) < 66 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st136: + if ( ++p == pe ) + goto _test_eof136; +case 136: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 118: goto st137; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st137: + if ( ++p == pe ) + goto _test_eof137; +case 137: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st138; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st138: + if ( ++p == pe ) + goto _test_eof138; +case 138: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st139; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st139: + if ( ++p == pe ) + goto _test_eof139; +case 139: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st140; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st140: + if ( ++p == pe ) + goto _test_eof140; +case 140: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st141; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st141: + if ( ++p == pe ) + goto _test_eof141; +case 141: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr215; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st142: + if ( ++p == pe ) + goto _test_eof142; +case 142: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 117: goto st143; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st143: + if ( ++p == pe ) + goto _test_eof143; +case 143: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto tr217; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st10: + if ( ++p == pe ) + goto _test_eof10; +case 10: + if ( (*p) == 124 ) + goto tr12; + goto st0; + } + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof1: cs = 1; goto _test_eof; + _test_eof2: cs = 2; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof3: cs = 3; goto _test_eof; + _test_eof4: cs = 4; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof5: cs = 5; goto _test_eof; + _test_eof6: cs = 6; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; + _test_eof7: cs = 7; goto _test_eof; + _test_eof21: cs = 21; goto _test_eof; + _test_eof22: cs = 22; goto _test_eof; + _test_eof23: cs = 23; goto _test_eof; + _test_eof24: cs = 24; goto _test_eof; + _test_eof25: cs = 25; goto _test_eof; + _test_eof26: cs = 26; goto _test_eof; + _test_eof27: cs = 27; goto _test_eof; + _test_eof28: cs = 28; goto _test_eof; + _test_eof29: cs = 29; goto _test_eof; + _test_eof30: cs = 30; goto _test_eof; + _test_eof31: cs = 31; goto _test_eof; + _test_eof32: cs = 32; goto _test_eof; + _test_eof33: cs = 33; goto _test_eof; + _test_eof34: cs = 34; goto _test_eof; + _test_eof35: cs = 35; goto _test_eof; + _test_eof36: cs = 36; goto _test_eof; + _test_eof37: cs = 37; goto _test_eof; + _test_eof38: cs = 38; goto _test_eof; + _test_eof39: cs = 39; goto _test_eof; + _test_eof40: cs = 40; goto _test_eof; + _test_eof41: cs = 41; goto _test_eof; + _test_eof42: cs = 42; goto _test_eof; + _test_eof43: cs = 43; goto _test_eof; + _test_eof44: cs = 44; goto _test_eof; + _test_eof45: cs = 45; goto _test_eof; + _test_eof46: cs = 46; goto _test_eof; + _test_eof47: cs = 47; goto _test_eof; + _test_eof48: cs = 48; goto _test_eof; + _test_eof49: cs = 49; goto _test_eof; + _test_eof50: cs = 50; goto _test_eof; + _test_eof51: cs = 51; goto _test_eof; + _test_eof52: cs = 52; goto _test_eof; + _test_eof53: cs = 53; goto _test_eof; + _test_eof54: cs = 54; goto _test_eof; + _test_eof55: cs = 55; goto _test_eof; + _test_eof56: cs = 56; goto _test_eof; + _test_eof57: cs = 57; goto _test_eof; + _test_eof58: cs = 58; goto _test_eof; + _test_eof59: cs = 59; goto _test_eof; + _test_eof60: cs = 60; goto _test_eof; + _test_eof61: cs = 61; goto _test_eof; + _test_eof62: cs = 62; goto _test_eof; + _test_eof63: cs = 63; goto _test_eof; + _test_eof64: cs = 64; goto _test_eof; + _test_eof65: cs = 65; goto _test_eof; + _test_eof66: cs = 66; goto _test_eof; + _test_eof67: cs = 67; goto _test_eof; + _test_eof68: cs = 68; goto _test_eof; + _test_eof69: cs = 69; goto _test_eof; + _test_eof70: cs = 70; goto _test_eof; + _test_eof71: cs = 71; goto _test_eof; + _test_eof72: cs = 72; goto _test_eof; + _test_eof73: cs = 73; goto _test_eof; + _test_eof74: cs = 74; goto _test_eof; + _test_eof75: cs = 75; goto _test_eof; + _test_eof76: cs = 76; goto _test_eof; + _test_eof77: cs = 77; goto _test_eof; + _test_eof78: cs = 78; goto _test_eof; + _test_eof79: cs = 79; goto _test_eof; + _test_eof80: cs = 80; goto _test_eof; + _test_eof81: cs = 81; goto _test_eof; + _test_eof82: cs = 82; goto _test_eof; + _test_eof83: cs = 83; goto _test_eof; + _test_eof84: cs = 84; goto _test_eof; + _test_eof85: cs = 85; goto _test_eof; + _test_eof86: cs = 86; goto _test_eof; + _test_eof87: cs = 87; goto _test_eof; + _test_eof88: cs = 88; goto _test_eof; + _test_eof89: cs = 89; goto _test_eof; + _test_eof90: cs = 90; goto _test_eof; + _test_eof91: cs = 91; goto _test_eof; + _test_eof92: cs = 92; goto _test_eof; + _test_eof93: cs = 93; goto _test_eof; + _test_eof94: cs = 94; goto _test_eof; + _test_eof95: cs = 95; goto _test_eof; + _test_eof96: cs = 96; goto _test_eof; + _test_eof97: cs = 97; goto _test_eof; + _test_eof98: cs = 98; goto _test_eof; + _test_eof99: cs = 99; goto _test_eof; + _test_eof100: cs = 100; goto _test_eof; + _test_eof101: cs = 101; goto _test_eof; + _test_eof102: cs = 102; goto _test_eof; + _test_eof103: cs = 103; goto _test_eof; + _test_eof104: cs = 104; goto _test_eof; + _test_eof105: cs = 105; goto _test_eof; + _test_eof106: cs = 106; goto _test_eof; + _test_eof107: cs = 107; goto _test_eof; + _test_eof108: cs = 108; goto _test_eof; + _test_eof109: cs = 109; goto _test_eof; + _test_eof110: cs = 110; goto _test_eof; + _test_eof111: cs = 111; goto _test_eof; + _test_eof112: cs = 112; goto _test_eof; + _test_eof113: cs = 113; goto _test_eof; + _test_eof114: cs = 114; goto _test_eof; + _test_eof115: cs = 115; goto _test_eof; + _test_eof116: cs = 116; goto _test_eof; + _test_eof117: cs = 117; goto _test_eof; + _test_eof118: cs = 118; goto _test_eof; + _test_eof119: cs = 119; goto _test_eof; + _test_eof120: cs = 120; goto _test_eof; + _test_eof8: cs = 8; goto _test_eof; + _test_eof9: cs = 9; goto _test_eof; + _test_eof121: cs = 121; goto _test_eof; + _test_eof122: cs = 122; goto _test_eof; + _test_eof123: cs = 123; goto _test_eof; + _test_eof124: cs = 124; goto _test_eof; + _test_eof125: cs = 125; goto _test_eof; + _test_eof126: cs = 126; goto _test_eof; + _test_eof127: cs = 127; goto _test_eof; + _test_eof128: cs = 128; goto _test_eof; + _test_eof129: cs = 129; goto _test_eof; + _test_eof130: cs = 130; goto _test_eof; + _test_eof131: cs = 131; goto _test_eof; + _test_eof132: cs = 132; goto _test_eof; + _test_eof133: cs = 133; goto _test_eof; + _test_eof134: cs = 134; goto _test_eof; + _test_eof135: cs = 135; goto _test_eof; + _test_eof136: cs = 136; goto _test_eof; + _test_eof137: cs = 137; goto _test_eof; + _test_eof138: cs = 138; goto _test_eof; + _test_eof139: cs = 139; goto _test_eof; + _test_eof140: cs = 140; goto _test_eof; + _test_eof141: cs = 141; goto _test_eof; + _test_eof142: cs = 142; goto _test_eof; + _test_eof143: cs = 143; goto _test_eof; + _test_eof10: cs = 10; goto _test_eof; + + _test_eof: {} + if ( p == eof ) + { + switch ( cs ) { + case 12: goto tr52; + case 13: goto tr53; + case 14: goto tr55; + case 15: goto tr57; + case 16: goto tr60; + case 5: goto tr5; + case 6: goto tr5; + case 17: goto tr60; + case 18: goto tr62; + case 19: goto tr60; + case 20: goto tr63; + case 21: goto tr65; + case 22: goto tr67; + case 23: goto tr69; + case 24: goto tr67; + case 25: goto tr67; + case 26: goto tr67; + case 27: goto tr67; + case 28: goto tr67; + case 29: goto tr67; + case 30: goto tr67; + case 31: goto tr67; + case 32: goto tr67; + case 33: goto tr67; + case 34: goto tr83; + case 35: goto tr67; + case 36: goto tr67; + case 37: goto tr67; + case 38: goto tr67; + case 39: goto tr67; + case 40: goto tr67; + case 41: goto tr67; + case 42: goto tr67; + case 43: goto tr67; + case 44: goto tr67; + case 45: goto tr67; + case 46: goto tr67; + case 47: goto tr98; + case 48: goto tr67; + case 49: goto tr67; + case 50: goto tr67; + case 51: goto tr67; + case 52: goto tr67; + case 53: goto tr67; + case 54: goto tr67; + case 55: goto tr67; + case 56: goto tr67; + case 57: goto tr67; + case 58: goto tr67; + case 59: goto tr67; + case 60: goto tr67; + case 61: goto tr67; + case 62: goto tr67; + case 63: goto tr115; + case 64: goto tr67; + case 65: goto tr67; + case 66: goto tr67; + case 67: goto tr122; + case 68: goto tr67; + case 69: goto tr67; + case 70: goto tr67; + case 71: goto tr67; + case 72: goto tr67; + case 73: goto tr129; + case 74: goto tr67; + case 75: goto tr67; + case 76: goto tr135; + case 77: goto tr67; + case 78: goto tr67; + case 79: goto tr67; + case 80: goto tr67; + case 81: goto tr67; + case 82: goto tr67; + case 83: goto tr67; + case 84: goto tr67; + case 85: goto tr67; + case 86: goto tr67; + case 87: goto tr67; + case 88: goto tr154; + case 89: goto tr67; + case 90: goto tr67; + case 91: goto tr67; + case 92: goto tr67; + case 93: goto tr67; + case 94: goto tr67; + case 95: goto tr67; + case 96: goto tr67; + case 97: goto tr67; + case 98: goto tr67; + case 99: goto tr67; + case 100: goto tr67; + case 101: goto tr67; + case 102: goto tr67; + case 103: goto tr170; + case 104: goto tr67; + case 105: goto tr67; + case 106: goto tr67; + case 107: goto tr67; + case 108: goto tr67; + case 109: goto tr67; + case 110: goto tr67; + case 111: goto tr67; + case 112: goto tr67; + case 113: goto tr67; + case 114: goto tr67; + case 115: goto tr186; + case 116: goto tr67; + case 117: goto tr67; + case 118: goto tr67; + case 119: goto tr67; + case 120: goto tr192; + case 8: goto tr9; + case 9: goto tr9; + case 121: goto tr67; + case 122: goto tr67; + case 123: goto tr67; + case 124: goto tr67; + case 125: goto tr67; + case 126: goto tr67; + case 127: goto tr67; + case 128: goto tr67; + case 129: goto tr67; + case 130: goto tr67; + case 131: goto tr67; + case 132: goto tr67; + case 133: goto tr67; + case 134: goto tr67; + case 135: goto tr67; + case 136: goto tr67; + case 137: goto tr67; + case 138: goto tr67; + case 139: goto tr67; + case 140: goto tr67; + case 141: goto tr67; + case 142: goto tr67; + case 143: goto tr67; + } + } + + _out: {} + } + +#line 641 "patchExprScanner.rl" + /* ^^^ FSM execution here ^^^ */; + + if (0 == 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; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/patch/patchExprScanner.rl b/src/finiteVolume/expressions/patch/patchExprScanner.rl new file mode 100644 index 0000000000000000000000000000000000000000..e26c621c3f0573e4a8de5cc81d14aac718a48910 --- /dev/null +++ b/src/finiteVolume/expressions/patch/patchExprScanner.rl @@ -0,0 +1,664 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + Ragel lexer interface for lemon grammar for patch expressions + +\*---------------------------------------------------------------------------*/ + +#include "patchExprScanner.H" +#include "patchExprDriver.H" +#include "patchExprLemonParser.h" +#include "patchExprParser.H" +#include "Enum.H" +#include "macros.H" + +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Wold-style-cast" + +// Debugging to stderr +#undef DebugInfo +#define DebugInfo if (debug) InfoErr + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + +//- Paste token prefix +#define TOKEN_OF(T) TOK_##T + +//- An {int, c_str} enum pairing +#define TOKEN_PAIR(Name,T) { TOKEN_OF(T), Name } + +#undef HAS_LOOKBEHIND_TOKENS + +// Special handling of predefined method types. Eg, .x(), .y(), ... +static const Enum<int> fieldMethodEnums +({ + TOKEN_PAIR("x", CMPT_X), + TOKEN_PAIR("y", CMPT_Y), + TOKEN_PAIR("z", CMPT_Z), + TOKEN_PAIR("xx", CMPT_XX), + TOKEN_PAIR("xy", CMPT_XY), + TOKEN_PAIR("xz", CMPT_XZ), + TOKEN_PAIR("yx", CMPT_YX), + TOKEN_PAIR("yy", CMPT_YY), + TOKEN_PAIR("yz", CMPT_YZ), + TOKEN_PAIR("zx", CMPT_ZX), + TOKEN_PAIR("zy", CMPT_ZY), + TOKEN_PAIR("zz", CMPT_ZZ), + TOKEN_PAIR("ii", CMPT_II), + TOKEN_PAIR("diag", DIAG), /* tensors only */ + TOKEN_PAIR("T", TRANSPOSE), /* tensors only */ +}); + +// Known field-token types +static const Enum<int> fieldTokenEnums +({ +#ifdef TOK_SCALAR_ID + TOKEN_PAIR(volScalarField::typeName.c_str(), SCALAR_ID), + TOKEN_PAIR(volVectorField::typeName.c_str(), VECTOR_ID), + TOKEN_PAIR(volTensorField::typeName.c_str(), TENSOR_ID), + TOKEN_PAIR(volSymmTensorField::typeName.c_str(), SYM_TENSOR_ID), + TOKEN_PAIR(volSphericalTensorField::typeName.c_str(), SPH_TENSOR_ID), +#else +#error TOK_SCALAR_ID not defined +#endif +#ifdef TOK_SSCALAR_ID + TOKEN_PAIR(surfaceScalarField::typeName.c_str(), SSCALAR_ID), + TOKEN_PAIR(surfaceVectorField::typeName.c_str(), SVECTOR_ID), + TOKEN_PAIR(surfaceTensorField::typeName.c_str(), STENSOR_ID), + TOKEN_PAIR(surfaceSymmTensorField::typeName.c_str(), SSYM_TENSOR_ID), + TOKEN_PAIR(surfaceSphericalTensorField::typeName.c_str(), SSPH_TENSOR_ID), +#else +#error TOK_SSCALAR_ID not defined +#endif +#ifdef TOK_PSCALAR_ID + TOKEN_PAIR(pointScalarField::typeName.c_str(), PSCALAR_ID), + TOKEN_PAIR(pointVectorField::typeName.c_str(), PVECTOR_ID), + TOKEN_PAIR(pointTensorField::typeName.c_str(), PTENSOR_ID), + TOKEN_PAIR(pointSymmTensorField::typeName.c_str(), PSYM_TENSOR_ID), + TOKEN_PAIR(pointSphericalTensorField::typeName.c_str(), PSPH_TENSOR_ID), +#else +#warning TOK_PSCALAR_ID not defined +#endif +}); + + +// Simple compile-time function name declarations. +// Useful for handling driver-specific dispatching, or functions that +// are not universally available. +static const Enum<int> funcTokenEnums +({ +#ifdef TOK_FLOOR + TOKEN_PAIR("floor", FLOOR), + TOKEN_PAIR("ceil", CEIL), + TOKEN_PAIR("round", ROUND), +#endif +#ifdef TOK_HYPOT /* Can use hypot? */ + TOKEN_PAIR("hypot", HYPOT), +#endif + + // Already parsed as function: TOKEN_PAIR("pos", FACE_CENTRE), + + TOKEN_PAIR("point", POINT_EXPR), // Point value + TOKEN_PAIR("face", FACE_EXPR), // Face areaNormal + + TOKEN_PAIR("faceToPoint", FACE_TO_POINT), + TOKEN_PAIR("pointToFace", POINT_TO_FACE), + + TOKEN_PAIR("area", FACE_AREA), + TOKEN_PAIR("pts", POINTS), +}); + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Classifying token type based on an identifier name is indeed ugly. +// +// 1) +// Handle special cases (eg, cellSet,...) first that have been tagged +// as expected content with the stashed "look-behind" token. +// Handle not-found errors here directly. +// +// 2) +// Fallback to determining which field-type (volScalarField etc) the name +// corresponds to. +// Handle not-found errors by return -1. +// +static int driverTokenType +( + const expressions::patchExpr::parseDriver& driver_, + const word& ident +) +{ +#if 0 + // Get stashed "look-behind" to decide what type of identifier we expect + const int lookBehind = driver_.resetStashedTokenId(); + + if (lookBehind && lookBehindTokenEnums.found(lookBehind)) + { + bool good = false; + + switch (lookBehind) + { + case TOK_CSET : good = driver_.isCellSet(ident); break; + case TOK_FSET : good = driver_.isFaceSet(ident); break; + case TOK_PSET : good = driver_.isPointSet(ident); break; + case TOK_CZONE : good = driver_.isCellZone(ident); break; + case TOK_FZONE : good = driver_.isFaceZone(ident); break; + case TOK_PZONE : good = driver_.isPointZone(ident); break; + } + + if (good) + { + return TOK_IDENTIFIER; + } + + // Fatal + driver_.reportFatal + ( + "Error no " + lookBehindTokenEnums.get(lookBehind) + ": " + ident + ); + + return -2; // Extra safety + } +#endif + + // Face variables + #ifdef TOK_SSCALAR_ID + { + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable<Type>(ident, false)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_SSCALAR_ID, scalar); + checkFieldToken(TOK_SVECTOR_ID, vector); + checkFieldToken(TOK_SSYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_SSPH_TENSOR_ID, sphericalTensor); + checkFieldToken(TOK_STENSOR_ID, tensor); + + // Not tested: checkFieldToken(TOK_SBOOL_ID, bool); + } + #endif + + // Point variables + #ifdef TOK_PSCALAR_ID + { + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable<Type>(ident, true)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_PSCALAR_ID, scalar); + checkFieldToken(TOK_PVECTOR_ID, vector); + checkFieldToken(TOK_PTENSOR_ID, tensor); + checkFieldToken(TOK_PTENSOR_ID, tensor); + checkFieldToken(TOK_PSYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_PSPH_TENSOR_ID, sphericalTensor); + + // Not tested: checkFieldToken(TOK_PBOOL_ID, bool); + } + #endif + + #undef checkFieldToken + + // Check registered fields and/or disk-files + { + const word fieldType(driver_.getFieldClassName(ident)); + + int tokType = fieldTokenEnums.get(fieldType, -1); + + if (tokType > 0) + { + return tokType; + } + } + + return -1; +} + +} // End anonymous namespace + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// Ragel machine definition +// Ragel variables (p, pe, eof, cs, top, stack, ts, te, act) defined later... +// +// Can use 'variable p xxx;' etc to change these names + +#define EMIT_TOKEN(T) \ + driver_.parsePosition() = (ts-buf); \ + DebugInfo<< STRINGIFY(T) << ": " << driver_.parsePosition() << nl; \ + parser_->parse(TOKEN_OF(T), nullptr); \ + driver_.parsePosition() = (p-buf); + + +%%{ + machine patchExpr; + write data; + + action emit_number { + driver_.parsePosition() = (ts-buf); + + DebugInfo + << "Number:" << std::string(ts, te-ts).c_str() + << " at " << driver_.parsePosition() << nl; + + if (readScalar(std::string(ts, te-ts), scanTok.svalue)) + { + parser_->parse(TOKEN_OF(NUMBER), &scanTok); + } + else + { + driver_.reportFatal + ( + "Error parsing number: " + std::string(ts, te-ts) + ); + } + + driver_.parsePosition() = (p-buf); + } + + action emit_ident { + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + } + + action emit_method { + // Tokenized ".method" - dispatch '.' and "method" separately + driver_.parsePosition() = (ts-buf); + dispatch_method(driver_, scanTok, word(ts+1, te-ts-1, false)); + driver_.parsePosition() = (p-buf); + } + + decimal = ((digit* '.' digit+) | (digit+ '.'?)) ; + number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ; + ident = ((alpha|'_') . ((alnum|[._])**)) ; + dquoted = '"' [^\"]+ '"' ; + squoted = "'" [^\']+ "'" ; + + + ## The scanner + main := |* + space*; + + number => emit_number; + + ## operators + '!' =>{ EMIT_TOKEN(NOT); }; + '%' =>{ EMIT_TOKEN(PERCENT); }; + '(' =>{ EMIT_TOKEN(LPAREN); }; + ')' =>{ EMIT_TOKEN(RPAREN); }; + '*' =>{ EMIT_TOKEN(TIMES); }; + '+' =>{ EMIT_TOKEN(PLUS); }; + '-' =>{ EMIT_TOKEN(MINUS); }; + ',' =>{ EMIT_TOKEN(COMMA); }; + '.' =>{ EMIT_TOKEN(DOT); }; + '/' =>{ EMIT_TOKEN(DIVIDE); }; + '?' =>{ EMIT_TOKEN(QUESTION); }; + ':' =>{ EMIT_TOKEN(COLON); }; + '<' =>{ EMIT_TOKEN(LESS); }; + '<=' =>{ EMIT_TOKEN(LESS_EQ); }; + '>' =>{ EMIT_TOKEN(GREATER); }; + '>=' =>{ EMIT_TOKEN(GREATER_EQ); }; + '==' =>{ EMIT_TOKEN(EQUAL); }; + '!=' =>{ EMIT_TOKEN(NOT_EQUAL); }; + '&&' =>{ EMIT_TOKEN(LAND); }; + '||' =>{ EMIT_TOKEN(LOR); }; + '&' =>{ EMIT_TOKEN(BIT_AND); }; +## Not needed? '|' =>{ EMIT_TOKEN(BIT_OK); }; + '^' =>{ EMIT_TOKEN(BIT_XOR); }; + + ## Some '.method' - Error if unknown + '.' alpha+ => emit_method; + + + ## Regular functions + "pi" =>{ EMIT_TOKEN(PI); }; + "degToRad" =>{ EMIT_TOKEN(DEG_TO_RAD); }; + "radToDeg" =>{ EMIT_TOKEN(RAD_TO_DEG); }; + "exp" =>{ EMIT_TOKEN(EXP); }; + "log" =>{ EMIT_TOKEN(LOG); }; + "log10" =>{ EMIT_TOKEN(LOG10); }; + "pow" =>{ EMIT_TOKEN(POW); }; + "sqr" =>{ EMIT_TOKEN(SQR); }; + "sqrt" =>{ EMIT_TOKEN(SQRT); }; + "cbrt" =>{ EMIT_TOKEN(CBRT); }; + "sin" =>{ EMIT_TOKEN(SIN); }; + "cos" =>{ EMIT_TOKEN(COS); }; + "tan" =>{ EMIT_TOKEN(TAN); }; + "asin" =>{ EMIT_TOKEN(ASIN); }; + "acos" =>{ EMIT_TOKEN(ACOS); }; + "atan" =>{ EMIT_TOKEN(ATAN); }; + "atan2" =>{ EMIT_TOKEN(ATAN2); }; + "sinh" =>{ EMIT_TOKEN(SINH); }; + "cosh" =>{ EMIT_TOKEN(COSH); }; + "tanh" =>{ EMIT_TOKEN(TANH); }; + "mag" =>{ EMIT_TOKEN(MAG); }; + "magSqr" =>{ EMIT_TOKEN(MAGSQR); }; + + "pos" =>{ EMIT_TOKEN(POS); }; + "neg" =>{ EMIT_TOKEN(NEG); }; + "pos0" =>{ EMIT_TOKEN(POS0); }; + "neg0" =>{ EMIT_TOKEN(NEG0); }; + "sign" =>{ EMIT_TOKEN(SIGN); }; + + ## Reductions, or other special functions + "min" =>{ EMIT_TOKEN(MIN); }; + "max" =>{ EMIT_TOKEN(MAX); }; + "average" =>{ EMIT_TOKEN(AVERAGE); }; + "sum" =>{ EMIT_TOKEN(SUM); }; + "weightAverage" =>{ EMIT_TOKEN(WEIGHT_AVERAGE); }; + "weightSum" =>{ EMIT_TOKEN(WEIGHT_SUM); }; + "rand" =>{ EMIT_TOKEN(RAND); }; + + ## Types + "bool" =>{ EMIT_TOKEN(BOOL); }; + "vector" =>{ EMIT_TOKEN(VECTOR); }; + "tensor" =>{ EMIT_TOKEN(TENSOR); }; + "symmTensor" =>{ EMIT_TOKEN(SYM_TENSOR); }; + "sphericalTensor" =>{ EMIT_TOKEN(SPH_TENSOR); }; + + ## Single value (constants, etc) + "Zero" =>{ EMIT_TOKEN(ZERO); }; + "true" =>{ EMIT_TOKEN(LTRUE); }; + "false" =>{ EMIT_TOKEN(LFALSE); }; + "tensor::I" =>{ EMIT_TOKEN(UNIT_TENSOR); }; + "time" =>{ EMIT_TOKEN(TIME); }; + + ## Identifier (field, etc - error if unknown) + ## Handle 'bare' names and single/double quoted ones + ident => emit_ident; + dquoted => emit_ident; + squoted => emit_ident; + + space*; + *|; +}%% + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::expressions::patchExpr::scanner::~scanner() +{ + if (parser_) + { + delete parser_; + } +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +bool Foam::expressions::patchExpr::scanner::dispatch_method +( + const parseDriver& driver_, + scanToken& scanTok, + word&& ident +) const +{ + if (ident[0] == '.') + { + ident.erase(0, 1); + } + + DebugInfo + << "Method:" << ident + << " at " << driver_.parsePosition() << nl; + + const int methType = fieldMethodEnums.get(ident, -1); + + if (methType > 0) + { + // Dispatch '.' and "method" separately + parser_->parse(TOK_DOT, nullptr); + parser_->parse(methType, nullptr); + + return true; + } + + driver_.reportFatal("Unknown method: " + ident); + return false; +} + + +bool Foam::expressions::patchExpr::scanner::dispatch_ident +( + const parseDriver& driver_, + scanToken& scanTok, + word&& ident +) const +{ + int tokType = -1; + + const bool quoted = + ( + (ident.front() == '"' || ident.front() == '\'') + && (ident.front() == ident.back()) + ); + + if (quoted) + { + ident.erase(ident.size()-1); + ident.erase(0, 1); + } + else + { + // Check for function name + tokType = funcTokenEnums.get(ident, -1); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " function:" + << parser_->nameOfToken(tokType) << nl; + + parser_->parse(tokType, nullptr); + return true; + } + + #ifdef HAS_LOOKBEHIND_TOKENS + // Specials such "cset" also reset the look-behind + tokType = lookBehindTokenEnums.get(ident, -1); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " as look-behind:" + << parser_->nameOfToken(tokType) << nl; + + driver_.resetStashedTokenId(tokType); + parser_->parse(tokType, nullptr); + return true; + } + #endif + } + + + // Can also peek at stashed "look-behind" + // const int lookBehind = driver_.stashedTokenId(); + + tokType = driverTokenType(driver_, ident); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " token:" + << parser_->nameOfToken(tokType) << nl; + + scanTok.name = new Foam::word(std::move(ident)); + parser_->parse(tokType, &scanTok); + + return true; + } + + + // Not found? Attempt to strip off '.x' endings etc, + // but not when quoted + + const auto dot = ident.rfind('.'); + const int methType = + ( + quoted || dot == std::string::npos + ? -1 + : fieldMethodEnums.get(ident.substr(dot+1), -1) + ); + + if + ( + methType > 0 + && (tokType = driverTokenType(driver_, ident.substr(0, dot))) > 0 + ) + { + DebugInfo + << "Emit:" << ident.substr(0, dot).c_str() << " token:" + << parser_->nameOfToken(tokType) << " with " + << ident.substr(dot).c_str() << " token:" + << parser_->nameOfToken(methType) << nl; + + // The field (before the ".") + ident.erase(dot); + + scanTok.name = new Foam::word(std::move(ident)); + parser_->parse(tokType, &scanTok); + + // Dispatch '.' and "method" separately + parser_->parse(TOK_DOT, nullptr); + parser_->parse(methType, nullptr); + + return true; + } + + driver_.reportFatal + ( + "Object " + ident + " does not exist or wrong type" + ); + + return false; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::expressions::patchExpr::scanner::process +( + const std::string& str, + size_t strBeg, + size_t strLen, + parseDriver& driver_ +) +{ + // Save debug value + const int oldDebug = debug; + + if (driver_.debugScanner()) + { + debug |= 4; + } + + if (!parser_) + { + parser_ = new parser(); + } + + driver_.content(str, strBeg, strLen); + + size_t strEnd = str.length(); + + if (strBeg > str.length()) + { + strBeg = str.length(); + } + else if (strLen != std::string::npos) + { + strLen += strBeg; + + if (strLen < str.length()) + { + strEnd = strLen; + } + } + + + parser_->start(driver_); + + // Scan token type + scanToken scanTok; + + // Ragel token start/end (required naming) + const char* ts; + const char* te; + + // Local buffer data. + // - p, pe, eof are required Ragel naming + // - buf is our own naming + + const char* buf = &(str[strBeg]); + const char* eof = &(str[strEnd]); + const char* p = buf; + const char* pe = eof; + + // Initialize FSM variables + %%{write init;}%% /* ^^^ FSM initialization here ^^^ */; + + %%{write exec;}%% /* ^^^ FSM execution here ^^^ */; + + if (%%{write error;}%% == cs) + { + driver_.reportFatal("Parse error while scanning", (p-buf)); + } + + if (p != eof) + { + driver_.reportFatal("Parsing failed with remaining content", (p-buf)); + } + + // Terminate parser execution + parser_->parse(0, nullptr); + parser_->stop(); + + // Restore debug value + debug = oldDebug; + + return true; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/createCode b/src/finiteVolume/expressions/volume/createCode new file mode 100755 index 0000000000000000000000000000000000000000..30d5e5902c024d04cf5ce08c8f46309e3a963659 --- /dev/null +++ b/src/finiteVolume/expressions/volume/createCode @@ -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 \ + "$@" + +#------------------------------------------------------------------------------ diff --git a/src/finiteVolume/expressions/volume/volumeExpr.C b/src/finiteVolume/expressions/volume/volumeExpr.C new file mode 100644 index 0000000000000000000000000000000000000000..8859f6deb56a0fcaddebdc8883f99537cac04436 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExpr.C @@ -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 + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriver.C b/src/finiteVolume/expressions/volume/volumeExprDriver.C new file mode 100644 index 0000000000000000000000000000000000000000..8cb2c5002ec94ddaf83bddbe29ba91274501fd2d --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriver.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriver.H b/src/finiteVolume/expressions/volume/volumeExprDriver.H new file mode 100644 index 0000000000000000000000000000000000000000..0ddb6a2104e5d056ecd9f0c6e174d20f0954d026 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriver.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriverFields.C b/src/finiteVolume/expressions/volume/volumeExprDriverFields.C new file mode 100644 index 0000000000000000000000000000000000000000..efc3457e091d0ea7c75bf12a0e492411251df803 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriverFields.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriverI.H b/src/finiteVolume/expressions/volume/volumeExprDriverI.H new file mode 100644 index 0000000000000000000000000000000000000000..2863f0ba1e8b900bb5dc0c425a1ace255932231a --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriverI.H @@ -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 + ); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriverTemplates.C b/src/finiteVolume/expressions/volume/volumeExprDriverTemplates.C new file mode 100644 index 0000000000000000000000000000000000000000..3ffdb5b0b155a5fe24fe1e4de5fe8e53f7b211de --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriverTemplates.C @@ -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; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprFwd.H b/src/finiteVolume/expressions/volume/volumeExprFwd.H new file mode 100644 index 0000000000000000000000000000000000000000..1a5df406c4bb7c02c2634980a815796d8cf581a4 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprFwd.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprLemonParser.h b/src/finiteVolume/expressions/volume/volumeExprLemonParser.h new file mode 100644 index 0000000000000000000000000000000000000000..2cca6cd8082bb5e0c70b23a4967b85c74db2dd1c --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprLemonParser.h @@ -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 diff --git a/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 b/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 new file mode 100644 index 0000000000000000000000000000000000000000..cc7ae238b5d990c150b05318efeaf3cd08a4d670 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprLemonParserMacros.m4 b/src/finiteVolume/expressions/volume/volumeExprLemonParserMacros.m4 new file mode 100644 index 0000000000000000000000000000000000000000..a0df5c6314cfc6fbaab7bfc8ddc6fc31d642d9ef --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprLemonParserMacros.m4 @@ -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 diff --git a/src/finiteVolume/expressions/volume/volumeExprParser.H b/src/finiteVolume/expressions/volume/volumeExprParser.H new file mode 100644 index 0000000000000000000000000000000000000000..7664d10b4e6d89d39006a9561bcc7b6c284cc302 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprParser.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprScanner.H b/src/finiteVolume/expressions/volume/volumeExprScanner.H new file mode 100644 index 0000000000000000000000000000000000000000..b432a602fbe9860d864b18b57a99a512956b27f6 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprScanner.H @@ -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 + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprScanner.cc b/src/finiteVolume/expressions/volume/volumeExprScanner.cc new file mode 100644 index 0000000000000000000000000000000000000000..c83ed2be6303a5bcac2ce8726601083c93ad3cd9 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprScanner.cc @@ -0,0 +1,3866 @@ + +#line 1 "volumeExprScanner.rl" +/*--------------------------------*- 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); + + + +#line 306 "volumeExprScanner.cc" +static const int volumeExpr_start = 11; +static const int volumeExpr_first_final = 11; +static const int volumeExpr_error = 0; + +static const int volumeExpr_en_main = 11; + + +#line 444 "volumeExprScanner.rl" + + + +// * * * * * * * * * * * * * * * * 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 + +#line 541 "volumeExprScanner.cc" + { + cs = volumeExpr_start; + ts = 0; + te = 0; + act = 0; + } + +#line 669 "volumeExprScanner.rl" + /* ^^^ FSM initialization here ^^^ */; + + +#line 553 "volumeExprScanner.cc" + { + if ( p == pe ) + goto _test_eof; + switch ( cs ) + { +tr2: +#line 328 "volumeExprScanner.rl" + {te = p+1;{ + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + }} + goto st11; +tr4: +#line 328 "volumeExprScanner.rl" + {te = p+1;{ + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + }} + goto st11; +tr5: +#line 306 "volumeExprScanner.rl" + {{p = ((te))-1;}{ + 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); + }} + goto st11; +tr8: +#line 371 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(EQUAL); }} + goto st11; +tr9: +#line 425 "volumeExprScanner.rl" + {{p = ((te))-1;}{ EMIT_TOKEN(TENSOR); }} + goto st11; +tr11: +#line 433 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(UNIT_TENSOR); }} + goto st11; +tr12: +#line 374 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LOR); }} + goto st11; +tr16: +#line 356 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(PERCENT); }} + goto st11; +tr19: +#line 357 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LPAREN); }} + goto st11; +tr20: +#line 358 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(RPAREN); }} + goto st11; +tr21: +#line 359 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(TIMES); }} + goto st11; +tr22: +#line 360 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(PLUS); }} + goto st11; +tr23: +#line 362 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(COMMA); }} + goto st11; +tr24: +#line 361 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(MINUS); }} + goto st11; +tr26: +#line 364 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(DIVIDE); }} + goto st11; +tr28: +#line 366 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(COLON); }} + goto st11; +tr32: +#line 365 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(QUESTION); }} + goto st11; +tr35: +#line 377 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(BIT_XOR); }} + goto st11; +tr52: +#line 350 "volumeExprScanner.rl" + {te = p;p--;} + goto st11; +tr53: +#line 355 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(NOT); }} + goto st11; +tr54: +#line 372 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(NOT_EQUAL); }} + goto st11; +tr55: +#line 375 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(BIT_AND); }} + goto st11; +tr56: +#line 373 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LAND); }} + goto st11; +tr57: +#line 363 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(DOT); }} + goto st11; +tr60: +#line 306 "volumeExprScanner.rl" + {te = p;p--;{ + 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); + }} + goto st11; +tr62: +#line 334 "volumeExprScanner.rl" + {te = p;p--;{ + // 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); + }} + goto st11; +tr63: +#line 367 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(LESS); }} + goto st11; +tr64: +#line 368 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LESS_EQ); }} + goto st11; +tr65: +#line 369 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(GREATER); }} + goto st11; +tr66: +#line 370 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(GREATER_EQ); }} + goto st11; +tr67: +#line 328 "volumeExprScanner.rl" + {te = p;p--;{ + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + }} + goto st11; +tr69: +#line 1 "NONE" + { switch( act ) { + case 26: + {{p = ((te))-1;} EMIT_TOKEN(PI); } + break; + case 27: + {{p = ((te))-1;} EMIT_TOKEN(DEG_TO_RAD); } + break; + case 28: + {{p = ((te))-1;} EMIT_TOKEN(RAD_TO_DEG); } + break; + case 29: + {{p = ((te))-1;} EMIT_TOKEN(EXP); } + break; + case 31: + {{p = ((te))-1;} EMIT_TOKEN(LOG10); } + break; + case 32: + {{p = ((te))-1;} EMIT_TOKEN(POW); } + break; + case 34: + {{p = ((te))-1;} EMIT_TOKEN(SQRT); } + break; + case 35: + {{p = ((te))-1;} EMIT_TOKEN(CBRT); } + break; + case 39: + {{p = ((te))-1;} EMIT_TOKEN(ASIN); } + break; + case 40: + {{p = ((te))-1;} EMIT_TOKEN(ACOS); } + break; + case 42: + {{p = ((te))-1;} EMIT_TOKEN(ATAN2); } + break; + case 43: + {{p = ((te))-1;} EMIT_TOKEN(SINH); } + break; + case 44: + {{p = ((te))-1;} EMIT_TOKEN(COSH); } + break; + case 45: + {{p = ((te))-1;} EMIT_TOKEN(TANH); } + break; + case 47: + {{p = ((te))-1;} EMIT_TOKEN(MAGSQR); } + break; + case 50: + {{p = ((te))-1;} EMIT_TOKEN(POS0); } + break; + case 51: + {{p = ((te))-1;} EMIT_TOKEN(NEG0); } + break; + case 52: + {{p = ((te))-1;} EMIT_TOKEN(SIGN); } + break; + case 53: + {{p = ((te))-1;} EMIT_TOKEN(MIN); } + break; + case 54: + {{p = ((te))-1;} EMIT_TOKEN(MAX); } + break; + case 55: + {{p = ((te))-1;} EMIT_TOKEN(AVERAGE); } + break; + case 56: + {{p = ((te))-1;} EMIT_TOKEN(SUM); } + break; + case 57: + {{p = ((te))-1;} EMIT_TOKEN(WEIGHT_AVERAGE); } + break; + case 58: + {{p = ((te))-1;} EMIT_TOKEN(WEIGHT_SUM); } + break; + case 59: + {{p = ((te))-1;} EMIT_TOKEN(RAND); } + break; + case 60: + {{p = ((te))-1;} EMIT_TOKEN(BOOL); } + break; + case 61: + {{p = ((te))-1;} EMIT_TOKEN(VECTOR); } + break; + case 63: + {{p = ((te))-1;} EMIT_TOKEN(SYM_TENSOR); } + break; + case 64: + {{p = ((te))-1;} EMIT_TOKEN(SPH_TENSOR); } + break; + case 65: + {{p = ((te))-1;} EMIT_TOKEN(ZERO); } + break; + case 66: + {{p = ((te))-1;} EMIT_TOKEN(LTRUE); } + break; + case 67: + {{p = ((te))-1;} EMIT_TOKEN(LFALSE); } + break; + case 69: + {{p = ((te))-1;} EMIT_TOKEN(TIME); } + break; + case 70: + {{p = ((te))-1;} + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + } + break; + } + } + goto st11; +tr83: +#line 399 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(ATAN); }} + goto st11; +tr98: +#line 395 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(COS); }} + goto st11; +tr115: +#line 388 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(LOG); }} + goto st11; +tr122: +#line 404 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(MAG); }} + goto st11; +tr129: +#line 408 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(NEG); }} + goto st11; +tr135: +#line 407 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(POS); }} + goto st11; +tr154: +#line 394 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(SIN); }} + goto st11; +tr170: +#line 391 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(SQR); }} + goto st11; +tr186: +#line 396 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(TAN); }} + goto st11; +tr192: +#line 425 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(TENSOR); }} + goto st11; +st11: +#line 1 "NONE" + {ts = 0;} + if ( ++p == pe ) + goto _test_eof11; +case 11: +#line 1 "NONE" + {ts = p;} +#line 900 "volumeExprScanner.cc" + switch( (*p) ) { + case 32: goto st12; + case 33: goto st13; + case 34: goto st1; + case 37: goto tr16; + case 38: goto st14; + case 39: goto st3; + case 40: goto tr19; + case 41: goto tr20; + case 42: goto tr21; + case 43: goto tr22; + case 44: goto tr23; + case 45: goto tr24; + case 46: goto st15; + case 47: goto tr26; + case 58: goto tr28; + case 60: goto st20; + case 61: goto st7; + case 62: goto st21; + case 63: goto tr32; + case 90: goto st24; + case 94: goto tr35; + case 95: goto st22; + case 97: goto st27; + case 98: goto st40; + case 99: goto st43; + case 100: goto st48; + case 101: goto st55; + case 102: goto st57; + case 108: goto st61; + case 109: goto st65; + case 110: goto st71; + case 112: goto st74; + case 114: goto st77; + case 115: goto st85; + case 116: goto st113; + case 118: goto st125; + case 119: goto st130; + case 124: goto st10; + } + if ( (*p) < 48 ) { + if ( 9 <= (*p) && (*p) <= 13 ) + goto st12; + } else if ( (*p) > 57 ) { + if ( (*p) > 89 ) { + if ( 103 <= (*p) && (*p) <= 122 ) + goto st22; + } else if ( (*p) >= 65 ) + goto st22; + } else + goto tr27; + goto st0; +st0: +cs = 0; + goto _out; +st12: + if ( ++p == pe ) + goto _test_eof12; +case 12: + if ( (*p) == 32 ) + goto st12; + if ( 9 <= (*p) && (*p) <= 13 ) + goto st12; + goto tr52; +st13: + if ( ++p == pe ) + goto _test_eof13; +case 13: + if ( (*p) == 61 ) + goto tr54; + goto tr53; +st1: + if ( ++p == pe ) + goto _test_eof1; +case 1: + if ( (*p) == 34 ) + goto st0; + goto st2; +st2: + if ( ++p == pe ) + goto _test_eof2; +case 2: + if ( (*p) == 34 ) + goto tr2; + goto st2; +st14: + if ( ++p == pe ) + goto _test_eof14; +case 14: + if ( (*p) == 38 ) + goto tr56; + goto tr55; +st3: + if ( ++p == pe ) + goto _test_eof3; +case 3: + if ( (*p) == 39 ) + goto st0; + goto st4; +st4: + if ( ++p == pe ) + goto _test_eof4; +case 4: + if ( (*p) == 39 ) + goto tr4; + goto st4; +st15: + if ( ++p == pe ) + goto _test_eof15; +case 15: + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr58; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st18; + } else + goto st18; + goto tr57; +tr58: +#line 1 "NONE" + {te = p+1;} + goto st16; +st16: + if ( ++p == pe ) + goto _test_eof16; +case 16: +#line 1028 "volumeExprScanner.cc" + switch( (*p) ) { + case 69: goto st5; + case 101: goto st5; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr58; + goto tr60; +st5: + if ( ++p == pe ) + goto _test_eof5; +case 5: + switch( (*p) ) { + case 43: goto st6; + case 45: goto st6; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto st17; + goto tr5; +st6: + if ( ++p == pe ) + goto _test_eof6; +case 6: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st17; + goto tr5; +st17: + if ( ++p == pe ) + goto _test_eof17; +case 17: + if ( 48 <= (*p) && (*p) <= 57 ) + goto st17; + goto tr60; +st18: + if ( ++p == pe ) + goto _test_eof18; +case 18: + if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st18; + } else if ( (*p) >= 65 ) + goto st18; + goto tr62; +tr27: +#line 1 "NONE" + {te = p+1;} + goto st19; +st19: + if ( ++p == pe ) + goto _test_eof19; +case 19: +#line 1079 "volumeExprScanner.cc" + switch( (*p) ) { + case 46: goto tr58; + case 69: goto st5; + case 101: goto st5; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr27; + goto tr60; +st20: + if ( ++p == pe ) + goto _test_eof20; +case 20: + if ( (*p) == 61 ) + goto tr64; + goto tr63; +st7: + if ( ++p == pe ) + goto _test_eof7; +case 7: + if ( (*p) == 61 ) + goto tr8; + goto st0; +st21: + if ( ++p == pe ) + goto _test_eof21; +case 21: + if ( (*p) == 61 ) + goto tr66; + goto tr65; +st22: + if ( ++p == pe ) + goto _test_eof22; +case 22: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +tr68: +#line 1 "NONE" + {te = p+1;} +#line 328 "volumeExprScanner.rl" + {act = 70;} + goto st23; +tr72: +#line 1 "NONE" + {te = p+1;} +#line 430 "volumeExprScanner.rl" + {act = 65;} + goto st23; +tr78: +#line 1 "NONE" + {te = p+1;} +#line 398 "volumeExprScanner.rl" + {act = 40;} + goto st23; +tr80: +#line 1 "NONE" + {te = p+1;} +#line 397 "volumeExprScanner.rl" + {act = 39;} + goto st23; +tr84: +#line 1 "NONE" + {te = p+1;} +#line 400 "volumeExprScanner.rl" + {act = 42;} + goto st23; +tr89: +#line 1 "NONE" + {te = p+1;} +#line 416 "volumeExprScanner.rl" + {act = 55;} + goto st23; +tr92: +#line 1 "NONE" + {te = p+1;} +#line 423 "volumeExprScanner.rl" + {act = 60;} + goto st23; +tr96: +#line 1 "NONE" + {te = p+1;} +#line 393 "volumeExprScanner.rl" + {act = 35;} + goto st23; +tr99: +#line 1 "NONE" + {te = p+1;} +#line 402 "volumeExprScanner.rl" + {act = 44;} + goto st23; +tr106: +#line 1 "NONE" + {te = p+1;} +#line 385 "volumeExprScanner.rl" + {act = 27;} + goto st23; +tr108: +#line 1 "NONE" + {te = p+1;} +#line 387 "volumeExprScanner.rl" + {act = 29;} + goto st23; +tr112: +#line 1 "NONE" + {te = p+1;} +#line 432 "volumeExprScanner.rl" + {act = 67;} + goto st23; +tr117: +#line 1 "NONE" + {te = p+1;} +#line 389 "volumeExprScanner.rl" + {act = 31;} + goto st23; +tr121: +#line 1 "NONE" + {te = p+1;} +#line 415 "volumeExprScanner.rl" + {act = 54;} + goto st23; +tr125: +#line 1 "NONE" + {te = p+1;} +#line 405 "volumeExprScanner.rl" + {act = 47;} + goto st23; +tr126: +#line 1 "NONE" + {te = p+1;} +#line 414 "volumeExprScanner.rl" + {act = 53;} + goto st23; +tr130: +#line 1 "NONE" + {te = p+1;} +#line 410 "volumeExprScanner.rl" + {act = 51;} + goto st23; +tr131: +#line 1 "NONE" + {te = p+1;} +#line 384 "volumeExprScanner.rl" + {act = 26;} + goto st23; +tr134: +#line 1 "NONE" + {te = p+1;} +#line 390 "volumeExprScanner.rl" + {act = 32;} + goto st23; +tr136: +#line 1 "NONE" + {te = p+1;} +#line 409 "volumeExprScanner.rl" + {act = 50;} + goto st23; +tr144: +#line 1 "NONE" + {te = p+1;} +#line 386 "volumeExprScanner.rl" + {act = 28;} + goto st23; +tr145: +#line 1 "NONE" + {te = p+1;} +#line 420 "volumeExprScanner.rl" + {act = 59;} + goto st23; +tr153: +#line 1 "NONE" + {te = p+1;} +#line 411 "volumeExprScanner.rl" + {act = 52;} + goto st23; +tr155: +#line 1 "NONE" + {te = p+1;} +#line 401 "volumeExprScanner.rl" + {act = 43;} + goto st23; +tr168: +#line 1 "NONE" + {te = p+1;} +#line 427 "volumeExprScanner.rl" + {act = 64;} + goto st23; +tr171: +#line 1 "NONE" + {te = p+1;} +#line 392 "volumeExprScanner.rl" + {act = 34;} + goto st23; +tr172: +#line 1 "NONE" + {te = p+1;} +#line 417 "volumeExprScanner.rl" + {act = 56;} + goto st23; +tr180: +#line 1 "NONE" + {te = p+1;} +#line 426 "volumeExprScanner.rl" + {act = 63;} + goto st23; +tr187: +#line 1 "NONE" + {te = p+1;} +#line 403 "volumeExprScanner.rl" + {act = 45;} + goto st23; +tr195: +#line 1 "NONE" + {te = p+1;} +#line 434 "volumeExprScanner.rl" + {act = 69;} + goto st23; +tr197: +#line 1 "NONE" + {te = p+1;} +#line 431 "volumeExprScanner.rl" + {act = 66;} + goto st23; +tr202: +#line 1 "NONE" + {te = p+1;} +#line 424 "volumeExprScanner.rl" + {act = 61;} + goto st23; +tr215: +#line 1 "NONE" + {te = p+1;} +#line 418 "volumeExprScanner.rl" + {act = 57;} + goto st23; +tr217: +#line 1 "NONE" + {te = p+1;} +#line 419 "volumeExprScanner.rl" + {act = 58;} + goto st23; +st23: + if ( ++p == pe ) + goto _test_eof23; +case 23: +#line 1334 "volumeExprScanner.cc" + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr69; +st24: + if ( ++p == pe ) + goto _test_eof24; +case 24: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st25; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st25: + if ( ++p == pe ) + goto _test_eof25; +case 25: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st26; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st26: + if ( ++p == pe ) + goto _test_eof26; +case 26: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto tr72; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st27: + if ( ++p == pe ) + goto _test_eof27; +case 27: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st28; + case 115: goto st30; + case 116: goto st32; + case 118: goto st35; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st28: + if ( ++p == pe ) + goto _test_eof28; +case 28: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st29; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st29: + if ( ++p == pe ) + goto _test_eof29; +case 29: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto tr78; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st30: + if ( ++p == pe ) + goto _test_eof30; +case 30: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st31; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st31: + if ( ++p == pe ) + goto _test_eof31; +case 31: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr80; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st32: + if ( ++p == pe ) + goto _test_eof32; +case 32: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st33; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st33: + if ( ++p == pe ) + goto _test_eof33; +case 33: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st34; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st34: + if ( ++p == pe ) + goto _test_eof34; +case 34: + switch( (*p) ) { + case 46: goto tr68; + case 50: goto tr84; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr83; +st35: + if ( ++p == pe ) + goto _test_eof35; +case 35: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st36; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st36: + if ( ++p == pe ) + goto _test_eof36; +case 36: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st37; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st37: + if ( ++p == pe ) + goto _test_eof37; +case 37: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st38; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st38: + if ( ++p == pe ) + goto _test_eof38; +case 38: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st39; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st39: + if ( ++p == pe ) + goto _test_eof39; +case 39: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr89; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st40: + if ( ++p == pe ) + goto _test_eof40; +case 40: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st41; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st41: + if ( ++p == pe ) + goto _test_eof41; +case 41: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st42; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st42: + if ( ++p == pe ) + goto _test_eof42; +case 42: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto tr92; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st43: + if ( ++p == pe ) + goto _test_eof43; +case 43: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 98: goto st44; + case 111: goto st46; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st44: + if ( ++p == pe ) + goto _test_eof44; +case 44: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st45; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st45: + if ( ++p == pe ) + goto _test_eof45; +case 45: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto tr96; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st46: + if ( ++p == pe ) + goto _test_eof46; +case 46: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st47; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st47: + if ( ++p == pe ) + goto _test_eof47; +case 47: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr99; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr98; +st48: + if ( ++p == pe ) + goto _test_eof48; +case 48: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st49; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st49: + if ( ++p == pe ) + goto _test_eof49; +case 49: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st50; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st50: + if ( ++p == pe ) + goto _test_eof50; +case 50: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st51; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st51: + if ( ++p == pe ) + goto _test_eof51; +case 51: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st52; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st52: + if ( ++p == pe ) + goto _test_eof52; +case 52: + switch( (*p) ) { + case 46: goto tr68; + case 82: goto st53; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st53: + if ( ++p == pe ) + goto _test_eof53; +case 53: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st54; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st54: + if ( ++p == pe ) + goto _test_eof54; +case 54: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto tr106; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st55: + if ( ++p == pe ) + goto _test_eof55; +case 55: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 120: goto st56; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st56: + if ( ++p == pe ) + goto _test_eof56; +case 56: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 112: goto tr108; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st57: + if ( ++p == pe ) + goto _test_eof57; +case 57: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st58; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st58: + if ( ++p == pe ) + goto _test_eof58; +case 58: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto st59; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st59: + if ( ++p == pe ) + goto _test_eof59; +case 59: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st60; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st60: + if ( ++p == pe ) + goto _test_eof60; +case 60: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr112; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st61: + if ( ++p == pe ) + goto _test_eof61; +case 61: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st62; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st62: + if ( ++p == pe ) + goto _test_eof62; +case 62: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st63; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st63: + if ( ++p == pe ) + goto _test_eof63; +case 63: + switch( (*p) ) { + case 46: goto tr68; + case 49: goto st64; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr115; +st64: + if ( ++p == pe ) + goto _test_eof64; +case 64: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr117; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st65: + if ( ++p == pe ) + goto _test_eof65; +case 65: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st66; + case 105: goto st70; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st66: + if ( ++p == pe ) + goto _test_eof66; +case 66: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st67; + case 120: goto tr121; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st67: + if ( ++p == pe ) + goto _test_eof67; +case 67: + switch( (*p) ) { + case 46: goto tr68; + case 83: goto st68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr122; +st68: + if ( ++p == pe ) + goto _test_eof68; +case 68: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 113: goto st69; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st69: + if ( ++p == pe ) + goto _test_eof69; +case 69: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr125; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st70: + if ( ++p == pe ) + goto _test_eof70; +case 70: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr126; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st71: + if ( ++p == pe ) + goto _test_eof71; +case 71: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st72; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st72: + if ( ++p == pe ) + goto _test_eof72; +case 72: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st73; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st73: + if ( ++p == pe ) + goto _test_eof73; +case 73: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr130; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr129; +st74: + if ( ++p == pe ) + goto _test_eof74; +case 74: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto tr131; + case 111: goto st75; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st75: + if ( ++p == pe ) + goto _test_eof75; +case 75: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st76; + case 119: goto tr134; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st76: + if ( ++p == pe ) + goto _test_eof76; +case 76: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr136; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr135; +st77: + if ( ++p == pe ) + goto _test_eof77; +case 77: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st78; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st78: + if ( ++p == pe ) + goto _test_eof78; +case 78: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto st79; + case 110: goto st84; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st79: + if ( ++p == pe ) + goto _test_eof79; +case 79: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st80; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st80: + if ( ++p == pe ) + goto _test_eof80; +case 80: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st81; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st81: + if ( ++p == pe ) + goto _test_eof81; +case 81: + switch( (*p) ) { + case 46: goto tr68; + case 68: goto st82; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st82: + if ( ++p == pe ) + goto _test_eof82; +case 82: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st83; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st83: + if ( ++p == pe ) + goto _test_eof83; +case 83: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto tr144; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st84: + if ( ++p == pe ) + goto _test_eof84; +case 84: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto tr145; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st85: + if ( ++p == pe ) + goto _test_eof85; +case 85: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st86; + case 112: goto st89; + case 113: goto st102; + case 117: goto st104; + case 121: goto st105; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st86: + if ( ++p == pe ) + goto _test_eof86; +case 86: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st87; + case 110: goto st88; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st87: + if ( ++p == pe ) + goto _test_eof87; +case 87: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr153; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st88: + if ( ++p == pe ) + goto _test_eof88; +case 88: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr155; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr154; +st89: + if ( ++p == pe ) + goto _test_eof89; +case 89: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto st90; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st90: + if ( ++p == pe ) + goto _test_eof90; +case 90: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st91; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st91: + if ( ++p == pe ) + goto _test_eof91; +case 91: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st92; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st92: + if ( ++p == pe ) + goto _test_eof92; +case 92: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st93; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st93: + if ( ++p == pe ) + goto _test_eof93; +case 93: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st94; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st94: + if ( ++p == pe ) + goto _test_eof94; +case 94: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st95; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st95: + if ( ++p == pe ) + goto _test_eof95; +case 95: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto st96; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st96: + if ( ++p == pe ) + goto _test_eof96; +case 96: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st97; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st97: + if ( ++p == pe ) + goto _test_eof97; +case 97: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st98; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st98: + if ( ++p == pe ) + goto _test_eof98; +case 98: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st99; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st99: + if ( ++p == pe ) + goto _test_eof99; +case 99: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st100; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st100: + if ( ++p == pe ) + goto _test_eof100; +case 100: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st101; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st101: + if ( ++p == pe ) + goto _test_eof101; +case 101: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr168; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st102: + if ( ++p == pe ) + goto _test_eof102; +case 102: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st103; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st103: + if ( ++p == pe ) + goto _test_eof103; +case 103: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto tr171; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr170; +st104: + if ( ++p == pe ) + goto _test_eof104; +case 104: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto tr172; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st105: + if ( ++p == pe ) + goto _test_eof105; +case 105: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st106; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st106: + if ( ++p == pe ) + goto _test_eof106; +case 106: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st107; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st107: + if ( ++p == pe ) + goto _test_eof107; +case 107: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st108; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st108: + if ( ++p == pe ) + goto _test_eof108; +case 108: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st109; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st109: + if ( ++p == pe ) + goto _test_eof109; +case 109: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st110; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st110: + if ( ++p == pe ) + goto _test_eof110; +case 110: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st111; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st111: + if ( ++p == pe ) + goto _test_eof111; +case 111: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st112; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st112: + if ( ++p == pe ) + goto _test_eof112; +case 112: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr180; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st113: + if ( ++p == pe ) + goto _test_eof113; +case 113: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st114; + case 101: goto st116; + case 105: goto st121; + case 114: goto st123; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st114: + if ( ++p == pe ) + goto _test_eof114; +case 114: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st115; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st115: + if ( ++p == pe ) + goto _test_eof115; +case 115: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr187; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr186; +st116: + if ( ++p == pe ) + goto _test_eof116; +case 116: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st117; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st117: + if ( ++p == pe ) + goto _test_eof117; +case 117: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st118; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st118: + if ( ++p == pe ) + goto _test_eof118; +case 118: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st119; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st119: + if ( ++p == pe ) + goto _test_eof119; +case 119: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr191; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +tr191: +#line 1 "NONE" + {te = p+1;} + goto st120; +st120: + if ( ++p == pe ) + goto _test_eof120; +case 120: +#line 3101 "volumeExprScanner.cc" + switch( (*p) ) { + case 46: goto tr68; + case 58: goto st8; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr192; +st8: + if ( ++p == pe ) + goto _test_eof8; +case 8: + if ( (*p) == 58 ) + goto st9; + goto tr9; +st9: + if ( ++p == pe ) + goto _test_eof9; +case 9: + if ( (*p) == 73 ) + goto tr11; + goto tr9; +st121: + if ( ++p == pe ) + goto _test_eof121; +case 121: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st122; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st122: + if ( ++p == pe ) + goto _test_eof122; +case 122: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr195; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st123: + if ( ++p == pe ) + goto _test_eof123; +case 123: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 117: goto st124; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st124: + if ( ++p == pe ) + goto _test_eof124; +case 124: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr197; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st125: + if ( ++p == pe ) + goto _test_eof125; +case 125: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st126; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st126: + if ( ++p == pe ) + goto _test_eof126; +case 126: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st127; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st127: + if ( ++p == pe ) + goto _test_eof127; +case 127: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto st128; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st128: + if ( ++p == pe ) + goto _test_eof128; +case 128: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st129; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st129: + if ( ++p == pe ) + goto _test_eof129; +case 129: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr202; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st130: + if ( ++p == pe ) + goto _test_eof130; +case 130: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st131; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st131: + if ( ++p == pe ) + goto _test_eof131; +case 131: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st132; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st132: + if ( ++p == pe ) + goto _test_eof132; +case 132: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st133; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st133: + if ( ++p == pe ) + goto _test_eof133; +case 133: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto st134; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st134: + if ( ++p == pe ) + goto _test_eof134; +case 134: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto st135; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st135: + if ( ++p == pe ) + goto _test_eof135; +case 135: + switch( (*p) ) { + case 46: goto tr68; + case 65: goto st136; + case 83: goto st142; + case 95: goto tr68; + } + if ( (*p) < 66 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st136: + if ( ++p == pe ) + goto _test_eof136; +case 136: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 118: goto st137; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st137: + if ( ++p == pe ) + goto _test_eof137; +case 137: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st138; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st138: + if ( ++p == pe ) + goto _test_eof138; +case 138: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st139; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st139: + if ( ++p == pe ) + goto _test_eof139; +case 139: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st140; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st140: + if ( ++p == pe ) + goto _test_eof140; +case 140: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st141; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st141: + if ( ++p == pe ) + goto _test_eof141; +case 141: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr215; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st142: + if ( ++p == pe ) + goto _test_eof142; +case 142: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 117: goto st143; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st143: + if ( ++p == pe ) + goto _test_eof143; +case 143: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto tr217; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st10: + if ( ++p == pe ) + goto _test_eof10; +case 10: + if ( (*p) == 124 ) + goto tr12; + goto st0; + } + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof1: cs = 1; goto _test_eof; + _test_eof2: cs = 2; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof3: cs = 3; goto _test_eof; + _test_eof4: cs = 4; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof5: cs = 5; goto _test_eof; + _test_eof6: cs = 6; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; + _test_eof7: cs = 7; goto _test_eof; + _test_eof21: cs = 21; goto _test_eof; + _test_eof22: cs = 22; goto _test_eof; + _test_eof23: cs = 23; goto _test_eof; + _test_eof24: cs = 24; goto _test_eof; + _test_eof25: cs = 25; goto _test_eof; + _test_eof26: cs = 26; goto _test_eof; + _test_eof27: cs = 27; goto _test_eof; + _test_eof28: cs = 28; goto _test_eof; + _test_eof29: cs = 29; goto _test_eof; + _test_eof30: cs = 30; goto _test_eof; + _test_eof31: cs = 31; goto _test_eof; + _test_eof32: cs = 32; goto _test_eof; + _test_eof33: cs = 33; goto _test_eof; + _test_eof34: cs = 34; goto _test_eof; + _test_eof35: cs = 35; goto _test_eof; + _test_eof36: cs = 36; goto _test_eof; + _test_eof37: cs = 37; goto _test_eof; + _test_eof38: cs = 38; goto _test_eof; + _test_eof39: cs = 39; goto _test_eof; + _test_eof40: cs = 40; goto _test_eof; + _test_eof41: cs = 41; goto _test_eof; + _test_eof42: cs = 42; goto _test_eof; + _test_eof43: cs = 43; goto _test_eof; + _test_eof44: cs = 44; goto _test_eof; + _test_eof45: cs = 45; goto _test_eof; + _test_eof46: cs = 46; goto _test_eof; + _test_eof47: cs = 47; goto _test_eof; + _test_eof48: cs = 48; goto _test_eof; + _test_eof49: cs = 49; goto _test_eof; + _test_eof50: cs = 50; goto _test_eof; + _test_eof51: cs = 51; goto _test_eof; + _test_eof52: cs = 52; goto _test_eof; + _test_eof53: cs = 53; goto _test_eof; + _test_eof54: cs = 54; goto _test_eof; + _test_eof55: cs = 55; goto _test_eof; + _test_eof56: cs = 56; goto _test_eof; + _test_eof57: cs = 57; goto _test_eof; + _test_eof58: cs = 58; goto _test_eof; + _test_eof59: cs = 59; goto _test_eof; + _test_eof60: cs = 60; goto _test_eof; + _test_eof61: cs = 61; goto _test_eof; + _test_eof62: cs = 62; goto _test_eof; + _test_eof63: cs = 63; goto _test_eof; + _test_eof64: cs = 64; goto _test_eof; + _test_eof65: cs = 65; goto _test_eof; + _test_eof66: cs = 66; goto _test_eof; + _test_eof67: cs = 67; goto _test_eof; + _test_eof68: cs = 68; goto _test_eof; + _test_eof69: cs = 69; goto _test_eof; + _test_eof70: cs = 70; goto _test_eof; + _test_eof71: cs = 71; goto _test_eof; + _test_eof72: cs = 72; goto _test_eof; + _test_eof73: cs = 73; goto _test_eof; + _test_eof74: cs = 74; goto _test_eof; + _test_eof75: cs = 75; goto _test_eof; + _test_eof76: cs = 76; goto _test_eof; + _test_eof77: cs = 77; goto _test_eof; + _test_eof78: cs = 78; goto _test_eof; + _test_eof79: cs = 79; goto _test_eof; + _test_eof80: cs = 80; goto _test_eof; + _test_eof81: cs = 81; goto _test_eof; + _test_eof82: cs = 82; goto _test_eof; + _test_eof83: cs = 83; goto _test_eof; + _test_eof84: cs = 84; goto _test_eof; + _test_eof85: cs = 85; goto _test_eof; + _test_eof86: cs = 86; goto _test_eof; + _test_eof87: cs = 87; goto _test_eof; + _test_eof88: cs = 88; goto _test_eof; + _test_eof89: cs = 89; goto _test_eof; + _test_eof90: cs = 90; goto _test_eof; + _test_eof91: cs = 91; goto _test_eof; + _test_eof92: cs = 92; goto _test_eof; + _test_eof93: cs = 93; goto _test_eof; + _test_eof94: cs = 94; goto _test_eof; + _test_eof95: cs = 95; goto _test_eof; + _test_eof96: cs = 96; goto _test_eof; + _test_eof97: cs = 97; goto _test_eof; + _test_eof98: cs = 98; goto _test_eof; + _test_eof99: cs = 99; goto _test_eof; + _test_eof100: cs = 100; goto _test_eof; + _test_eof101: cs = 101; goto _test_eof; + _test_eof102: cs = 102; goto _test_eof; + _test_eof103: cs = 103; goto _test_eof; + _test_eof104: cs = 104; goto _test_eof; + _test_eof105: cs = 105; goto _test_eof; + _test_eof106: cs = 106; goto _test_eof; + _test_eof107: cs = 107; goto _test_eof; + _test_eof108: cs = 108; goto _test_eof; + _test_eof109: cs = 109; goto _test_eof; + _test_eof110: cs = 110; goto _test_eof; + _test_eof111: cs = 111; goto _test_eof; + _test_eof112: cs = 112; goto _test_eof; + _test_eof113: cs = 113; goto _test_eof; + _test_eof114: cs = 114; goto _test_eof; + _test_eof115: cs = 115; goto _test_eof; + _test_eof116: cs = 116; goto _test_eof; + _test_eof117: cs = 117; goto _test_eof; + _test_eof118: cs = 118; goto _test_eof; + _test_eof119: cs = 119; goto _test_eof; + _test_eof120: cs = 120; goto _test_eof; + _test_eof8: cs = 8; goto _test_eof; + _test_eof9: cs = 9; goto _test_eof; + _test_eof121: cs = 121; goto _test_eof; + _test_eof122: cs = 122; goto _test_eof; + _test_eof123: cs = 123; goto _test_eof; + _test_eof124: cs = 124; goto _test_eof; + _test_eof125: cs = 125; goto _test_eof; + _test_eof126: cs = 126; goto _test_eof; + _test_eof127: cs = 127; goto _test_eof; + _test_eof128: cs = 128; goto _test_eof; + _test_eof129: cs = 129; goto _test_eof; + _test_eof130: cs = 130; goto _test_eof; + _test_eof131: cs = 131; goto _test_eof; + _test_eof132: cs = 132; goto _test_eof; + _test_eof133: cs = 133; goto _test_eof; + _test_eof134: cs = 134; goto _test_eof; + _test_eof135: cs = 135; goto _test_eof; + _test_eof136: cs = 136; goto _test_eof; + _test_eof137: cs = 137; goto _test_eof; + _test_eof138: cs = 138; goto _test_eof; + _test_eof139: cs = 139; goto _test_eof; + _test_eof140: cs = 140; goto _test_eof; + _test_eof141: cs = 141; goto _test_eof; + _test_eof142: cs = 142; goto _test_eof; + _test_eof143: cs = 143; goto _test_eof; + _test_eof10: cs = 10; goto _test_eof; + + _test_eof: {} + if ( p == eof ) + { + switch ( cs ) { + case 12: goto tr52; + case 13: goto tr53; + case 14: goto tr55; + case 15: goto tr57; + case 16: goto tr60; + case 5: goto tr5; + case 6: goto tr5; + case 17: goto tr60; + case 18: goto tr62; + case 19: goto tr60; + case 20: goto tr63; + case 21: goto tr65; + case 22: goto tr67; + case 23: goto tr69; + case 24: goto tr67; + case 25: goto tr67; + case 26: goto tr67; + case 27: goto tr67; + case 28: goto tr67; + case 29: goto tr67; + case 30: goto tr67; + case 31: goto tr67; + case 32: goto tr67; + case 33: goto tr67; + case 34: goto tr83; + case 35: goto tr67; + case 36: goto tr67; + case 37: goto tr67; + case 38: goto tr67; + case 39: goto tr67; + case 40: goto tr67; + case 41: goto tr67; + case 42: goto tr67; + case 43: goto tr67; + case 44: goto tr67; + case 45: goto tr67; + case 46: goto tr67; + case 47: goto tr98; + case 48: goto tr67; + case 49: goto tr67; + case 50: goto tr67; + case 51: goto tr67; + case 52: goto tr67; + case 53: goto tr67; + case 54: goto tr67; + case 55: goto tr67; + case 56: goto tr67; + case 57: goto tr67; + case 58: goto tr67; + case 59: goto tr67; + case 60: goto tr67; + case 61: goto tr67; + case 62: goto tr67; + case 63: goto tr115; + case 64: goto tr67; + case 65: goto tr67; + case 66: goto tr67; + case 67: goto tr122; + case 68: goto tr67; + case 69: goto tr67; + case 70: goto tr67; + case 71: goto tr67; + case 72: goto tr67; + case 73: goto tr129; + case 74: goto tr67; + case 75: goto tr67; + case 76: goto tr135; + case 77: goto tr67; + case 78: goto tr67; + case 79: goto tr67; + case 80: goto tr67; + case 81: goto tr67; + case 82: goto tr67; + case 83: goto tr67; + case 84: goto tr67; + case 85: goto tr67; + case 86: goto tr67; + case 87: goto tr67; + case 88: goto tr154; + case 89: goto tr67; + case 90: goto tr67; + case 91: goto tr67; + case 92: goto tr67; + case 93: goto tr67; + case 94: goto tr67; + case 95: goto tr67; + case 96: goto tr67; + case 97: goto tr67; + case 98: goto tr67; + case 99: goto tr67; + case 100: goto tr67; + case 101: goto tr67; + case 102: goto tr67; + case 103: goto tr170; + case 104: goto tr67; + case 105: goto tr67; + case 106: goto tr67; + case 107: goto tr67; + case 108: goto tr67; + case 109: goto tr67; + case 110: goto tr67; + case 111: goto tr67; + case 112: goto tr67; + case 113: goto tr67; + case 114: goto tr67; + case 115: goto tr186; + case 116: goto tr67; + case 117: goto tr67; + case 118: goto tr67; + case 119: goto tr67; + case 120: goto tr192; + case 8: goto tr9; + case 9: goto tr9; + case 121: goto tr67; + case 122: goto tr67; + case 123: goto tr67; + case 124: goto tr67; + case 125: goto tr67; + case 126: goto tr67; + case 127: goto tr67; + case 128: goto tr67; + case 129: goto tr67; + case 130: goto tr67; + case 131: goto tr67; + case 132: goto tr67; + case 133: goto tr67; + case 134: goto tr67; + case 135: goto tr67; + case 136: goto tr67; + case 137: goto tr67; + case 138: goto tr67; + case 139: goto tr67; + case 140: goto tr67; + case 141: goto tr67; + case 142: goto tr67; + case 143: goto tr67; + } + } + + _out: {} + } + +#line 671 "volumeExprScanner.rl" + /* ^^^ FSM execution here ^^^ */; + + if (0 == 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; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprScanner.rl b/src/finiteVolume/expressions/volume/volumeExprScanner.rl new file mode 100644 index 0000000000000000000000000000000000000000..0b198b10af6ec960b5bbcdc1006ffc7c9d885c9b --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprScanner.rl @@ -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; +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/T b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/T new file mode 100644 index 0000000000000000000000000000000000000000..166a338f306e8136b3630a02fe3502e1ff5b4e0e --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/T @@ -0,0 +1,55 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "0"; + object T; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 0 0 1 0 0 0]; + +internalField uniform 300; + +boundaryField +{ + inlet + { + type outletMappedUniformInletHeatAddition; + outletPatch outlet1; + Q 5; // Heat addition in W + TMin 300; + TMax 500; + value $internalField; + } + + outlet1 + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + + outlet2 + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + + defaultFaces + { + type zeroGradient; + } +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/U b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/U new file mode 100644 index 0000000000000000000000000000000000000000..60b7f0d8f09802e940157c7fce58afd966763be1 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/U @@ -0,0 +1,50 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volVectorField; + object U; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 1 -1 0 0 0 0]; + +internalField uniform (0 0 0); + +boundaryField +{ + inlet + { + type pressureInletOutletVelocity; + value uniform (0 0 0); + } + + outlet1 + { + type inletOutlet; + inletValue uniform (0 0 0); + value uniform (0 0 0); + } + + outlet2 + { + type inletOutlet; + inletValue uniform (0 0 0); + value uniform (0 0 0); + } + + defaultFaces + { + type fixedValue; + value uniform (0 0 0); + } +} + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/alphat b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/alphat new file mode 100644 index 0000000000000000000000000000000000000000..6471c6900653ead97535beeb8a9b72e712819532 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/alphat @@ -0,0 +1,50 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "0"; + object alphat; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -1 0 0 0 0]; + +internalField uniform 1e-3; + +boundaryField +{ + inlet + { + type calculated; + value uniform 0; + } + + outlet1 + { + type calculated; + value uniform 0; + } + + outlet2 + { + type calculated; + value uniform 0; + } + + defaultFaces + { + type compressible::alphatWallFunction; + value $internalField; + } +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/epsilon b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/epsilon new file mode 100644 index 0000000000000000000000000000000000000000..3f577a7999de7891bb56bf8470d29e272e7c3415 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/epsilon @@ -0,0 +1,53 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "0"; + object epsilon; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -3 0 0 0 0]; + +internalField uniform 200; + +boundaryField +{ + inlet + { + type turbulentMixingLengthDissipationRateInlet; + mixingLength 0.01; // 1cm - half channel height + value $internalField; + } + + outlet1 + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + + outlet2 + { + type inletOutlet; + inletValue $internalField; + value $internalField; + } + + defaultFaces + { + type epsilonWallFunction; + value $internalField; + } +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/k b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/k new file mode 100644 index 0000000000000000000000000000000000000000..1e041613e9057b1f4ad9a779e57b932db784ff2f --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/k @@ -0,0 +1,51 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "0"; + object k; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -2 0 0 0 0]; + +internalField uniform 1; + +boundaryField +{ + inlet + { + type turbulentIntensityKineticEnergyInlet; + intensity 0.05; // 5% turbulent intensity + value $internalField; + } + + outlet1 + { + type inletOutlet; + inletValue $internalField; + } + + outlet2 + { + type inletOutlet; + inletValue $internalField; + } + + defaultFaces + { + type kqRWallFunction; + value $internalField; + } +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/nuTilda b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/nuTilda new file mode 100644 index 0000000000000000000000000000000000000000..dc39c62165a512a39cf3d3b12ba3bc6e1896d55d --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/nuTilda @@ -0,0 +1,44 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object nuTilda; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type zeroGradient; + } + + outlet1 + { + type zeroGradient; + } + + outlet2 + { + type zeroGradient; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/nut b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/nut new file mode 100644 index 0000000000000000000000000000000000000000..1552d4d85c8c8eab272c513ea53c3e17cf443d40 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/nut @@ -0,0 +1,50 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + location "0"; + object nut; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [0 2 -1 0 0 0 0]; + +internalField uniform 0; + +boundaryField +{ + inlet + { + type calculated; + value uniform 0; + } + + outlet1 + { + type calculated; + value uniform 0; + } + + outlet2 + { + type calculated; + value uniform 0; + } + + defaultFaces + { + type nutkWallFunction; + value uniform 0; + } +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/p b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/p new file mode 100644 index 0000000000000000000000000000000000000000..1e896e6508e17bb1e29aae6b71da545c7e5ae59f --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/0/p @@ -0,0 +1,71 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class volScalarField; + object p; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +dimensions [1 -1 -2 0 0 0 0]; + +internalField uniform 1e5; + +boundaryField +{ + inlet + { + type uniformTotalPressure; + gamma 1.2; + + p0 table + ( + (0 1e5) + (1 1.4e5) + ); + } + + outlet1 + { + type fixedValue; + value $internalField; + } + + outlet1 + { + type exprFixedValue; + value $internalField; + + valueExpr "0.5*(pInlet + pOutlet2)"; + variables + ( + "pInlet{inlet} = weightAverage(p)" + "pOutlet2{outlet2} = p" + ); + + // debug true; + // debugScanner true; + // debugParser true; + } + + + outlet2 + { + type fixedValue; + value $internalField; + } + + defaultFaces + { + type zeroGradient; + } +} + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/README.txt b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/README.txt new file mode 100644 index 0000000000000000000000000000000000000000..5c812a1e4bd27920bb8d5b4f8c8360d0d9432175 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/README.txt @@ -0,0 +1,4 @@ +15/8/8 Simple T-junction. Inlet on left, one outlet at bottom, one at top. +To test multiple outlets. + +Enable debugScanner/debugParser for a verbose view of the parsing engine. diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/fvOptions b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/fvOptions new file mode 100644 index 0000000000000000000000000000000000000000..ce5c49527bb7f8ea02ba26a3e15fc1fe2a4dee06 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/fvOptions @@ -0,0 +1,22 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object fvOptions; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +viscousDissipation +{ + type viscousDissipation; + enabled true; +} +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/thermophysicalProperties b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/thermophysicalProperties new file mode 100644 index 0000000000000000000000000000000000000000..356422609d9fa0054e4c4589cade640aa1516b58 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/thermophysicalProperties @@ -0,0 +1,48 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object thermophysicalProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +thermoType +{ + type hePsiThermo; + mixture pureMixture; + transport sutherland; + thermo hConst; + equationOfState perfectGas; + specie specie; + energy sensibleEnthalpy; +} + +mixture +{ + specie + { + molWeight 28.9; + } + thermodynamics + { + Cp 1007; + Hf 0; + } + transport + { + As 1.4792e-06; + Ts 116; + } +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/turbulenceProperties b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/turbulenceProperties new file mode 100644 index 0000000000000000000000000000000000000000..f728d3fb7cd5ed4a5372fd0d20d3a093c28cd6f2 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/constant/turbulenceProperties @@ -0,0 +1,30 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "constant"; + object turbulenceProperties; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +simulationType RAS; + +RAS +{ + RASModel kEpsilon; + + turbulence on; + + printCoeffs on; +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/blockMeshDict b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/blockMeshDict new file mode 100644 index 0000000000000000000000000000000000000000..ed28fc6988fa13c5a377dfad67d3f762072c7ffd --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/blockMeshDict @@ -0,0 +1,127 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object blockMeshDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// outlet1 +// +-+ +// | | +// | | +// | | +// | | +// +-----------+ | +// |inlet | +// +-----------+ | +// | | +// | | +// | | +// | | +// +-+ +// outlet2 + +scale 1; + +vertices +( + (0.0 -0.01 0) //0 + (0.2 -0.01 0) + (0.2 0.01 0) //2 + (0.0 0.01 0) + + (0.22 -0.01 0) //4 + (0.22 0.01 0) + + (0.2 -0.21 0) //6 + (0.22 -0.21 0) + + (0.2 0.21 0) //8 + (0.22 0.21 0) + + // Z + (0.0 -0.01 0.02) //0 + (0.2 -0.01 0.02) + (0.2 0.01 0.02) //2 + (0.0 0.01 0.02) + + (0.22 -0.01 0.02) //4 + (0.22 0.01 0.02) + + (0.2 -0.21 0.02) //6 + (0.22 -0.21 0.02) + + (0.2 0.21 0.02) //8 + (0.22 0.21 0.02) + +); + +blocks +( + // inlet block + hex (0 1 2 3 10 11 12 13) (50 5 5) simpleGrading (1 1 1) + + // central block + hex (1 4 5 2 11 14 15 12) (5 5 5) simpleGrading (1 1 1) + + // bottom block + hex (6 7 4 1 16 17 14 11) (5 50 5) simpleGrading (1 1 1) + + // top block + hex (2 5 9 8 12 15 19 18) (5 50 5) simpleGrading (1 1 1) +); + +edges +( +); + +boundary +( + inlet + { + type patch; + faces + ( + (0 10 13 3) + ); + } + + outlet1 + { + type patch; + faces + ( + (6 7 17 16) + ); + } + + outlet2 + { + type patch; + faces + ( + (8 18 19 9) + ); + } + + defaultFaces + { + type wall; + faces (); + } +); + +mergePatchPairs +( +); + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/controlDict b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/controlDict new file mode 100644 index 0000000000000000000000000000000000000000..02148db3ccfb508ec28eac8443f6ca9fa71f508e --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/controlDict @@ -0,0 +1,52 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object controlDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +application rhoPimpleFoam; + +startFrom startTime; + +startTime 0; + +stopAt endTime; + +endTime 1.0; + +deltaT 0.001; + +writeControl adjustable; + +writeInterval 0.1; + +purgeWrite 0; + +writeFormat ascii; + +writePrecision 6; + +writeCompression off; + +timeFormat general; + +timePrecision 6; + +runTimeModifiable true; + +adjustTimeStep yes; + +maxCo 3; + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/fvSchemes b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/fvSchemes new file mode 100644 index 0000000000000000000000000000000000000000..26d7a694892315be3e4389153daaff26eb149027 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/fvSchemes @@ -0,0 +1,57 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSchemes; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +ddtSchemes +{ + default Euler; +} + +gradSchemes +{ + default Gauss linear; +} + +divSchemes +{ + default none; + div(phi,U) Gauss limitedLinearV 1; + div(phi,k) Gauss limitedLinear 1; + div(phi,epsilon) Gauss limitedLinear 1; + div(phi,h) Gauss limitedLinear 1; + div(phi,R) Gauss limitedLinear 1; + div(R) Gauss linear; + div(phi,K) Gauss linear; + div(((rho*nuEff)*dev2(T(grad(U))))) Gauss linear; +} + +laplacianSchemes +{ + default Gauss linear corrected; +} + +interpolationSchemes +{ + default linear; +} + +snGradSchemes +{ + default corrected; +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/fvSolution b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/fvSolution new file mode 100644 index 0000000000000000000000000000000000000000..82ea2a0025c053581fcf0a712cc57974fd4b42cb --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/fvSolution @@ -0,0 +1,70 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + location "system"; + object fvSolution; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +solvers +{ + p + { + solver GAMG; + tolerance 1e-08; + relTol 0.01; + smoother GaussSeidel; + } + + pFinal + { + solver GAMG; + tolerance 1e-08; + relTol 0; + smoother GaussSeidel; + } + + "(rho|U|k|epsilon|h)" + { + solver smoothSolver; + smoother symGaussSeidel; + tolerance 1e-07; + relTol 0.05; + } + + "(rho|U|k|epsilon|h)Final" + { + $U; + tolerance 1e-07; + relTol 0; + } +} + +PIMPLE +{ + momentumPredictor no; + transonic no; + nOuterCorrectors 1; + nCorrectors 5; + nNonOrthogonalCorrectors 0; +} + +relaxationFactors +{ + equations + { + ".*" 1; + } +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/setExprBoundaryFieldsDict b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/setExprBoundaryFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..6412e4f64b29a30fd4887b49dc0b4e68119781e2 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/setExprBoundaryFieldsDict @@ -0,0 +1,32 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setExprBoundaryFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +pattern +{ + field T; + + expressions + ( + { + patch outlet2; + target something; + expression #{ (pos().x() < 1e-4 ? 60 : 120) #}; + } + ); +} + + +// ************************************************************************* // diff --git a/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/setExprFieldsDict b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/setExprFieldsDict new file mode 100644 index 0000000000000000000000000000000000000000..1a124966e73b8c5454906613c123b448121d1e85 --- /dev/null +++ b/tutorials/compressible/rhoPimpleFoam/RAS/TJunctionAverage/system/setExprFieldsDict @@ -0,0 +1,53 @@ +/*--------------------------------*- C++ -*----------------------------------*\ +| ========= | | +| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox | +| \\ / O peration | Version: v1912 | +| \\ / A nd | Website: www.openfoam.com | +| \\/ M anipulation | | +\*---------------------------------------------------------------------------*/ +FoamFile +{ + version 2.0; + format ascii; + class dictionary; + object setExprFieldsDict; +} +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + + +expressions +( + T + { + field T; + dimensions [0 0 0 1 0 0 0]; + + constants + { + centre (0.21 0 0.01); + } + + variables + ( + "radius = 0.1" + ); + + condition + #{ + // Within the radius + (mag(pos() - $[(vector)constants.centre]) < radius) + + // but only +ve y! + && pos((pos() - $[(vector)constants.centre]).y()) > 0 + #}; + + expression + #{ + 300 + + 200 * (1 - mag(pos() - $[(vector)constants.centre]) / radius) + #}; + } +); + + +// ************************************************************************* //