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-------------------------------------------------------------------------------
10License
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
34void Foam::loopControl::clear()
35{
36 total_ = 0;
37 interval_ = 0;
38
40 onLoop_.clear();
42 onEnd_.clear();
43
44 converged_ = false;
45}
46
47
48void 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
97bool 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
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
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
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// ************************************************************************* //
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:116
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
virtual bool read()
Re-read model coefficients if they have changed.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:80
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
Definition: dictionary.C:540
dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary pointer if present.
Definition: dictionaryI.H:127
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
void clear()
Clear the dictionary.
Definition: dictionary.C:857
Selector class for finite volume solution solution. fvMesh is derived from fvSolution so that all fie...
Definition: fvSolution.H:60
A class for managing arbitrary loops with the ability to invoke function object execution.
Definition: loopControl.H:143
~loopControl()
Destructor.
Definition: loopControl.C:212
const word & name() const
Name of the loop control.
Definition: loopControl.H:237
label interval_
The interval to execute onLoop function-objects.
Definition: loopControl.H:170
wordRes onConverged_
Function object names to fire on convergence.
Definition: loopControl.H:179
dictionary convergenceDict_
Dictionary for checking convergence (all regions)
Definition: loopControl.H:173
wordRes onLoop_
Function object names to fire during the loop (at executeInterval)
Definition: loopControl.H:176
bool converged_
Convergence tests passed.
Definition: loopControl.H:186
static Pair< scalar > maxResidual(const fvMesh &fvmesh, const entry &dataDictEntry)
const dictionary & solutionDict() const
Definition: solution.C:355
A class for managing sub-loops referencing Time.
Definition: subLoopTime.H:54
label nCycles() const
The total number of cycles.
Definition: subLoopTime.H:100
label index() const
The current cycle index.
Definition: subLoopTime.H:94
label total_
The total number of cycles in the sub-cycle.
Definition: subLoopTime.H:74
A class for handling words, derived from Foam::string.
Definition: word.H:68
patchWriters clear()
engineTime & runTime
Foam::PtrList< Foam::fvMesh > meshes(regionNames.size())
OBJstream os(runTime.globalPath()/outputName)
const word dictName("faMeshDefinition")
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces)
Definition: boundaryPatch.C:83
dictionary dict
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition: stdFoam.H:278