mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: setExprFields and setExprBoundaryFields
- these are the expressions equivalent of funkySetFields and funkySetBoundaryFields
This commit is contained in:
@ -0,0 +1,3 @@
|
||||
setExprBoundaryFields.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/setExprBoundaryFields
|
||||
@ -0,0 +1,8 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lfiniteVolume \
|
||||
-lmeshTools \
|
||||
-lgenericPatchFields
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,3 @@
|
||||
setExprFields.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/setExprFields
|
||||
@ -0,0 +1,8 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lfiniteVolume \
|
||||
-lmeshTools \
|
||||
-lgenericPatchFields
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -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)
|
||||
#};
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -28,7 +28,7 @@ Class
|
||||
Foam::exprMixedFvPatchField
|
||||
|
||||
Description
|
||||
Foam::exprMixedFvPatchField
|
||||
A mixed boundary condition with expressions.
|
||||
|
||||
Usage
|
||||
\table
|
||||
|
||||
@ -28,7 +28,7 @@ Class
|
||||
Foam::exprValuePointPatchField
|
||||
|
||||
Description
|
||||
A fixed value boundary condition with expressions.
|
||||
A fixed value point boundary condition with expressions.
|
||||
|
||||
Usage
|
||||
\table
|
||||
|
||||
Reference in New Issue
Block a user