Loading...
Searching...
No Matches
pimpleControl.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2011-2017 OpenFOAM Foundation
9 Copyright (C) 2017-2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
29#include "pimpleControl.H"
30
31// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32
33namespace Foam
35 defineTypeNameAndDebug(pimpleControl, 0);
36}
37
38
39// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
40
42{
44
45 const dictionary pimpleDict(dict());
46
47 solveFlow_ = pimpleDict.getOrDefault("solveFlow", true);
48 nCorrPIMPLE_ = pimpleDict.getOrDefault<label>("nOuterCorrectors", 1);
49 nCorrPISO_ = pimpleDict.getOrDefault<label>("nCorrectors", 1);
50 SIMPLErho_ = pimpleDict.getOrDefault("SIMPLErho", false);
52 pimpleDict.getOrDefault("turbOnFinalIterOnly", true);
54 pimpleDict.getOrDefault("finalOnLastPimpleIterOnly", false);
55 ddtCorr_ = pimpleDict.getOrDefault("ddtCorr", true);
56
57 return true;
58}
59
60
62{
63 // no checks on first iteration - nothing has been calculated yet
64 if ((corr_ == 1) || residualControl_.empty() || finalIter())
65 {
66 return false;
67 }
68
69
70 const bool storeIni = this->storeInitialResiduals();
71
72 bool achieved = true;
73 bool checked = false; // safety that some checks were indeed performed
74
75 const dictionary& solverDict = mesh_.data().solverPerformanceDict();
76 for (const entry& solverPerfDictEntry : solverDict)
77 {
78 const word& fieldName = solverPerfDictEntry.keyword();
79 const label fieldi = applyToField(fieldName);
80
81 if (fieldi != -1)
82 {
83 Pair<scalar> residuals = maxResidual(solverPerfDictEntry);
84
85 checked = true;
86
87 scalar relative = 0.0;
88 bool relCheck = false;
89
90 const bool absCheck =
91 (residuals.last() < residualControl_[fieldi].absTol);
92
93 if (storeIni)
94 {
95 residualControl_[fieldi].initialResidual = residuals.first();
96 }
97 else
98 {
99 const scalar iniRes =
100 (residualControl_[fieldi].initialResidual + ROOTVSMALL);
101
102 relative = residuals.last() / iniRes;
103 relCheck = (relative < residualControl_[fieldi].relTol);
104 }
105
106 achieved = achieved && (absCheck || relCheck);
107
108 if (debug)
109 {
110 Info<< algorithmName_ << " loop:" << endl;
111
112 Info<< " " << fieldName
113 << " PIMPLE iter " << corr_
114 << ": ini res = "
115 << residualControl_[fieldi].initialResidual
116 << ", abs tol = " << residuals.last()
117 << " (" << residualControl_[fieldi].absTol << ")"
118 << ", rel tol = " << relative
119 << " (" << residualControl_[fieldi].relTol << ")"
120 << endl;
121 }
123 }
124
125 return checked && achieved;
126}
127
128
129void Foam::pimpleControl::setFirstIterFlag(const bool check, const bool force)
130{
132 << "corr:" << corr_
133 << " corrPISO:" << corrPISO_
134 << " corrNonOrtho:" << corrNonOrtho_
135 << endl;
138}
139
140
141// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
142
143Foam::pimpleControl::pimpleControl
144(
145 fvMesh& mesh,
146 const word& dictName,
147 const bool verbose
148)
149:
151 solveFlow_(true),
152 nCorrPIMPLE_(0),
153 nCorrPISO_(0),
154 corrPISO_(0),
155 SIMPLErho_(false),
156 turbOnFinalIterOnly_(true),
157 finalOnLastPimpleIterOnly_(false),
158 ddtCorr_(true),
159 converged_(false)
160{
161 read();
162
163 if (verbose)
164 {
166
167 if (nCorrPIMPLE_ > 1)
168 {
169 if (residualControl_.empty())
170 {
171 Info<< ": no residual control data found. "
172 << "Calculations will employ " << nCorrPIMPLE_
173 << " corrector loops" << nl;
174 }
175 else
176 {
177 Info<< ": max iterations = " << nCorrPIMPLE_ << nl;
178
179 for (const fieldData& ctrl : residualControl_)
180 {
181 Info<< " field " << ctrl.name << token::TAB
182 << ": relTol " << ctrl.relTol
183 << ", tolerance " << ctrl.absTol
184 << nl;
185 }
186 }
187 }
188 else
189 {
190 Info<< ": Operating solver in PISO mode" << nl;
191 }
192
194 }
195}
196
197
198// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
199
201{
202 read();
203
204 ++corr_;
205
206 if (debug)
207 {
208 Info<< algorithmName_ << " loop: corr = " << corr_ << endl;
209 }
210
211 setFirstIterFlag();
212
213 if (corr_ == nCorrPIMPLE_ + 1)
214 {
215 if (!residualControl_.empty() && (nCorrPIMPLE_ != 1))
216 {
217 Info<< algorithmName_ << ": not converged within "
218 << nCorrPIMPLE_ << " iterations" << endl;
219 }
220
221 corr_ = 0;
222 mesh_.data().setFinalIteration(false);
223 return false;
224 }
225
226 bool completed = false;
227 if (converged_ || criteriaSatisfied())
228 {
229 if (converged_)
230 {
231 Info<< algorithmName_ << ": converged in " << corr_ - 1
232 << " iterations" << endl;
233
234 mesh_.data().setFinalIteration(false);
235 corr_ = 0;
236 converged_ = false;
237
238 completed = true;
239 }
240 else
241 {
242 Info<< algorithmName_ << ": iteration " << corr_ << endl;
243 storePrevIterFields();
244
245 mesh_.data().setFinalIteration(true);
246 converged_ = true;
247 }
248 }
249 else
250 {
251 if (finalIter())
252 {
253 mesh_.data().setFinalIteration(true);
254 }
255
256 if (corr_ <= nCorrPIMPLE_)
257 {
258 Info<< algorithmName_ << ": iteration " << corr_ << endl;
259 storePrevIterFields();
260 completed = false;
261 }
262 }
263
264 return !completed;
265}
266
267
268// ************************************************************************* //
const dictionary & pimpleDict
T & last() noexcept
Access last element of the list, position [N-1] - back().
Definition FixedList.H:758
An ordered pair of two objects of type <T> with first() and second() elements.
Definition Pair.H:66
const T & first() const noexcept
Access the first element.
Definition Pair.H:137
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
Mesh data needed to do the Finite Volume discretisation.
Definition fvMesh.H:85
PIMPLE control class to supply convergence information/checks for the PIMPLE loop.
bool SIMPLErho_
Flag to indicate whether to update density in SIMPLE rather than PISO mode.
label corrPISO_
Current PISO corrector.
virtual bool criteriaSatisfied()
Return true if all convergence checks are satisfied.
bool finalIter() const
Return true for final PIMPLE (outer) iteration.
bool finalOnLastPimpleIterOnly_
Flag to indicate wheter the final solver is used only on the final pimple iter.
label nCorrPISO_
Maximum number of PISO correctors.
label nCorrPIMPLE_
Maximum number of PIMPLE correctors.
bool storeInitialResiduals() const
Return true to store the initial residuals.
bool solveFlow_
Flag to indicate whether to solve for the flow.
bool turbOnFinalIterOnly_
Flag to indicate whether to only solve turbulence on final iter.
virtual bool loop()
PIMPLE loop.
bool ddtCorr_
Flag to indicate that ddtCorr should be applied; default = yes.
virtual void setFirstIterFlag(const bool check=true, const bool force=false)
Set the firstIteration flag on the mesh data dictionary.
virtual bool read()
Read controls from fvSolution dictionary.
bool converged_
Converged flag.
Base class for solution control classes.
const word algorithmName_
The dictionary name, e.g. SIMPLE, PIMPLE.
label corrNonOrtho_
Current non-orthogonal corrector loop index.
label corr_
Current corrector loop index.
List< fieldData > residualControl_
List of residual data per field.
virtual const dictionary dict() const
Return the solution dictionary.
fvMesh & mesh_
Reference to the mesh database.
virtual void storePrevIterFields() const
Store previous iteration fields.
virtual label applyToField(const word &fieldName, const bool useRegEx=true) const
Return index of field in residualControl_ if present.
static Pair< scalar > maxResidual(const fvMesh &fvmesh, const entry &dataDictEntry)
Extract maximum residual for the solver performance entry, provided the corresponding volume field is...
virtual void setFirstIterFlag(const bool check=true, const bool force=false)
Set the firstIteration flag on the mesh data dictionary.
virtual bool read()
Read controls from fvSolution dictionary.
@ TAB
Tab [isspace].
Definition token.H:142
A class for handling words, derived from Foam::string.
Definition word.H:66
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
dynamicFvMesh & mesh
const word dictName("faMeshDefinition")
#define DebugInfo
Report an information message using Foam::Info.
Namespace for handling debugging switches.
Definition debug.C:45
tmp< surfaceScalarField > relative(const tmp< surfaceScalarField > &tphi, const volVectorField &U)
Return the given absolute flux in relative form.
Definition fvcMeshPhi.C:148
Namespace for OpenFOAM.
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition int32.H:127
messageStream Info
Information stream (stdout output on master, null elsewhere).
static void check(const int retVal, const char *what)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
Simple convenient storage of field residuals.