diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index 0ff3e598d92c04f3f82ab75041d9cffa49df23a4..f8aac2551b9f9565a3f80789b8d2ab1fcf526a15 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -352,6 +352,7 @@ general = cfdTools/general $(general)/findRefCell/findRefCell.C $(general)/adjustPhi/adjustPhi.C $(general)/bound/bound.C +$(general)/pimpleControl/pimpleControl.C porousMedia = $(general)/porousMedia $(porousMedia)/porousZone.C diff --git a/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControl.C b/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControl.C new file mode 100644 index 0000000000000000000000000000000000000000..77ae648eac1d73ae7f7868f91d1eee65690dcbca --- /dev/null +++ b/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControl.C @@ -0,0 +1,191 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2011 OpenCFD Ltd. + \\/ 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/>. + +\*---------------------------------------------------------------------------*/ + +#include "pimpleControl.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(pimpleControl, 0); +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +Foam::label Foam::pimpleControl::applyToField(const word& fieldName) const +{ + forAll(residualControl_, i) + { + if (residualControl_[i].name.match(fieldName)) + { + return i; + } + } + + return -1; +} + + +bool Foam::pimpleControl::criteriaSatisfied() +{ + if ((corr_ == 0) || residualControl_.empty() || finalIter()) + { + return false; + } + + bool firstIter = corr_ == 1; + + bool achieved = true; + const dictionary& solverDict = mesh_.solverPerformanceDict(); + + forAllConstIter(dictionary, solverDict, iter) + { + const word& variableName = iter().keyword(); + label fieldI = applyToField(variableName); + if (fieldI != -1) + { + const List<lduMatrix::solverPerformance> sp(iter().stream()); + const scalar residual = sp.last().initialResidual(); + + if (firstIter) + { + residualControl_[fieldI].initialResidual = + sp.first().initialResidual(); + } + + bool absCheck = residual < residualControl_[fieldI].absTol; + + bool relCheck = false; + + scalar relative = 0.0; + if (!firstIter) + { + scalar iniRes = + residualControl_[fieldI].initialResidual + + ROOTVSMALL; + + relative = residual/iniRes; + + relCheck = relative < residualControl_[fieldI].relTol; + } + + achieved = achieved && (absCheck || relCheck); + + if (debug) + { + Info<< "PIMPLE loop statistics:" << endl; + + Info<< " " << variableName << " iter " << corr_ + << ": ini res = " + << residualControl_[fieldI].initialResidual + << ", abs tol = " << residual + << " (" << residualControl_[fieldI].absTol << ")" + << ", rel tol = " << relative + << " (" << residualControl_[fieldI].relTol << ")" + << endl; + } + } + } + + return achieved; +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::pimpleControl::pimpleControl(fvMesh& mesh) +: + mesh_(mesh), + nCorr_(0), + corr_(0), + residualControl_() +{ + read(); + + if (residualControl_.size() > 0) + { + Info<< "PIMPLE: max iterations = " << nCorr_ << endl; + forAll(residualControl_, i) + { + Info<< " field " << residualControl_[i].name << token::TAB + << ": relTol " << residualControl_[i].relTol + << ", absTol " << residualControl_[i].absTol + << nl; + } + Info<< endl; + } + else + { + Info<< "No PIMPLE residual control data found. " + << "Calculations will employ a fixed number of corrector loops" + << nl << endl; + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::pimpleControl::~pimpleControl() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::pimpleControl::read() +{ + const dictionary& dict = mesh_.solutionDict().subDict("PIMPLE"); + nCorr_ = dict.lookupOrDefault<label>("nOuterCorrectors", 1); + const dictionary residualDict(dict.subOrEmptyDict("residualControl")); + DynamicList<fieldData> data(residualDict.toc().size()); + wordHashSet fieldNames; + forAllConstIter(dictionary, residualDict, iter) + { + if (fieldNames.insert(iter().keyword())) + { + fieldData fd; + fd.name = iter().keyword().c_str(); + if (iter().isDict()) + { + const dictionary& fieldDict(iter().dict()); + fd.relTol = readScalar(fieldDict.lookup("relTol")); + fd.absTol = readScalar(fieldDict.lookup("absTol")); + fd.initialResidual = 0.0; + data.append(fd); + } + else + { + FatalErrorIn("bool Foam::pimpleControl::read()") + << "Residual data for " << iter().keyword() + << " must be specified as a dictionary"; + } + } + } + + residualControl_.transfer(data); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControl.H b/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControl.H new file mode 100644 index 0000000000000000000000000000000000000000..2538658d880d5094876c83dc3a0291215a4755a8 --- /dev/null +++ b/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControl.H @@ -0,0 +1,141 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2011 OpenCFD Ltd. + \\/ 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/>. + +Class + Foam::pimpleControl + +Description + PIMPLE control class to supply convergence information/checks for + the PIMPLE loop. + +\*---------------------------------------------------------------------------*/ + +#ifndef pimpleControl_H +#define pimpleControl_H + +#include "fvMesh.H" +//#include "className.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class pimpleControl Declaration +\*---------------------------------------------------------------------------*/ + +class pimpleControl +{ + struct fieldData + { + wordRe name; + scalar relTol; + scalar absTol; + scalar initialResidual; + }; + + + // Private data + + //- Reference to the mesh database + fvMesh& mesh_; + + //- Maximum number of PIMPLE correctors + int nCorr_; + + //- Current PIMPLE corrector + int corr_; + + //- List of residual data per field + List<fieldData> residualControl_; + + + // Private Member Functions + + //- Return index of field in residualControl_ if present + label applyToField(const word& fieldName) const; + + //- Return true if all convergence checks are satified + bool criteriaSatisfied(); + + //- Disallow default bitwise copy construct + pimpleControl(const pimpleControl&); + + //- Disallow default bitwise assignment + void operator=(const pimpleControl&); + + +public: + + + // Static Data Members + + //- Run-time type information + TypeName("pimpleControl"); + + + // Constructors + + //- Construct from mesh + pimpleControl(fvMesh& mesh); + + + //- Destructor + virtual ~pimpleControl(); + + + // Member Functions + + //- Read constrols from fvSolution dictionary + void read(); + + //- Loop start + bool start(); + + //- Loop loop + bool loop(); + + //- Helper function to identify final iteration + bool finalIter() const; + + + // Member Operators + + void operator++(int); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "pimpleControlI.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControlI.H b/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControlI.H new file mode 100644 index 0000000000000000000000000000000000000000..bef9dd016403e3ce5f077667242c95f0d7ab085a --- /dev/null +++ b/src/finiteVolume/cfdTools/general/pimpleControl/pimpleControlI.H @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2011-2011 OpenCFD Ltd. + \\/ 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/>. + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline bool Foam::pimpleControl::start() +{ + corr_ = 0; + + return true; +} + + +inline bool Foam::pimpleControl::loop() +{ + if (criteriaSatisfied()) + { + Info<< "PIMPLE loop converged in " << corr_ << " iterations" << endl; + return false; + } + else + { + if (finalIter()) + { + mesh_.data::add("finalIteration", true); + } + + if (corr_ < nCorr_) + { + Info<< "PIMPLE iteration " << corr_ + 1 << endl; + return true; + } + else + { + Info<< "PIMPLE loop not converged within " << nCorr_ + << " iterations" << endl; + return false; + } + } +} + + +inline bool Foam::pimpleControl::finalIter() const +{ + return corr_ == nCorr_-1; +} + + +inline void Foam::pimpleControl::operator++(int) +{ + if (finalIter()) + { + mesh_.data::remove("finalIteration"); + } + + corr_++; +} + + +// ************************************************************************* //