solutionControl.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "solutionControl.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 namespace Foam
34 {
36 }
37 
38 
39 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
40 
41 bool Foam::solutionControl::read(const bool absTolOnly)
42 {
43  const dictionary solutionDict(this->dict());
44 
45  // Read solution controls
47  solutionDict.getOrDefault<label>("nNonOrthogonalCorrectors", 0);
49  solutionDict.getOrDefault("momentumPredictor", true);
50  transonic_ = solutionDict.getOrDefault("transonic", false);
51  consistent_ = solutionDict.getOrDefault("consistent", false);
52  frozenFlow_ = solutionDict.getOrDefault("frozenFlow", false);
53 
54  // Read residual information
55  const dictionary residualDict
56  (
57  solutionDict.subOrEmptyDict("residualControl")
58  );
59 
61 
62  for (const entry& dEntry : residualDict)
63  {
64  const word& fName = dEntry.keyword();
65  const label fieldi = applyToField(fName, false);
66  if (fieldi == -1)
67  {
68  fieldData fd;
69  fd.name = fName.c_str();
70 
71  if (absTolOnly)
72  {
73  fd.absTol = residualDict.get<scalar>(fName);
74  fd.relTol = -1;
75  fd.initialResidual = -1;
76  }
77  else if (dEntry.isDict())
78  {
79  const dictionary& fieldDict = dEntry.dict();
80  fd.absTol = fieldDict.get<scalar>("tolerance");
81  fd.relTol = fieldDict.get<scalar>("relTol");
82  fd.initialResidual = 0.0;
83  }
84  else
85  {
87  << "Residual data for " << dEntry.keyword()
88  << " must be specified as a dictionary"
89  << exit(FatalError);
90  }
91 
92  data.append(fd);
93  }
94  else
95  {
96  fieldData& fd = data[fieldi];
97  if (absTolOnly)
98  {
99  fd.absTol = residualDict.get<scalar>(fName);
100  }
101  else if (dEntry.isDict())
102  {
103  const dictionary& fieldDict = dEntry.dict();
104  fd.absTol = fieldDict.get<scalar>("tolerance");
105  fd.relTol = fieldDict.get<scalar>("relTol");
106  }
107  else
108  {
110  << "Residual data for " << dEntry.keyword()
111  << " must be specified as a dictionary"
112  << exit(FatalError);
113  }
114  }
115  }
116 
117  residualControl_.transfer(data);
118 
119  if (debug)
120  {
122  {
123  const fieldData& fd = residualControl_[i];
124  Info<< "residualControl[" << i << "]:" << nl
125  << " name : " << fd.name << nl
126  << " absTol : " << fd.absTol << nl
127  << " relTol : " << fd.relTol << nl
128  << " iniResid : " << fd.initialResidual << endl;
129  }
130  }
131 
132  return true;
133 }
134 
135 
137 {
138  return read(false);
139 }
140 
141 
143 (
144  const word& fieldName,
145  const bool useRegEx
146 ) const
147 {
148  forAll(residualControl_, i)
149  {
150  if (residualControl_[i].name.match(fieldName, !useRegEx))
151  {
152  return i;
153  }
154  }
155 
156  return -1;
157 }
158 
159 
161 {
162 // storePrevIter<label>();
163  storePrevIter<scalar>();
164  storePrevIter<vector>();
165  storePrevIter<sphericalTensor>();
166  storePrevIter<symmTensor>();
167  storePrevIter<tensor>();
168 }
169 
170 
172 (
173  const entry& solverPerfDictEntry
174 ) const
175 {
176  return maxResidual(mesh_, solverPerfDictEntry);
177 }
178 
179 
181 (
182  const bool check,
183  const bool force
184 )
185 {
186  DebugInfo
187  << "solutionControl: force:" << force
188  << " check: " << check
189  << " corr: " << corr_
190  << " corrNonOrtho:" << corrNonOrtho_
191  << endl;
192 
193  if (force || (check && corr_ <= 1 && corrNonOrtho_ == 0))
194  {
195  DebugInfo<< "solutionControl: set firstIteration flag" << endl;
196  mesh_.data().setFirstIteration(true);
197  }
198  else
199  {
200  DebugInfo<< "solutionControl: remove firstIteration flag" << endl;
201  mesh_.data().setFirstIteration(false);
202  }
203 }
204 
205 
206 bool Foam::solutionControl::writeData(Ostream&) const
207 {
209  return false;
210 }
212 
213 
214 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
215 
216 template<class Type>
218 (
219  const fvMesh& fvmesh,
220  const entry& solverPerfDictEntry,
221  Pair<scalar>& residuals
222 )
223 {
225 
226  const word& fieldName = solverPerfDictEntry.keyword();
227 
228  if (fvmesh.foundObject<fieldType>(fieldName))
229  {
230  const List<SolverPerformance<Type>> sp(solverPerfDictEntry.stream());
231 
232  residuals.first() = cmptMax(sp.first().initialResidual());
233  residuals.last() = cmptMax(sp.last().initialResidual());
234 
235  return true;
236  }
237 
238  return false;
239 }
240 
241 
243 (
244  const fvMesh& fvmesh,
245  const entry& solverPerfDictEntry
246 )
247 {
248  Pair<scalar> residuals(0,0);
249 
250  // Check with builtin short-circuit
251  const bool ok =
252  (
253  maxTypeResidual<scalar>(fvmesh, solverPerfDictEntry, residuals)
254  || maxTypeResidual<vector>(fvmesh, solverPerfDictEntry, residuals)
255  || maxTypeResidual<sphericalTensor>(fvmesh, solverPerfDictEntry, residuals)
256  || maxTypeResidual<symmTensor>(fvmesh, solverPerfDictEntry, residuals)
257  || maxTypeResidual<tensor>(fvmesh, solverPerfDictEntry, residuals)
258  );
259 
260  if (!ok && solutionControl::debug)
261  {
262  Info<<"no residual for " << solverPerfDictEntry.keyword()
263  << " on mesh " << fvmesh.name() << nl;
264  }
266  return residuals;
267 }
268 
269 
270 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
271 
272 Foam::solutionControl::solutionControl(fvMesh& mesh, const word& algorithmName)
273 :
275  (
276  IOobject
277  (
278  typeName,
279  mesh.time().timeName(),
280  mesh,
281  IOobject::NO_READ,
282  IOobject::NO_WRITE
283  )
284  ),
285  mesh_(mesh),
286  residualControl_(),
287  algorithmName_(algorithmName),
288  nNonOrthCorr_(0),
289  momentumPredictor_(true),
290  transonic_(false),
291  consistent_(false),
292  frozenFlow_(false),
293  corr_(0),
294  corrNonOrtho_(0)
295 {}
296 
297 
298 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
299 
301 {
302  return mesh_.solutionDict().subOrEmptyDict(algorithmName_);
303 }
304 
305 
306 // ************************************************************************* //
const T & first() const noexcept
Access the first element.
Definition: Pair.H:137
virtual bool writeData(Ostream &) const
Dummy write for regIOobject.
void cmptMax(FieldField< Field, typename FieldField< Field, Type >::cmptType > &cf, const FieldField< Field, Type > &f)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
List< fieldData > residualControl_
List of residual data per field.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Base class for solution control classes.
fvSolution solutionDict(runTime)
virtual label applyToField(const word &fieldName, const bool useRegEx=true) const
Return index of field in residualControl_ if present.
label nNonOrthCorr_
Maximum number of non-orthogonal correctors.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
Generic GeometricField class.
Definition: areaFieldsFwd.H:50
bool match(const std::string &text) const
Test for equality.
Definition: stringI.H:217
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:127
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static Pair< scalar > maxResidual(const fvMesh &fvmesh, const entry &dataDictEntry)
Extract maximum residual for the solver performance entry, provided the corresponding volume field is...
void fieldData(vtk::formatter &fmt, label nFields)
Emit "FIELD FieldData <n>".
word timeName
Definition: getTimeIndex.H:3
const keyType & keyword() const noexcept
Return keyword.
Definition: entry.H:231
dynamicFvMesh & mesh
An ordered pair of two objects of type <T> with first() and second() elements.
Definition: instant.H:46
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
A class for handling words, derived from Foam::string.
Definition: word.H:63
virtual bool read()
Read controls from fvSolution dictionary.
virtual void setFirstIterFlag(const bool check=true, const bool force=false)
Set the firstIteration flag on the mesh data dictionary.
bool transonic_
Flag to indicate to solve using transonic algorithm.
#define DebugInfo
Report an information message using Foam::Info.
int debug
Static debugging option.
defineTypeNameAndDebug(combustionModel, 0)
virtual const dictionary dict() const
Return the solution dictionary.
static void check(const int retVal, const char *what)
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
virtual void storePrevIterFields() const
Store previous iteration fields.
T & last() noexcept
Access last element of the list, position [N-1] - back()
Definition: FixedList.H:737
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
bool momentumPredictor_
Flag to indicate to solve for momentum.
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
bool foundObject(const word &name, const bool recursive=false) const
Is the named Type found?
bool frozenFlow_
Flag to indicate that the flow system of equations should not.
static bool maxTypeResidual(const fvMesh &fvmesh, const entry &solverPerfDictEntry, Pair< scalar > &residuals)
Initial and final residual of the specified field-name, provided that the corresponding volume field ...
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
#define NotImplemented
Issue a FatalErrorIn for a function not currently implemented.
Definition: error.H:686
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
bool consistent_
Flag to indicate to relax pressure using the.
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63