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-2022 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 }
40 
41 // List of sub-dictionaries to rewrite
43 ({
44  "preconditioner", "smoother"
45 });
46 
47 
48 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
49 
50 void Foam::solution::read(const dictionary& dict)
51 {
52  const dictionary* dictptr;
53 
54  if ((dictptr = dict.findDict("cache")) != nullptr)
55  {
56  cache_ = *dictptr;
57  caching_ = cache_.getOrDefault("active", true);
58  }
59 
60  if ((dictptr = dict.findDict("relaxationFactors")) != nullptr)
61  {
62  const dictionary& relaxDict = *dictptr;
63 
64  bool needsCompat = true;
65 
66  if ((dictptr = relaxDict.findDict("fields")) != nullptr)
67  {
68  needsCompat = false;
69  fieldRelaxDict_ = *dictptr;
70  fieldRelaxCache_.clear();
71  }
72 
73  if ((dictptr = relaxDict.findDict("equations")) != nullptr)
74  {
75  needsCompat = false;
76  eqnRelaxDict_ = *dictptr;
77  eqnRelaxCache_.clear();
78  }
79 
80  if (needsCompat)
81  {
82  // backwards compatibility
83  fieldRelaxDict_.clear();
84  fieldRelaxCache_.clear();
85 
86  for (const word& e : relaxDict.toc())
87  {
88  scalar value = relaxDict.get<scalar>(e);
89 
90  if (e.starts_with('p'))
91  {
92  fieldRelaxDict_.add(e, value);
93  }
94  else if (e.starts_with("rho"))
95  {
96  fieldRelaxDict_.add(e, value);
97  }
98  }
99 
100  eqnRelaxDict_ = relaxDict;
101  eqnRelaxCache_.clear();
102  }
103 
104 
105  fieldRelaxDefault_ = Function1<scalar>::NewIfPresent
106  (
107  "default",
108  fieldRelaxDict_
109  );
110  if (!fieldRelaxDefault_)
111  {
112  fieldRelaxDefault_.reset
113  (
114  new Function1Types::Constant<scalar>("default", 0)
115  );
116  }
117 
118  eqnRelaxDefault_ = Function1<scalar>::NewIfPresent
119  (
120  "default",
121  eqnRelaxDict_
122  );
123  if (!eqnRelaxDefault_)
124  {
125  eqnRelaxDefault_.reset
126  (
127  new Function1Types::Constant<scalar>("default", 0)
128  );
129  }
130 
131  DebugInfo
132  << "Relaxation factors:" << nl
133  << "fields: " << fieldRelaxDict_ << nl
134  << "equations: " << eqnRelaxDict_ << endl;
135  }
136 
137  if ((dictptr = dict.findDict("solvers")) != nullptr)
138  {
139  solvers_ = *dictptr;
140  upgradeSolverDict(solvers_);
141  }
142 }
143 
144 
145 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
146 
147 Foam::solution::solution
148 (
149  const objectRegistry& obr,
151  const fileName& dictName,
152  const dictionary* fallback
153 )
154 :
155  IOdictionary
156  (
157  IOobject
158  (
159  dictName,
160  obr.time().system(),
161  obr,
162  rOpt,
163  IOobject::NO_WRITE
164  ),
165  fallback
166  ),
167  cache_(),
168  caching_(false),
169  fieldRelaxDict_(),
170  eqnRelaxDict_(),
171  solvers_()
172 {
173  // Treat as MUST_READ_IF_MODIFIED whenever possible
174  if
175  (
177  || (isReadOptional() && headerOk())
178  )
179  {
181  addWatch();
182  }
183 
185  {
186  read(solutionDict());
187  }
188 }
189 
190 
191 Foam::solution::solution
192 (
193  const objectRegistry& obr,
194  const fileName& dictName,
195  const dictionary* fallback
196 )
197 :
198  solution(obr, obr.readOpt(), dictName, fallback)
199 {}
200 
201 
202 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
203 
204 // A non-default destructor since we had incomplete types in the header
206 {}
207 
208 
209 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
210 
212 (
213  dictionary& dict,
214  const bool verbose
215 )
216 {
217  label nChanged = 0;
218 
219  // backward compatibility:
220  // recast primitive entries into dictionary entries
221  for (const entry& dEntry : dict)
222  {
223  if (!dEntry.isDict())
224  {
225  ITstream& is = dEntry.stream();
226  word name(is);
227  dictionary subdict;
228 
229  subdict.add("solver", name);
230  subdict <<= dictionary(is);
231 
232  // preconditioner and smoother entries can be
233  // 1) primitiveEntry w/o settings,
234  // 2) or a dictionaryEntry.
235  // transform primitiveEntry with settings -> dictionaryEntry
236  for (const word& dictName : subDictNames)
237  {
238  entry* eptr = subdict.findEntry(dictName, keyType::LITERAL);
239 
240  if (eptr && !eptr->isDict())
241  {
242  ITstream& is = eptr->stream();
243  is >> name;
244 
245  if (!is.eof())
246  {
247  dictionary newDict;
248  newDict.add(dictName, name);
249  newDict <<= dictionary(is);
250 
251  subdict.set(dictName, newDict);
252  }
253  }
254  }
255 
256  // write out information to help people adjust to the new syntax
257  if (verbose && Pstream::master())
258  {
259  Info<< "// using new solver syntax:\n"
260  << dEntry.keyword() << subdict << endl;
261  }
262 
263  // overwrite with dictionary entry
264  dict.set(dEntry.keyword(), subdict);
265 
266  ++nChanged;
267  }
268  }
269 
270  return nChanged;
271 }
272 
273 
274 bool Foam::solution::cache(const word& name) const
275 {
276  if (caching_)
277  {
278  DebugInfo<< "Cache: find entry for " << name << endl;
279  return cache_.found(name);
280  }
281 
282  return false;
283 }
284 
285 
286 bool Foam::solution::relaxField(const word& name) const
287 {
288  DebugInfo
289  << "Field relaxation factor for " << name
290  << " is " << (fieldRelaxDict_.found(name) ? "set" : "unset") << endl;
291 
292  return fieldRelaxDict_.found(name) || fieldRelaxDict_.found("default");
293 }
294 
295 
297 {
298  DebugInfo<< "Find equation relaxation factor for " << name << endl;
299  return eqnRelaxDict_.found(name) || eqnRelaxDict_.found("default");
300 }
301 
302 
303 Foam::scalar Foam::solution::fieldRelaxationFactor(const word& name) const
304 {
305  DebugInfo<< "Lookup variable relaxation factor for " << name << endl;
306 
307  if (fieldRelaxDict_.found(name))
308  {
310  (
311  fieldRelaxCache_, // cache
312  name,
313  fieldRelaxDict_,
315  )().value(time().timeOutputValue());
316  }
317  else if (fieldRelaxDefault_)
318  {
319  return fieldRelaxDefault_().value(time().timeOutputValue());
320  }
321 
322  FatalIOErrorInFunction(fieldRelaxDict_)
323  << "Cannot find variable relaxation factor for '" << name
324  << "' or a suitable default value." << nl
325  << exit(FatalIOError);
326 
327  return 0;
328 }
329 
330 
331 Foam::scalar Foam::solution::equationRelaxationFactor(const word& name) const
332 {
333  DebugInfo<< "Lookup equation relaxation factor for " << name << endl;
334 
335  if (eqnRelaxDict_.found(name))
336  {
338  (
339  eqnRelaxCache_, // cache
340  name,
341  eqnRelaxDict_,
343  )().value(time().timeOutputValue());
344  }
345  else if (eqnRelaxDefault_)
346  {
347  return eqnRelaxDefault_().value(time().timeOutputValue());
348  }
349 
350  FatalIOErrorInFunction(eqnRelaxDict_)
351  << "Cannot find equation relaxation factor for '" << name
352  << "' or a suitable default value."
353  << exit(FatalIOError);
354 
355  return 0;
356 }
357 
358 
360 {
361  if (found("select"))
362  {
363  return subDict(get<word>("select"));
364  }
365 
366  return *this;
367 }
368 
369 
371 {
372  DebugInfo<< "Lookup solver for " << name << endl;
373  return solvers_.subDict(name);
374 }
375 
376 
378 {
379  DebugInfo<< "Lookup solver for " << name << endl;
380  return solvers_.subDict(name);
381 }
382 
383 
385 {
386  if (regIOobject::read())
387  {
388  read(solutionDict());
389 
390  return true;
391  }
392 
393  return false;
394 }
395 
396 
397 // ************************************************************************* //
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
Return the relaxation factor for the given equation.
Definition: solution.C:324
dictionary dict
static autoPtr< Function1< Type > > NewIfPresent(const word &entryName, const dictionary &dict, const word &redirectType=word::null, const objectRegistry *obrPtr=nullptr)
An optional selector.
Definition: Function1New.C:209
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:120
defineDebugSwitchWithName(pointMVCWeight, "pointMVCWeight", 0)
bool read()
Read the solution dictionary.
Definition: solution.C:377
static const Foam::List< Foam::word > subDictNames({ "preconditioner", "smoother" })
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
fvSolution solutionDict(runTime)
const dictionary & solver(const word &name) const
Return the solver controls dictionary for the given field.
Definition: solution.C:370
const word dictName("faMeshDefinition")
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
bool headerOk()
Read and check header info. Does not check the headerClassName.
Definition: regIOobject.C:434
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:637
bool relaxField(const word &name) const
Return true if the relaxation factor is given for the field.
Definition: solution.C:279
const dictionary & solverDict(const word &name) const
Return the solver controls dictionary for the given field.
Definition: solution.C:363
bool isReadOptional() const noexcept
True if (READ_IF_PRESENT) bits are set.
bool relaxEquation(const word &name) const
Return true if the relaxation factor is given for the equation.
Definition: solution.C:289
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:125
dictionary()
Default construct, a top-level empty dictionary.
Definition: dictionary.C:68
virtual Type value(const scalar x) const
Return value as a function of (scalar) independent variable.
Definition: Function1.C:62
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:52
A class for handling words, derived from Foam::string.
Definition: word.H:63
const dictionary & solutionDict() const
Return the selected sub-dictionary of solvers if the "select" keyword is given, otherwise return the ...
Definition: solution.C:352
Reading required, file watched for runTime modification.
bool cache(const word &name) const
Return true if the given field should be cached.
Definition: solution.C:267
String literal.
Definition: keyType.H:82
#define DebugInfo
Report an information message using Foam::Info.
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED)
Definition: regIOobject.C:263
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
static bool master(const label communicator=worldComm)
Am I the master rank.
Definition: UPstream.H:672
scalar fieldRelaxationFactor(const word &name) const
Return the relaxation factor for the given field.
Definition: solution.C:296
virtual ~solution()
Destructor.
Definition: solution.C:198
const entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:80
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
Definition: entry.H:287
Selector class for relaxation factors, solver type and solution.
Definition: solution.H:59
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:777
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:1655
void clear()
Clear the dictionary.
Definition: dictionary.C:856
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
bool found
Regular expression.
Definition: keyType.H:83
static label upgradeSolverDict(dictionary &dict, const bool verbose=true)
Update from older solver controls syntax.
Definition: solution.C:205
bool eof() const noexcept
True if end of input seen.
Definition: IOstream.H:282
An input stream of tokens.
Definition: ITstream.H:48
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.