diff --git a/applications/utilities/miscellaneous/foamDebugSwitches/foamDebugSwitches.C b/applications/utilities/miscellaneous/foamDebugSwitches/foamDebugSwitches.C index 5089c75b8a260de6a8e1b0510a57d9a90474a606..25c3fafebb464b54b2abd752103863979afbdcd2 100644 --- a/applications/utilities/miscellaneous/foamDebugSwitches/foamDebugSwitches.C +++ b/applications/utilities/miscellaneous/foamDebugSwitches/foamDebugSwitches.C @@ -159,8 +159,6 @@ int main(int argc, char *argv[]) Info<< "OptimisationSwitches: " << currOpt << endl; } - - Info<< "done" << endl; return 0; diff --git a/applications/utilities/miscellaneous/foamDictionary/Make/files b/applications/utilities/miscellaneous/foamDictionary/Make/files new file mode 100644 index 0000000000000000000000000000000000000000..4482d582c37987b3eccb8b79fb3c6303a0e8070a --- /dev/null +++ b/applications/utilities/miscellaneous/foamDictionary/Make/files @@ -0,0 +1,3 @@ +foamDictionary.C + +EXE = $(FOAM_USER_APPBIN)/foamDictionary diff --git a/applications/utilities/miscellaneous/foamDictionary/Make/options b/applications/utilities/miscellaneous/foamDictionary/Make/options new file mode 100644 index 0000000000000000000000000000000000000000..2b9edfc6600f72a5ff1e83a07d752e9f1ea39b85 --- /dev/null +++ b/applications/utilities/miscellaneous/foamDictionary/Make/options @@ -0,0 +1,4 @@ +EXE_INC = \ + -DFULLDEBUG -g -O0 + +/* EXE_LIBS = */ diff --git a/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C b/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C new file mode 100644 index 0000000000000000000000000000000000000000..e00cb2518c6c4d214ce50c8576be4c3f17e31eef --- /dev/null +++ b/applications/utilities/miscellaneous/foamDictionary/foamDictionary.C @@ -0,0 +1,362 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenFOAM Foundation + \\/ M anipulation | +------------------------------------------------------------------------------- +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 + foamDictionary + +Description + Interrogates and manipulates dictionaries. + +Usage + - foamDictionary [OPTION] dictionary + + \param -entry \<name\> \n + Selects an entry + + \param -keywords \<name\> \n + Prints the keywords (of the selected entry or of the top level if + no entry was selected + + \param -add \<value\> \n + Adds the entry (should not exist yet) + + \param -set \<value\> \n + Adds or replaces the entry + + Typical usage: + - change simulation to run for one timestep only: + foamDictionary system/controlDict -entry stopAt -set writeNow; + + - change solver + foamDictionary system/fvSolution -entry solvers.p.solver -set PCG + + - print bc type + foamDictionary 0/U -entry boundaryField.movingWall.type + + - change bc parameter + foamDictionary 0/U -entry boundaryField.movingWall.value \ + -set "uniform (2 0 0)" + + - change whole bc type + foamDictionary 0/U -entry boundaryField.movingWall \ + -set "{type uniformFixedValue; uniformValue (2 0 0);}" + +\*---------------------------------------------------------------------------*/ + +#include "argList.H" +#include "Time.H" +#include "IFstream.H" +#include "OFstream.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- Converts old scope syntax to new syntax +word scope(const fileName& entryName) +{ + if (entryName.find(':') != string::npos) + { + wordList entryNames(entryName.components(':')); + + word entry(entryNames[0]); + for (label i = 1; i < entryNames.size(); i++) + { + entry += word('.') + entryNames[i]; + } + return entry; + } + else + { + return entryName; + } +} + + +//- Extract keyword (last bit of scoped name +word keyword(const word& scopedName) +{ + word key(scopedName); + string::size_type i = scopedName.find_last_of("."); + if (i != string::npos) + { + key = scopedName.substr(i+1, string::npos); + } + return key; +} + + +void setScoped +( + dictionary& dict, + const word& keyword, + const bool overwrite, + entry* d +) +{ + if (keyword[0] == ':') + { + // Go up to top level and recurse to find entries + setScoped + ( + const_cast<dictionary&>(dict.topDict()), + keyword.substr(1, keyword.size()-1), + overwrite, + d + ); + return; + } + else + { + string::size_type dotPos = keyword.find('.'); + + if (dotPos == string::npos) + { + // Non-scoped lookup + if (overwrite) + { + dict.set(d); + } + else + { + dict.add(d, false); + } + return; + } + else + { + if (dotPos == 0) + { + // Starting with a '.'. Go up for every 2nd '.' found + + const dictionary* dictPtr = &dict; + + string::size_type begVar = dotPos + 1; + string::const_iterator iter = + keyword.begin() + begVar; + string::size_type endVar = begVar; + while + ( + iter != keyword.end() + && *iter == '.' + ) + { + ++iter; + ++endVar; + + // Go to parent + if (&dictPtr->parent() == &dictionary::null) + { + FatalIOErrorInFunction(dict) + << "No parent of current dictionary" + << " when searching for " + << keyword.substr + ( + begVar, + keyword.size() - begVar + ) + << exit(FatalIOError); + } + dictPtr = &dictPtr->parent(); + } + + setScoped + ( + const_cast<dictionary&>(*dictPtr), + keyword.substr(endVar), + overwrite, + d + ); + return; + } + else + { + // Extract the first word + word firstWord = keyword.substr(0, dotPos); + + const entry* entPtr = dict.lookupScopedEntryPtr + ( + firstWord, + false, // Recursive + false + ); + + if (!entPtr || !entPtr->isDict()) + { + FatalIOErrorInFunction(dict) + << "keyword " << firstWord + << " is undefined in dictionary " + << dict.name() << " or is not a dictionary" + << endl + << "Valid keywords are " << dict.keys() + << exit(FatalIOError); + } + + const dictionary& firstDict = entPtr->dict(); + + setScoped + ( + const_cast<dictionary&>(firstDict), + keyword.substr(dotPos, keyword.size()-dotPos), + overwrite, + d + ); + return; + } + } + } +} + + +int main(int argc, char *argv[]) +{ + argList::addNote("manipulates dictionaries"); + + argList::noBanner(); + argList::validArgs.append("dictionary"); + argList::addBoolOption("keywords", "report keywords"); + argList::addOption("entry", "name", "report/select the named entry"); + argList::addOption + ( + "set", + "value", + "changes existing entry or adds new entry" + ); + argList::addOption + ( + "add", + "value", + "adds a new entry" + ); + + #include "setRootCase.H" + + fileName dictFileName(args.rootPath()/args.caseName()/args[1]); + + autoPtr<IFstream> dictFile(new IFstream(dictFileName)); + + if (dictFile().good()) + { + bool changed = false; + + // Read but preserve headers + dictionary dict; + dict.read(dictFile(), true); + + word entryName; + if (args.optionReadIfPresent("entry", entryName)) + { + word scopedName(scope(entryName)); + + string newValue; + if + ( + args.optionReadIfPresent("set", newValue) + || args.optionReadIfPresent("add", newValue) + ) + { + bool overwrite = args.optionFound("set"); + + word key(keyword(scopedName)); + + IStringStream str(string(key) + ' ' + newValue + ';'); + setScoped(dict, scopedName, overwrite, entry::New(str).ptr()); + changed = true; + + // Print the changed entry + const entry* entPtr = dict.lookupScopedEntryPtr + ( + scopedName, + false, + true // Support wildcards + ); + if (entPtr) + { + Info<< *entPtr << endl; + } + } + else + { + const entry* entPtr = dict.lookupScopedEntryPtr + ( + scopedName, + false, + true // Support wildcards + ); + + if (entPtr) + { + if (args.optionFound("keywords")) + { + const dictionary& dict = entPtr->dict(); + forAllConstIter(dictionary, dict, iter) + { + Info<< iter().keyword() << endl; + } + } + else + { + Info<< *entPtr << endl; + } + } + else + { + FatalIOErrorInFunction(dictFile) + << "Cannot find entry " << entryName + << exit(FatalError, 2); + } + } + } + else if (args.optionFound("keywords")) + { + forAllConstIter(dictionary, dict, iter) + { + Info<< iter().keyword() << endl; + } + } + else + { + Info<< dict; + } + + if (changed) + { + dictFile.clear(); + OFstream os(dictFileName); + IOobject::writeBanner(os); + dict.write(os, false); + IOobject::writeEndDivider(os); + } + } + else + { + FatalErrorInFunction + << "Cannot open file " << dictFileName + << exit(FatalError, 1); + } + + return 0; +} + + +// ************************************************************************* //