loopControl.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) 2017-2020 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "loopControl.H"
29 #include "fvSolution.H"
30 #include "solutionControl.H"
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 void Foam::loopControl::clear()
35 {
36  total_ = 0;
37  interval_ = 0;
38 
40  onLoop_.clear();
42  onEnd_.clear();
43 
44  converged_ = false;
45 }
46 
47 
48 void Foam::loopControl::read(const dictionary& dict)
49 {
50  clear();
51 
52  bool enabled = dict.getOrDefault("enabled", true);
53 
54  if (enabled)
55  {
56  scalar timeStart;
57  if (dict.readIfPresent("timeStart", timeStart))
58  {
59  timeStart = time_.userTimeToTime(timeStart);
60 
61  enabled =
62  (
63  enabled
64  && time_.value() >= (timeStart - 0.5*time_.deltaTValue())
65  );
66  }
67 
68  scalar timeEnd;
69  if (dict.readIfPresent("timeEnd", timeEnd))
70  {
71  timeEnd = time_.userTimeToTime(timeEnd);
72 
73  enabled =
74  (
75  enabled
76  && time_.value() <= (timeEnd + 0.5*time_.deltaTValue())
77  );
78  }
79  }
80 
81  if (!enabled)
82  {
83  return;
84  }
85 
86  dict.readIfPresent("iterations", total_);
87  dict.readIfPresent("interval", interval_);
88 
89  convergenceDict_ = dict.subOrEmptyDict("convergence");
90 
91  dict.readIfPresent("onLoop", onLoop_);
92  dict.readIfPresent("onConverged", onConverged_);
93  dict.readIfPresent("onEnd", onEnd_);
94 }
95 
96 
97 bool Foam::loopControl::checkConverged() const
98 {
99  if (convergenceDict_.empty())
100  {
101  return false;
102  }
103 
104  HashTable<const fvMesh*> meshes = time_.lookupClass<const fvMesh>();
105 
106  bool achieved = true;
107  bool checked = false; // safety that some checks were indeed performed
108 
109  forAllConstIters(meshes, meshIter)
110  {
111  const fvMesh& regionMesh = *(meshIter.val());
112 
113  const dictionary& solverDict = regionMesh.solverPerformanceDict();
114 
115  forAllConstIters(solverDict, iter)
116  {
117  const entry& dataDictEntry = *iter;
118 
119  const word& variableName = dataDictEntry.keyword();
120 
121  const scalar absTol =
122  convergenceDict_.getOrDefault<scalar>(variableName, -1);
123 
124  if (absTol > 0)
125  {
126  // Treat like a SIMPLE control
127 
128  Pair<scalar> residuals =
130  (
131  regionMesh,
132  dataDictEntry
133  );
134 
135  checked = true;
136  achieved = achieved && (residuals.first() < absTol);
137  }
138  }
139  }
140 
141  return checked && achieved;
142 }
143 
144 
145 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
146 
147 Foam::loopControl::loopControl
148 (
149  Time& runTime,
150  const label nCycles,
151  const word& loopName
152 )
153 :
154  subLoopTime(runTime, nCycles),
155  name_(loopName),
156  interval_(0),
157  convergenceDict_(),
158  onLoop_(),
159  onConverged_(),
160  onEnd_(),
161  converged_(false)
162 {}
163 
164 
165 Foam::loopControl::loopControl
166 (
167  Time& runTime,
168  const dictionary& algorithmDict,
169  const word& dictName
170 )
171 :
173 {
174  // The loop sub-dictionary
175  const dictionary* dictptr = algorithmDict.findDict(dictName);
176 
177  if (dictptr)
178  {
179  // Info<< dictName << *dictptr << endl;
180  read(*dictptr);
181  }
182 }
183 
184 
185 Foam::loopControl::loopControl
186 (
187  Time& runTime,
188  const word& algorithmName,
189  const word& dictName
190 )
191 :
193 {
194  fvSolution fvsol(time_);
195 
196  // Eg, PIMPLE or SIMPLE from <system/fvSolution>
197  const dictionary* dictptr = fvsol.solutionDict().findDict(algorithmName);
198 
199  if (dictptr)
200  {
201  // The loop sub-dictionary
202  dictptr = dictptr->findDict(dictName);
203 
204  if (dictptr)
205  {
206  // Info<< dictName << *dictptr << endl;
207  read(*dictptr);
208  }
209  }
210 }
211 
212 
213 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
214 
216 {
217  stop();
218 }
219 
220 
221 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
222 
224 {
225  bool active = (index_ < total_); // as per status()
226 
227  if (active)
228  {
229  operator++();
230 
231  converged_ = checkConverged();
232 
233  if (converged_)
234  {
235  time_.functionObjects().execute(onConverged_, index_);
236  stop();
237  return false;
238  }
239  else if
240  (
241  interval_ && !(index_ % interval_)
242  && !onLoop_.empty()
243  )
244  {
245  time_.functionObjects().execute(onLoop_, index_);
246  }
247  }
248  else if (index_)
249  {
250  // Not active, the loop condition has now exiting on the last subloop
251 
252  if (!converged_ && !onEnd_.empty())
253  {
254  time_.functionObjects().execute(onEnd_, index_);
255  }
256  }
257 
258  return active;
259 }
260 
261 
262 // * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * //
263 
265 {
266  os << ctrl.name() << ": ";
267  if (ctrl.nCycles() && ctrl.index() <= ctrl.nCycles())
268  {
269  os << ctrl.index() << '/' << ctrl.nCycles();
270  }
271  else
272  {
273  os << "off";
274  }
275 
276  return os;
277 }
278 
279 
280 // ************************************************************************* //
Foam::dictionary::findDict
dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary pointer if present.
Definition: dictionary.C:508
Foam::loopControl::onLoop_
wordRes onLoop_
Function object names to fire during the loop (at executeInterval)
Definition: loopControl.H:176
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
Foam::loopControl::onConverged_
wordRes onConverged_
Function object names to fire on convergence.
Definition: loopControl.H:179
dictName
const word dictName("blockMeshDict")
Foam::loopControl
A class for managing arbitrary loops with the ability to invoke function object execution.
Definition: loopControl.H:140
solutionControl.H
Foam::loopControl::~loopControl
~loopControl()
Destructor.
Definition: loopControl.C:215
Foam::loopControl::convergenceDict_
dictionary convergenceDict_
Dictionary for checking convergence (all regions)
Definition: loopControl.H:173
Foam::loopControl::loop
bool loop()
Definition: loopControl.C:223
Foam::operator<<
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:83
Foam::loopControl::onEnd_
wordRes onEnd_
Definition: loopControl.H:183
Foam::subLoopTime::nCycles
label nCycles() const
The total number of cycles.
Definition: subLoopTime.H:100
Foam::loopControl::name
const word & name() const
Name of the loop control.
Definition: loopControl.H:237
Foam::fvSolution
Selector class for finite volume solution solution. fvMesh is derived from fvSolution so that all fie...
Definition: fvSolution.H:50
meshes
PtrList< fvMesh > meshes(regionNames.size())
Foam::solutionControl::maxResidual
static Pair< scalar > maxResidual(const fvMesh &fvmesh, const entry &dataDictEntry)
Definition: solutionControl.C:243
Foam::subLoopTime
A class for managing sub-loops referencing Time.
Definition: subLoopTime.H:53
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
fvSolution.H
Foam::dictionary::subOrEmptyDict
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
Definition: dictionary.C:608
Foam::loopControl::converged_
bool converged_
Convergence tests passed.
Definition: loopControl.H:186
Foam::solution::solutionDict
const dictionary & solutionDict() const
Return the selected sub-dictionary of solvers if the "select".
Definition: solution.C:346
clear
patchWriters clear()
Foam::subLoopTime::index
label index() const
The current cycle index.
Definition: subLoopTime.H:94
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
loopControl.H
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:115
Foam::subLoopTime::total_
label total_
The total number of cycles in the sub-cycle.
Definition: subLoopTime.H:74
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:122
Foam::dictionary::clear
void clear()
Clear the dictionary.
Definition: dictionary.C:924
Foam::loopControl::interval_
label interval_
The interval to execute onLoop function-objects.
Definition: loopControl.H:170
Foam::dictionary::readIfPresent
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:417