/*---------------------------------------------------------------------------*\ ========= | \\ / 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 . Application setExprFields Group grpPreProcessingUtilities Description Set boundary values using an expression Note Based on funkySetBoundaryFields Copyright 2006-2018 Bernhard Gschaider \*---------------------------------------------------------------------------*/ #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("field")); List 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(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(false); if (!headOk) { // Restore type const_cast(IOdictionary::typeName) = oldTypeName; WarningInFunction << "Requested field to change " << fieldName << " does not exist in " << fieldHeader.path() << endl; continue; } IOdictionary fieldDict(fieldHeader); // Restore type const_cast(IOdictionary::typeName) = oldTypeName; // Fake type back to what was in field const_cast(fieldDict.type()) = fieldDict.headerClassName(); Info<< "Processing field " << fieldName << nl; dictionary& boundaryFieldDict = fieldDict.subDict("boundaryField"); for (const dictionary& currDict : exprDicts) { const word targetName = currDict.get("target"); const word patchName = currDict.get("patch"); dictionary& patchDict = boundaryFieldDict.subDict(patchName); expressions::exprString expr ( currDict.get("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; } // ************************************************************************* //