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-2021 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  for (const entry& dataDictEntry : solverDict)
115  {
116  const word& variableName = dataDictEntry.keyword();
117 
118  const scalar absTol =
119  convergenceDict_.getOrDefault<scalar>(variableName, -1);
120 
121  if (absTol > 0)
122  {
123  // Treat like a SIMPLE control
124 
125  Pair<scalar> residuals =
127  (
128  regionMesh,
129  dataDictEntry
130  );
131 
132  checked = true;
133  achieved = achieved && (residuals.first() < absTol);
134  }
135  }
136  }
137 
138  return checked && achieved;
139 }
140 
141 
142 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
143 
144 Foam::loopControl::loopControl
145 (
146  Time& runTime,
147  const label nCycles,
148  const word& loopName
149 )
150 :
151  subLoopTime(runTime, nCycles),
152  name_(loopName),
153  interval_(0),
154  convergenceDict_(),
155  onLoop_(),
156  onConverged_(),
157  onEnd_(),
158  converged_(false)
159 {}
160 
161 
162 Foam::loopControl::loopControl
163 (
164  Time& runTime,
165  const dictionary& algorithmDict,
166  const word& dictName
167 )
168 :
170 {
171  // The loop sub-dictionary
172  const dictionary* dictptr = algorithmDict.findDict(dictName);
173 
174  if (dictptr)
175  {
176  // Info<< dictName << *dictptr << endl;
177  read(*dictptr);
178  }
179 }
180 
181 
182 Foam::loopControl::loopControl
183 (
184  Time& runTime,
185  const word& algorithmName,
186  const word& dictName
187 )
188 :
190 {
191  fvSolution fvsol(time_);
192 
193  // Eg, PIMPLE or SIMPLE from <system/fvSolution>
194  const dictionary* dictptr = fvsol.solutionDict().findDict(algorithmName);
195 
196  if (dictptr)
197  {
198  // The loop sub-dictionary
199  dictptr = dictptr->findDict(dictName);
200 
201  if (dictptr)
202  {
203  // Info<< dictName << *dictptr << endl;
204  read(*dictptr);
205  }
206  }
207 }
208 
209 
210 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
211 
213 {
214  stop();
215 }
216 
217 
218 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
219 
221 {
222  bool active = (index_ < total_); // as per status()
223 
224  if (active)
225  {
226  operator++();
227 
228  converged_ = checkConverged();
229 
230  if (converged_)
231  {
232  time_.functionObjects().execute(onConverged_, index_);
233  stop();
234  return false;
235  }
236  else if
237  (
238  interval_ && !(index_ % interval_)
239  && !onLoop_.empty()
240  )
241  {
242  time_.functionObjects().execute(onLoop_, index_);
243  }
244  }
245  else if (index_)
246  {
247  // Not active, the loop condition has now exiting on the last subloop
248 
249  if (!converged_ && !onEnd_.empty())
250  {
251  time_.functionObjects().execute(onEnd_, index_);
252  }
253  }
254 
255  return active;
256 }
257 
258 
259 // * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * //
260 
262 {
263  os << ctrl.name() << ": ";
264  if (ctrl.nCycles() && ctrl.index() <= ctrl.nCycles())
265  {
266  os << ctrl.index() << '/' << ctrl.nCycles();
267  }
268  else
269  {
270  os << "off";
271  }
272 
273  return os;
274 }
275 
276 
277 // ************************************************************************* //
Foam::dictionary::findDict
dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary pointer if present.
Definition: dictionaryI.H:127
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:65
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
dictName
const word dictName("faMeshDefinition")
Foam::loopControl::onConverged_
wordRes onConverged_
Function object names to fire on convergence.
Definition: loopControl.H:179
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:212
Foam::loopControl::convergenceDict_
dictionary convergenceDict_
Dictionary for checking convergence (all regions)
Definition: loopControl.H:173
Foam::loopControl::loop
bool loop()
Definition: loopControl.C:220
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
meshes
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
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
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:123
fvSolution.H
os
OBJstream os(runTime.globalPath()/outputName)
Foam::dictionary::subOrEmptyDict
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
Definition: dictionary.C:540
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:342
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:116
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:148
Foam::dictionary::clear
void clear()
Clear the dictionary.
Definition: dictionary.C:857
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:405