solution.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2020 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "solution.H"
27 #include "Time.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
33  defineTypeNameAndDebug(solution, 0);
34 }
35 
36 // List of sub-dictionaries to rewrite
38 (
39  Foam::IStringStream("(preconditioner smoother)")()
40 );
41 
42 
43 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
44 
45 void Foam::solution::read(const dictionary& dict)
46 {
47  if (dict.found("cache"))
48  {
49  cache_ = dict.subDict("cache");
50  caching_ = cache_.lookupOrDefault("active", true);
51  }
52 
53  if (dict.found("relaxationFactors"))
54  {
55  const dictionary& relaxDict(dict.subDict("relaxationFactors"));
56  if (relaxDict.found("fields") || relaxDict.found("equations"))
57  {
58  if (relaxDict.found("fields"))
59  {
60  fieldRelaxDict_ = relaxDict.subDict("fields");
61  }
62 
63  if (relaxDict.found("equations"))
64  {
65  eqnRelaxDict_ = relaxDict.subDict("equations");
66  }
67  }
68  else
69  {
70  // backwards compatibility
71  fieldRelaxDict_.clear();
72 
73  const wordList entryNames(relaxDict.toc());
74  forAll(entryNames, i)
75  {
76  const word& e = entryNames[i];
77  scalar value = relaxDict.lookup<scalar>(e);
78 
79  if (e(0, 1) == "p")
80  {
81  fieldRelaxDict_.add(e, value);
82  }
83  else if (e.length() >= 3)
84  {
85  if (e(0, 3) == "rho")
86  {
87  fieldRelaxDict_.add(e, value);
88  }
89  }
90 
91  }
92 
93  eqnRelaxDict_ = relaxDict;
94  }
95 
96  fieldRelaxDefault_ =
97  fieldRelaxDict_.lookupOrDefault<scalar>("default", 0.0);
98 
99  eqnRelaxDefault_ =
100  eqnRelaxDict_.lookupOrDefault<scalar>("default", 0.0);
101 
102  if (debug)
103  {
104  Info<< "Relaxation factors:" << nl
105  << "fields: " << fieldRelaxDict_ << nl
106  << "equations: " << eqnRelaxDict_ << endl;
107  }
108  }
109 
110 
111  if (dict.found("solvers"))
112  {
113  solvers_ = dict.subDict("solvers");
114  upgradeSolverDict(solvers_);
115  }
116 }
117 
118 
119 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
120 
122 (
123  const objectRegistry& obr,
124  const fileName& dictName
125 )
126 :
128  (
129  IOobject
130  (
131  dictName,
132  obr.time().system(),
133  obr,
134  (
138  : obr.readOpt()
139  ),
141  )
142  ),
143  cache_(dictionary::null),
144  caching_(false),
145  fieldRelaxDict_(dictionary::null),
146  eqnRelaxDict_(dictionary::null),
147  fieldRelaxDefault_(0),
148  eqnRelaxDefault_(0),
149  solvers_(dictionary::null)
150 {
151  if
152  (
153  readOpt() == IOobject::MUST_READ
154  || readOpt() == IOobject::MUST_READ_IF_MODIFIED
155  || (readOpt() == IOobject::READ_IF_PRESENT && headerOk())
156  )
157  {
158  read(solutionDict());
159  }
160 }
161 
162 
163 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
164 
166 (
167  dictionary& dict,
168  const bool verbose
169 )
170 {
171  label nChanged = 0;
172 
173  // backward compatibility:
174  // recast primitive entries into dictionary entries
175  forAllIter(dictionary, dict, iter)
176  {
177  if (!iter().isDict())
178  {
179  Istream& is = iter().stream();
180  word name(is);
181  dictionary subdict;
182 
183  subdict.add("solver", name);
184  subdict <<= dictionary(is);
185 
186  // preconditioner and smoother entries can be
187  // 1) primitiveEntry w/o settings,
188  // 2) or a dictionaryEntry.
189  // transform primitiveEntry with settings -> dictionaryEntry
190  forAll(subDictNames, dictI)
191  {
192  const word& dictName = subDictNames[dictI];
193  entry* ePtr = subdict.lookupEntryPtr(dictName,false,false);
194 
195  if (ePtr && !ePtr->isDict())
196  {
197  Istream& is = ePtr->stream();
198  is >> name;
199 
200  if (!is.eof())
201  {
202  dictionary newDict;
203  newDict.add(dictName, name);
204  newDict <<= dictionary(is);
205 
206  subdict.set(dictName, newDict);
207  }
208  }
209  }
210 
211  // write out information to help people adjust to the new syntax
212  if (verbose && Pstream::master())
213  {
214  Info<< "// using new solver syntax:\n"
215  << iter().keyword() << subdict << endl;
216  }
217 
218  // overwrite with dictionary entry
219  dict.set(iter().keyword(), subdict);
220 
221  nChanged++;
222  }
223  }
224 
225  return nChanged;
226 }
227 
228 
229 bool Foam::solution::cache(const word& name) const
230 {
231  if (caching_)
232  {
233  if (debug)
234  {
235  Info<< "Cache: find entry for " << name << endl;
236  }
237 
238  return cache_.found(name);
239  }
240  else
241  {
242  return false;
243  }
244 }
245 
246 
248 {
249  if (debug)
250  {
251  Info<< "Field relaxation factor for " << name
252  << " is " << (fieldRelaxDict_.found(name) ? "set" : "unset")
253  << endl;
254  }
255 
256  return fieldRelaxDict_.found(name) || fieldRelaxDict_.found("default");
257 }
258 
259 
261 {
262  if (debug)
263  {
264  Info<< "Find equation relaxation factor for " << name << endl;
265  }
266 
267  return eqnRelaxDict_.found(name) || eqnRelaxDict_.found("default");
268 }
269 
270 
272 {
273  if (debug)
274  {
275  Info<< "Lookup variable relaxation factor for " << name << endl;
276  }
277 
278  if (fieldRelaxDict_.found(name))
279  {
280  return fieldRelaxDict_.lookup<scalar>(name);
281  }
282  else if (fieldRelaxDefault_ > small)
283  {
284  return fieldRelaxDefault_;
285  }
286  else
287  {
289  (
290  fieldRelaxDict_
291  ) << "Cannot find variable relaxation factor for '" << name
292  << "' or a suitable default value."
293  << exit(FatalIOError);
294 
295  return 0;
296  }
297 }
298 
299 
301 {
302  if (debug)
303  {
304  Info<< "Lookup equation relaxation factor for " << name << endl;
305  }
306 
307  if (eqnRelaxDict_.found(name))
308  {
309  return eqnRelaxDict_.lookup<scalar>(name);
310  }
311  else if (eqnRelaxDefault_ > small)
312  {
313  return eqnRelaxDefault_;
314  }
315  else
316  {
318  (
319  eqnRelaxDict_
320  ) << "Cannot find equation relaxation factor for '" << name
321  << "' or a suitable default value."
322  << exit(FatalIOError);
323 
324  return 0;
325  }
326 }
327 
328 
330 {
331  if (found("select"))
332  {
333  return subDict(word(lookup("select")));
334  }
335  else
336  {
337  return *this;
338  }
339 }
340 
341 
343 {
344  if (debug)
345  {
346  Info<< "Lookup solver for " << name << endl;
347  }
348 
349  return solvers_.subDict(name);
350 }
351 
352 
354 {
355  if (regIOobject::read())
356  {
357  read(solutionDict());
358 
359  return true;
360  }
361  else
362  {
363  return false;
364  }
365 }
366 
367 
368 // ************************************************************************* //
scalar equationRelaxationFactor(const word &name) const
Return the relaxation factor for the given eqation.
Definition: solution.C:300
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A class for handling file names.
Definition: fileName.H:79
const entry * lookupEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:682
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
virtual bool read()
Read object.
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:156
bool read()
Read the solution dictionary.
Definition: solution.C:353
#define forAllIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:459
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:423
bool relaxField(const word &name) const
Return true if the relaxation factor is given for the field.
Definition: solution.C:247
const dictionary & solverDict(const word &name) const
Return the solver controls dictionary for the given field.
Definition: solution.C:342
bool relaxEquation(const word &name) const
Return true if the relaxation factor is given for the equation.
Definition: solution.C:260
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1133
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:53
bool read(const char *, int32_t &)
Definition: int32IO.C:85
stressControl lookup("compactNormalStress") >> compactNormalStress
static const Foam::List< Foam::word > subDictNames(Foam::IStringStream("(preconditioner smoother)")())
A class for handling words, derived from string.
Definition: word.H:59
const dictionary & solutionDict() const
Return the selected sub-dictionary of solvers if the "select".
Definition: solution.C:329
bool cache(const word &name) const
Return true if the given field should be cached.
Definition: solution.C:229
static const dictionary null
Null dictionary.
Definition: dictionary.H:242
bool eof() const
Return true if end of input seen.
Definition: IOstream.H:336
const word & system() const
Return system name.
Definition: TimePaths.H:113
virtual bool isDict() const
Return true if this entry is a dictionary.
Definition: entry.H:156
solution(const objectRegistry &obr, const fileName &dictName)
Construct for given objectRegistry and dictionary.
Definition: solution.C:122
static const char nl
Definition: Ostream.H:260
const Time & time() const
Return time.
defineTypeNameAndDebug(combustionModel, 0)
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
List< word > wordList
A List of words.
Definition: fileName.H:54
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:335
Input from memory buffer stream.
Definition: IStringStream.H:49
scalar fieldRelaxationFactor(const word &name) const
Return the relaxation factor for the given field.
Definition: solution.C:271
void set(entry *)
Assign a new entry, overwrite any existing entry.
Definition: dictionary.C:1271
messageStream Info
const doubleScalar e
Elementary charge.
Definition: doubleScalar.H:105
Registry of regIOobjects.
virtual ITstream & stream() const =0
Return token stream if this entry is a primitive entry.
readOption readOpt() const
Definition: IOobject.H:353
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92
bool found
static label upgradeSolverDict(dictionary &dict, const bool verbose=true)
Update from older solver controls syntax.
Definition: solution.C:166
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:65
IOerror FatalIOError