Loading...
Searching...
No Matches
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
39 convergenceDict_.clear();
40 onLoop_.clear();
41 onConverged_.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 bool achieved = true;
105 bool checked = false; // safety that some checks were indeed performed
106
107 const objectRegistry& obr = time_;
108
109 forAllConstIters(obr, iter)
110 {
111 const fvMesh* meshPtr = dynamic_cast<const fvMesh*>(iter.val());
112 if (!meshPtr) continue;
113 const fvMesh& regionMesh = *meshPtr;
114
115 const dictionary& solverDict =
116 regionMesh.data().solverPerformanceDict();
117 for (const entry& dataDictEntry : solverDict)
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 }
141 return checked && achieved;
142}
143
144
145// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
146
147Foam::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_(),
159 onConverged_(),
160 onEnd_(),
161 converged_(false)
162{}
163
164
165Foam::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)
179 // Info<< dictName << *dictptr << endl;
180 read(*dictptr);
181 }
182}
183
184
185Foam::loopControl::loopControl
186(
187 Time& runTime,
188 const word& algorithmName,
189 const word& dictName
190)
191:
192 loopControl(runTime, 0, dictName)
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);
209 }
210}
211
212
213// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
214
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 }
258 return active;
259}
260
261
262// * * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * //
263
264Foam::Ostream& Foam::operator<<(Ostream& os, const loopControl& ctrl)
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// ************************************************************************* //
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition Ostream.H:59
An ordered pair of two objects of type <T> with first() and second() elements.
Definition Pair.H:66
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition Time.H:75
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
dictionary subOrEmptyDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX, const bool mandatory=false) const
Find and return a sub-dictionary as a copy, otherwise return an empty dictionary.
Definition dictionary.C:521
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and it is a dictionary) otherwise return nullptr...
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
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
Selector class for finite volume solution solution. fvMesh is derived from fvSolution so that all fie...
Definition fvSolution.H:54
A class for managing arbitrary loops with the ability to invoke function object execution.
~loopControl()
Destructor.
word name_
Name of the loop control (the lookup dictionary name).
const word & name() const
Name of the loop control.
label interval_
The interval to execute onLoop function-objects.
wordRes onConverged_
Function object names to fire on convergence.
dictionary convergenceDict_
Dictionary for checking convergence (all regions).
bool loop()
True if looping is active, increments the index and executes the onLoop and onConverged functions.
wordRes onLoop_
Function object names to fire during the loop (at executeInterval).
wordRes onEnd_
Function object names to fire when the loop exits without convergence.
bool converged_
Convergence tests passed.
Registry of regIOobjects.
static Pair< scalar > maxResidual(const fvMesh &fvmesh, const entry &dataDictEntry)
Extract maximum residual for the solver performance entry, provided the corresponding volume field is...
const dictionary & solutionDict() const
The entire dictionary or the optional "select" sub-dictionary.
Definition solution.C:448
A class for managing sub-loops referencing Time.
Definition subLoopTime.H:50
label nCycles() const
The total number of cycles.
label index() const
The current cycle index.
subLoopTime & operator++()
Prefix increment.
Definition subLoopTime.C:73
void stop()
Force terminate the loop.
Definition subLoopTime.C:49
label index_
The current sub-cycle index.
Definition subLoopTime.H:73
label total_
The total number of cycles in the sub-cycle.
Definition subLoopTime.H:78
A class for handling words, derived from Foam::string.
Definition word.H:66
engineTime & runTime
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
OBJstream os(runTime.globalPath()/outputName)
const word dictName("faMeshDefinition")
surface1 clear()
Ostream & operator<<(Ostream &, const boundaryPatch &p)
Write boundaryPatch as dictionary entries (without surrounding braces).
dictionary dict
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235