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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "pimpleControl.H"
27 #include "Switch.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
33  defineTypeNameAndDebug(pimpleControl, 0);
34 }
35 
36 
37 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
38 
40 {
41  solutionControl::read(false);
42 
43  // Read solution controls
44  const dictionary& pimpleDict = dict();
45  nCorrPIMPLE_ = pimpleDict.lookupOrDefault<label>("nOuterCorrectors", 1);
46  nCorrPISO_ = pimpleDict.lookupOrDefault<label>("nCorrectors", 1);
47  turbOnFinalIterOnly_ =
48  pimpleDict.lookupOrDefault<Switch>("turbOnFinalIterOnly", true);
49 }
50 
51 
53 {
54  // no checks on first iteration - nothing has been calculated yet
55  if ((corr_ == 1) || residualControl_.empty() || finalIter())
56  {
57  return false;
58  }
59 
60 
61  bool storeIni = this->storeInitialResiduals();
62 
63  bool achieved = true;
64  bool checked = false; // safety that some checks were indeed performed
65 
66  const dictionary& solverDict = mesh_.solverPerformanceDict();
67  forAllConstIter(dictionary, solverDict, iter)
68  {
69  const word& variableName = iter().keyword();
70  const label fieldI = applyToField(variableName);
71  if (fieldI != -1)
72  {
73  const List<solverPerformance> sp(iter().stream());
74  const scalar residual = sp.last().initialResidual();
75 
76  checked = true;
77 
78  if (storeIni)
79  {
80  residualControl_[fieldI].initialResidual =
81  sp.first().initialResidual();
82  }
83 
84  const bool absCheck = residual < residualControl_[fieldI].absTol;
85  bool relCheck = false;
86 
87  scalar relative = 0.0;
88  if (!storeIni)
89  {
90  const scalar iniRes =
91  residualControl_[fieldI].initialResidual
92  + ROOTVSMALL;
93 
94  relative = residual/iniRes;
95  relCheck = relative < residualControl_[fieldI].relTol;
96  }
97 
98  achieved = achieved && (absCheck || relCheck);
99 
100  if (debug)
101  {
102  Info<< algorithmName_ << " loop:" << endl;
103 
104  Info<< " " << variableName
105  << " PIMPLE iter " << corr_
106  << ": ini res = "
107  << residualControl_[fieldI].initialResidual
108  << ", abs tol = " << residual
109  << " (" << residualControl_[fieldI].absTol << ")"
110  << ", rel tol = " << relative
111  << " (" << residualControl_[fieldI].relTol << ")"
112  << endl;
113  }
114  }
115  }
116 
117  return checked && achieved;
118 }
119 
120 
121 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
122 
123 Foam::pimpleControl::pimpleControl(fvMesh& mesh, const word& dictName)
124 :
125  solutionControl(mesh, dictName),
126  nCorrPIMPLE_(0),
127  nCorrPISO_(0),
128  corrPISO_(0),
129  turbOnFinalIterOnly_(true),
130  converged_(false)
131 {
132  read();
133 
134  if (nCorrPIMPLE_ > 1)
135  {
136  Info<< nl;
137  if (residualControl_.empty())
138  {
139  Info<< algorithmName_ << ": no residual control data found. "
140  << "Calculations will employ " << nCorrPIMPLE_
141  << " corrector loops" << nl << endl;
142  }
143  else
144  {
145  Info<< algorithmName_ << ": max iterations = " << nCorrPIMPLE_
146  << endl;
148  {
149  Info<< " field " << residualControl_[i].name << token::TAB
150  << ": relTol " << residualControl_[i].relTol
151  << ", tolerance " << residualControl_[i].absTol
152  << nl;
153  }
154  Info<< endl;
155  }
156  }
157  else
158  {
159  Info<< nl << algorithmName_ << ": Operating solver in PISO mode" << nl
160  << endl;
161  }
162 }
163 
164 
165 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
166 
168 {}
169 
170 
171 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
172 
174 {
175  read();
176 
177  corr_++;
178 
179  if (debug)
180  {
181  Info<< algorithmName_ << " loop: corr = " << corr_ << endl;
182  }
183 
184  if (corr_ == nCorrPIMPLE_ + 1)
185  {
186  if ((!residualControl_.empty()) && (nCorrPIMPLE_ != 1))
187  {
188  Info<< algorithmName_ << ": not converged within "
189  << nCorrPIMPLE_ << " iterations" << endl;
190  }
191 
192  corr_ = 0;
193  mesh_.data::remove("finalIteration");
194  return false;
195  }
196 
197  bool completed = false;
198  if (converged_ || criteriaSatisfied())
199  {
200  if (converged_)
201  {
202  Info<< algorithmName_ << ": converged in " << corr_ - 1
203  << " iterations" << endl;
204 
205  mesh_.data::remove("finalIteration");
206  corr_ = 0;
207  converged_ = false;
208 
209  completed = true;
210  }
211  else
212  {
213  Info<< algorithmName_ << ": iteration " << corr_ << endl;
215 
216  mesh_.data::add("finalIteration", true);
217  converged_ = true;
218  }
219  }
220  else
221  {
222  if (finalIter())
223  {
224  mesh_.data::add("finalIteration", true);
225  }
226 
227  if (corr_ <= nCorrPIMPLE_)
228  {
229  Info<< algorithmName_ << ": iteration " << corr_ << endl;
231  completed = false;
232  }
233  }
234 
235  return !completed;
236 }
237 
238 
239 // ************************************************************************* //
Base class for solution control classes.
virtual void storePrevIterFields() const
Store previous iteration fields.
fvMesh & mesh_
Reference to the mesh database.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
bool converged_
Converged flag.
Definition: pimpleControl.H:81
virtual void read()
Read controls from fvSolution dictionary.
Definition: pimpleControl.C:39
virtual void read()
Read controls from fvSolution dictionary.
T & last()
Return the last element of the list.
Definition: UListI.H:131
const Type & initialResidual() const
Return initial residual.
A class for handling words, derived from string.
Definition: word.H:59
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
bool finalIter() const
Helper function to identify final PIMPLE (outer) iteration.
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, y/n, t/f, or none.
Definition: Switch.H:60
label nCorrPIMPLE_
Maximum number of PIMPLE correctors.
Definition: pimpleControl.H:69
messageStream Info
dynamicFvMesh & mesh
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
T & first()
Return the first element of the list.
Definition: UListI.H:117
Namespace for OpenFOAM.
virtual bool loop()
PIMPLE loop.
const word dictName("particleTrackDict")
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
virtual ~pimpleControl()
Destructor.
dictionary dict
static const char nl
Definition: Ostream.H:260
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
tmp< surfaceScalarField > relative(const tmp< surfaceScalarField > &tphi, const volVectorField &U)
Return the given absolute flux in relative form.
Definition: fvcMeshPhi.C:152
#define forAll(list, i)
Definition: UList.H:421
List< fieldData > residualControl_
List of residual data per field.
label corr_
Current corrector loop index.
T lookupOrDefault(const word &, const T &, bool recursive=false, bool patternMatch=true) const
Find and return a T,.
const dictionary & pimpleDict
Definition: setRDeltaT.H:29
virtual bool criteriaSatisfied()
Return true if all convergence checks are satisfied.
Definition: pimpleControl.C:52
const word algorithmName_
The dictionary name, e.g. SIMPLE, PIMPLE.
defineTypeNameAndDebug(combustionModel, 0)