solution.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) 2019-2024 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 "solution.H"
30 #include "HashPtrTable.H"
31 #include "Function1.H"
32 #include "Time.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38  defineDebugSwitchWithName(solution, "solution", 0);
39  registerDebugSwitchWithName(solution, solution, "solution");
40 }
41 
42 // List of sub-dictionaries to rewrite
44 ({
45  "preconditioner",
46  "smoother"
47 });
48 
49 
50 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
51 
52 void Foam::solution::read(const dictionary& dict)
53 {
54  const dictionary* dictptr;
55 
56  if ((dictptr = dict.findDict("cache")) != nullptr)
57  {
58  cache_ = *dictptr;
59  caching_ = cache_.getOrDefault("active", true);
60  }
61 
62  if ((dictptr = dict.findDict("relaxationFactors")) != nullptr)
63  {
64  const dictionary& relaxDict = *dictptr;
65 
66  bool needsCompat = true;
67 
68  if ((dictptr = relaxDict.findDict("fields")) != nullptr)
69  {
70  needsCompat = false;
71  fieldRelaxDict_ = *dictptr;
72  fieldRelaxCache_.clear();
73  }
74 
75  if ((dictptr = relaxDict.findDict("equations")) != nullptr)
76  {
77  needsCompat = false;
78  eqnRelaxDict_ = *dictptr;
79  eqnRelaxCache_.clear();
80  }
81 
82  if (needsCompat)
83  {
84  // backwards compatibility
85  fieldRelaxDict_.clear();
86  fieldRelaxCache_.clear();
87 
88  for (const word& e : relaxDict.toc())
89  {
90  scalar value = relaxDict.get<scalar>(e);
91 
92  if (e.starts_with('p'))
93  {
94  fieldRelaxDict_.add(e, value);
95  }
96  else if (e.starts_with("rho"))
97  {
98  fieldRelaxDict_.add(e, value);
99  }
100  }
101 
102  eqnRelaxDict_ = relaxDict;
103  eqnRelaxCache_.clear();
104  }
105 
106 
107  fieldRelaxDefault_ = Function1<scalar>::NewIfPresent
108  (
109  "default",
110  fieldRelaxDict_,
111  &db()
112  );
113  if (!fieldRelaxDefault_)
114  {
115  fieldRelaxDefault_.reset
116  (
117  new Function1Types::Constant<scalar>("default", 0, &db())
118  );
119  }
120 
121  eqnRelaxDefault_ = Function1<scalar>::NewIfPresent
122  (
123  "default",
124  eqnRelaxDict_,
125  &db()
126  );
127  if (!eqnRelaxDefault_)
128  {
129  eqnRelaxDefault_.reset
130  (
131  new Function1Types::Constant<scalar>("default", 0, &db())
132  );
133  }
134 
135  DebugInfo
136  << "Relaxation factors:" << nl
137  << "fields: " << fieldRelaxDict_ << nl
138  << "equations: " << eqnRelaxDict_ << endl;
139  }
140 
141  if ((dictptr = dict.findDict("solvers")) != nullptr)
142  {
143  solvers_ = *dictptr;
144  upgradeSolverDict(solvers_);
145  }
146 }
147 
148 
149 const Foam::dictionary& Foam::solution::selectedDict() const
150 {
151  word select;
152 
153  if (readIfPresent("select", select, keyType::LITERAL))
154  {
155  return subDict(select);
156  }
157 
158  return *this;
159 }
160 
161 
162 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
163 
164 Foam::solution::solution
165 (
166  const objectRegistry& obr,
168  const fileName& dictName,
169  const dictionary* fallback
170 )
171 :
173  (
174  IOobject
175  (
176  dictName,
177  obr.time().system(),
178  obr,
179  rOpt,
180  IOobjectOption::NO_WRITE
181  ),
182  fallback
183  ),
184  cache_(),
185  caching_(false),
186  fieldRelaxDict_(),
187  eqnRelaxDict_(),
188  solvers_()
189 {
190  // Treat as READ_MODIFIED whenever possible
191  if
192  (
194  || (isReadOptional() && headerOk())
195  )
196  {
198  addWatch();
199  }
200 
201  // Update: from values read or copied in
202  if
203  (
205  || !dictionary::empty()
206  )
207  {
208  read(selectedDict());
209  }
210 }
211 
212 
213 Foam::solution::solution
214 (
215  const objectRegistry& obr,
216  const fileName& dictName,
217  const dictionary* fallback
218 )
219 :
220  solution(obr, obr.readOpt(), dictName, fallback)
221 {}
222 
223 
224 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
225 
226 // No default destructor in header (incomplete types)
228 {}
229 
230 
231 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
232 
234 (
235  dictionary& dict,
236  const bool verbose
237 )
238 {
239  label nChanged = 0;
240 
241  // backward compatibility:
242  // recast primitive entries into dictionary entries
243  for (const entry& dEntry : dict)
244  {
245  if (dEntry.isStream())
246  {
247  ITstream& is = dEntry.stream();
248  word name(is);
249  dictionary subdict;
250 
251  subdict.add("solver", name);
252  subdict <<= dictionary(is);
253 
254  // preconditioner and smoother entries can be
255  // 1) primitiveEntry w/o settings,
256  // 2) or a dictionaryEntry.
257  // transform primitiveEntry with settings -> dictionaryEntry
258  for (const word& dictName : subDictNames)
259  {
260  ITstream* streamPtr =
262 
263  if (streamPtr)
264  {
265  auto& is = *streamPtr;
266  is >> name;
267 
268  if (!is.eof())
269  {
270  dictionary newDict;
271  newDict.add(dictName, name);
272  newDict <<= dictionary(is);
273 
274  subdict.set(dictName, newDict);
275  }
276  }
277  }
278 
279  // write out information to help people adjust to the new syntax
280  if (verbose && Pstream::master())
281  {
282  Info<< "// using new solver syntax:\n"
283  << dEntry.keyword() << subdict << endl;
284  }
285 
286  // overwrite with dictionary entry
287  dict.set(dEntry.keyword(), subdict);
288 
289  ++nChanged;
290  }
291  }
292 
293  return nChanged;
294 }
295 
296 
297 bool Foam::solution::cache(const word& name) const
298 {
299  if (caching_)
300  {
301  DebugInfo<< "Cache: find entry for " << name << endl;
302  return cache_.found(name);
303  }
304 
305  return false;
306 }
307 
308 
309 // void Foam::solution::enableCache(const word& name) const
310 // {
311 // if (!cache_.found(name))
312 // {
313 // DebugInfo<< "Cache: enable cache for " << name << endl;
314 // cache_.add(name, true);
315 // caching_ = true;
316 // }
317 // }
318 
319 
320 bool Foam::solution::relaxField(const word& name) const
321 {
322  DebugInfo
323  << "Field relaxation factor for " << name
324  << " is " << (fieldRelaxDict_.found(name) ? "set" : "unset") << endl;
325 
326  return fieldRelaxDict_.found(name) || fieldRelaxDict_.found("default");
327 }
328 
329 
331 {
332  DebugInfo<< "Find equation relaxation factor for " << name << endl;
333  return eqnRelaxDict_.found(name) || eqnRelaxDict_.found("default");
334 }
335 
336 
337 bool Foam::solution::relaxField(const word& name, scalar& factor) const
338 {
339  DebugInfo<< "Lookup field relaxation factor for " << name << endl;
340 
341  if (fieldRelaxDict_.found(name))
342  {
343  factor = Function1<scalar>::New
344  (
345  fieldRelaxCache_, // cache
346  name,
347  fieldRelaxDict_,
349  &db()
350  )().value(time().timeOutputValue());
351 
352  DebugInfo
353  << "Field relaxation factor for " << name
354  << " is " << factor
355  << " (from Function1)" << endl;
356 
357  return true;
358  }
359  else if (fieldRelaxDict_.found("default") && fieldRelaxDefault_)
360  {
361  factor = fieldRelaxDefault_->value(time().timeOutputValue());
362 
363  DebugInfo
364  << "Field relaxation factor for " << name
365  << " is " << factor
366  << " (from default " << eqnRelaxDefault_->type() << ')' << endl;
367 
368  return true;
369  }
370 
371  // Fallthrough - nothing found
373  DebugInfo<< "No field relaxation factor for " << name << endl;
374 
375  return false;
376 }
377 
378 
379 bool Foam::solution::relaxEquation(const word& name, scalar& factor) const
380 {
381  DebugInfo<< "Lookup equation relaxation factor for " << name << endl;
382 
383  if (eqnRelaxDict_.found(name))
384  {
385  factor = Function1<scalar>::New
386  (
387  eqnRelaxCache_, // cache
388  name,
389  eqnRelaxDict_,
391  &db()
392  )().value(time().timeOutputValue());
393 
394  DebugInfo
395  << "Equation relaxation factor for " << name
396  << " is " << factor
397  << " (from Function1)" << endl;
398 
399  return true;
400  }
401  else if (eqnRelaxDict_.found("default") && eqnRelaxDefault_)
402  {
403  factor = eqnRelaxDefault_->value(time().timeOutputValue());
404 
405  DebugInfo
406  << "Equation relaxation factor for " << name
407  << " is " << factor
408  << " (from default " << eqnRelaxDefault_->type() << ')' << endl;
409 
410  return true;
411  }
412 
413  // Fallthrough - nothing found
415  DebugInfo<< "No equation relaxation factor for " << name << endl;
416 
417  return false;
418 }
419 
420 
421 Foam::scalar Foam::solution::fieldRelaxationFactor(const word& name) const
422 {
423  // Any initial value
424  scalar factor = 0;
425 
426  if (!relaxField(name, factor))
427  {
428  FatalIOErrorInFunction(fieldRelaxDict_)
429  << "Cannot find field relaxation factor for '" << name
430  << "' or a suitable default value." << nl
432  }
433 
434  return factor;
435 }
436 
437 
438 Foam::scalar Foam::solution::equationRelaxationFactor(const word& name) const
439 {
440  // Any initial value
441  scalar factor = 0;
442 
443  if (!relaxEquation(name, factor))
444  {
445  FatalIOErrorInFunction(eqnRelaxDict_)
446  << "Cannot find equation relaxation factor for '" << name
447  << "' or a suitable default value."
449  }
450 
451  return factor;
452 }
453 
456 {
457  return selectedDict();
458 }
459 
460 
462 {
463  DebugInfo<< "Lookup subDict : " << name << endl;
464  return selectedDict().subDict(name);
465 }
466 
469 {
470  return solvers_;
471 }
472 
473 
475 {
476  DebugInfo<< "Lookup solver for " << name << endl;
477  return solvers_.subDict(name);
478 }
479 
480 
482 {
483  DebugInfo<< "Lookup solver for " << name << endl;
484  return solvers_.subDict(name);
485 }
486 
487 
489 {
490  if (regIOobject::read())
491  {
492  read(selectedDict());
493 
494  return true;
495  }
496 
497  return false;
498 }
499 
500 
501 // ************************************************************************* //
Top level data entry class for use in dictionaries. Provides a mechanism to specify a variable as a c...
scalar equationRelaxationFactor(const word &name) const
Get the relaxation factor for the given equation. Fatal if not found.
Definition: solution.C:431
dictionary dict
A class for handling file names.
Definition: fileName.H:72
readOption readOpt() const noexcept
Get the read option.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
virtual bool read()
Read object.
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
defineDebugSwitchWithName(pointMVCWeight, "pointMVCWeight", 0)
bool read()
Read the solution dictionary.
Definition: solution.C:481
ITstream * findStream(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return an entry stream if present (and it is a stream) otherwise return nullptr.
Definition: dictionaryI.H:144
static const Foam::List< Foam::word > subDictNames({ "preconditioner", "smoother" })
List< bool > select(const label n, const labelUList &locations)
Construct a selection list of bools (all false) with the given pre-size, subsequently add specified l...
Definition: BitOps.C:134
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
const dictionary & solver(const word &name) const
The solver controls dictionary for the given field. Same as solverDict(...)
Definition: solution.C:474
const word dictName("faMeshDefinition")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
bool headerOk()
Read and check header info. Does not check the headerClassName.
Definition: regIOobject.C:505
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:625
bool relaxField(const word &name) const
True if the relaxation factor is given for the field.
Definition: solution.C:313
const dictionary & solverDict(const word &name) const
The solver controls dictionary for the given field. Same as solversDict().subDict(...)
Definition: solution.C:467
bool isReadOptional() const noexcept
True if (LAZY_READ) bits are set [same as READ_IF_PRESENT].
bool relaxEquation(const word &name) const
True if the relaxation factor is given for the equation.
Definition: solution.C:323
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:127
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
dictionary()
Default construct, a top-level empty dictionary.
Definition: dictionary.C:68
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
A class for handling words, derived from Foam::string.
Definition: word.H:63
const dictionary & solutionDict() const
The entire dictionary or the optional "select" sub-dictionary.
Definition: solution.C:448
bool cache(const word &name) const
True if the given field should be cached.
Definition: solution.C:290
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition: IOobject.C:450
String literal.
Definition: keyType.H:82
#define DebugInfo
Report an information message using Foam::Info.
static autoPtr< Function1< Type > > NewIfPresent(const word &entryName, const dictionary &dict, const word &redirectType, const objectRegistry *obrPtr=nullptr)
An optional selector, with fallback redirection.
Definition: Function1New.C:209
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED)
Definition: regIOobject.C:277
const dictionary & solversDict() const
The solver controls dictionary (all fields)
Definition: solution.C:461
registerDebugSwitchWithName(solution, solution, "solution")
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:637
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1094
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
scalar fieldRelaxationFactor(const word &name) const
Get the relaxation factor for the given field. Fatal if not found.
Definition: solution.C:414
meshDefDict readIfPresent("polyMeshPatches", polyPatchNames)
virtual ~solution()
Destructor. Non-default in header (incomplete types)
Definition: solution.C:220
messageStream Info
Information stream (stdout output on master, null elsewhere)
Selector class for relaxation factors, solver type and solution.
Definition: solution.H:92
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:765
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...
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition: POSIX.C:1702
Registry of regIOobjects.
void clear()
Clear the dictionary.
Definition: dictionary.C:844
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
Regular expression.
Definition: keyType.H:83
static label upgradeSolverDict(dictionary &dict, const bool verbose=true)
Update from older solver controls syntax.
Definition: solution.C:227
bool eof() const noexcept
True if end of input seen.
Definition: IOstream.H:289
An input stream of tokens.
Definition: ITstream.H:52
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
readOption
Enumeration defining read preferences.