/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2013 OpenFOAM Foundation Copyright (C) 2021 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 fvSolutionCombine Description Simple utility for combining fvSolution solution entries. \*---------------------------------------------------------------------------*/ #include "argList.H" #include "Time.H" #include "wordRe.H" #include "OSspecific.H" using namespace Foam; // check for identical dictionary content, regardless of the order bool checkDictionaryContent(const dictionary& dict1, const dictionary& dict2) { // trivial cases first if (&dict1 == &dict2) { return true; } else if (dict1.size() != dict2.size()) { return false; } for (const entry& entry1 : dict1) { const entry* eptr = dict2.findEntry(entry1.keyword(), keyType::LITERAL); if (!eptr) { return false; } const entry& entry2 = *eptr; bool ok = false; if (entry1.isDict()) { if (entry2.isDict()) { ok = checkDictionaryContent(entry1.dict(), entry2.dict()); } } else { ok = (entry1 == entry2); } if (!ok) { return false; } } return true; } // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Main program: int main(int argc, char *argv[]) { argList::noParallel(); argList::addBoolOption("rewrite"); argList::addBoolOption("show"); argList args(argc, argv); Time runTime(args.rootPath(), args.caseName()); const word dictName("fvSolution"); bool optRewrite = args.found("rewrite"); bool optShow = args.found("show"); IOdictionary solutionDict ( IOobject ( dictName, runTime.system(), runTime, IOobject::MUST_READ_IF_MODIFIED, IOobject::NO_WRITE, IOobject::NO_REGISTER ) ); if (!solutionDict.found("solvers")) { Info<<"no solvers entry found in : " << dictName << endl; return 2; } if (optRewrite && solutionDict.instance() != runTime.system()) { Info<<"instance is not " << runTime.system() << "- disabling rewrite for this file" << nl; optRewrite = false; } dictionary& solverDict = solutionDict.subDict("solvers"); wordList names = solverDict.toc(); wordList oldNames = names; bool changed = false; for (label orig = 0; orig < names.size()-1; ++orig) { // Skip patterns or entries that have already been done if (names[orig].empty() || regExp::is_meta(names[orig])) { continue; } const dictionary& dict1 = solverDict.subDict(names[orig]); for (label check = orig+1; check < names.size(); ++check) { // Skip patterns or entries that have already been done if (names[check].empty() || regExp::is_meta(names[check])) { continue; } const dictionary& dict2 = solverDict.subDict(names[check]); // Check for identical content if (checkDictionaryContent(dict1, dict2)) { names[orig] += "|" + names[check]; names[check].clear(); changed = true; } } } if (changed) { forAll(names, nameI) { if (names[nameI].empty()) { solverDict.remove(oldNames[nameI]); Info<<" #remove " << oldNames[nameI]; } else { Info<< " " << oldNames[nameI]; if (names[nameI] != oldNames[nameI]) { // make "(abc|def)" pattern keyType renamed("(" + names[nameI] + ")", keyType::REGEX); solverDict.changeKeyword(oldNames[nameI], renamed); Info<< " -> " << renamed; } } Info<< endl; } if (optRewrite) { mvBak(solutionDict.objectPath(), "orig"); Info<< "Backup to .orig" << nl << "Writing " << solutionDict.objectPath() << nl << endl; solutionDict.regIOobject::write(); } else if (optShow) { IOobject::writeDivider(Info); solutionDict.dictionary::write(Info, false); } else { Info<< "\nFile not rewritten" << endl; } } else { Info<< "no changes" << endl; } Info<< "Done\n" << endl; return changed ? 0 : 1; } // ************************************************************************* //