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-2021 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  if (dict.found("cache"))
53  {
54  cache_ = dict.subDict("cache");
55  caching_ = cache_.getOrDefault("active", true);
56  }
57 
58  if (dict.found("relaxationFactors"))
59  {
60  const dictionary& relaxDict = dict.subDict("relaxationFactors");
61 
62  if (relaxDict.found("fields") || relaxDict.found("equations"))
63  {
64  if (relaxDict.found("fields"))
65  {
66  fieldRelaxDict_ = relaxDict.subDict("fields");
67  fieldRelaxCache_.clear();
68  }
69 
70  if (relaxDict.found("equations"))
71  {
72  eqnRelaxDict_ = relaxDict.subDict("equations");
73  eqnRelaxCache_.clear();
74  }
75  }
76  else
77  {
78  // backwards compatibility
79  fieldRelaxDict_.clear();
80  fieldRelaxCache_.clear();
81 
82  for (const word& e : relaxDict.toc())
83  {
84  scalar value = relaxDict.get<scalar>(e);
85 
86  if (e.starts_with('p'))
87  {
88  fieldRelaxDict_.add(e, value);
89  }
90  else if (e.starts_with("rho"))
91  {
92  fieldRelaxDict_.add(e, value);
93  }
94  }
95 
96  eqnRelaxDict_ = relaxDict;
97  eqnRelaxCache_.clear();
98  }
99 
100 
101  fieldRelaxDefault_ = Function1<scalar>::NewIfPresent
102  (
103  "default",
104  fieldRelaxDict_
105  );
106  if (!fieldRelaxDefault_)
107  {
108  fieldRelaxDefault_.reset
109  (
110  new Function1Types::Constant<scalar>("default", 0)
111  );
112  }
113 
114  eqnRelaxDefault_ = Function1<scalar>::NewIfPresent
115  (
116  "default",
117  eqnRelaxDict_
118  );
119  if (!eqnRelaxDefault_)
120  {
121  eqnRelaxDefault_.reset
122  (
123  new Function1Types::Constant<scalar>("default", 0)
124  );
125  }
126 
127  DebugInfo
128  << "Relaxation factors:" << nl
129  << "fields: " << fieldRelaxDict_ << nl
130  << "equations: " << eqnRelaxDict_ << endl;
131  }
132 
133  if (dict.found("solvers"))
134  {
135  solvers_ = dict.subDict("solvers");
136  upgradeSolverDict(solvers_);
137  }
138 }
139 
140 
141 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
142 
143 Foam::solution::solution
144 (
145  const objectRegistry& obr,
146  const fileName& dictName,
147  const dictionary* fallback
148 )
149 :
151  (
152  IOobject
153  (
154  dictName,
155  obr.time().system(),
156  obr,
157  (
161  : obr.readOpt()
162  ),
164  ),
165  fallback
166  ),
167  cache_(),
168  caching_(false),
169  fieldRelaxDict_(),
170  eqnRelaxDict_(),
171  solvers_()
172 {
173  if
174  (
175  readOpt() == IOobject::MUST_READ
176  || readOpt() == IOobject::MUST_READ_IF_MODIFIED
177  || (readOpt() == IOobject::READ_IF_PRESENT && headerOk())
178  )
179  {
180  read(solutionDict());
181  }
182 }
183 
184 
185 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
186 
187 // A non-default destructor since we had incomplete types in the header
189 {}
190 
191 
192 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
193 
195 (
196  dictionary& dict,
197  const bool verbose
198 )
199 {
200  label nChanged = 0;
201 
202  // backward compatibility:
203  // recast primitive entries into dictionary entries
204  for (const entry& dEntry : dict)
205  {
206  if (!dEntry.isDict())
207  {
208  ITstream& is = dEntry.stream();
209  word name(is);
210  dictionary subdict;
211 
212  subdict.add("solver", name);
213  subdict <<= dictionary(is);
214 
215  // preconditioner and smoother entries can be
216  // 1) primitiveEntry w/o settings,
217  // 2) or a dictionaryEntry.
218  // transform primitiveEntry with settings -> dictionaryEntry
219  for (const word& dictName : subDictNames)
220  {
221  entry* eptr = subdict.findEntry(dictName, keyType::LITERAL);
222 
223  if (eptr && !eptr->isDict())
224  {
225  ITstream& is = eptr->stream();
226  is >> name;
227 
228  if (!is.eof())
229  {
230  dictionary newDict;
231  newDict.add(dictName, name);
232  newDict <<= dictionary(is);
233 
234  subdict.set(dictName, newDict);
235  }
236  }
237  }
238 
239  // write out information to help people adjust to the new syntax
240  if (verbose && Pstream::master())
241  {
242  Info<< "// using new solver syntax:\n"
243  << dEntry.keyword() << subdict << endl;
244  }
245 
246  // overwrite with dictionary entry
247  dict.set(dEntry.keyword(), subdict);
248 
249  ++nChanged;
250  }
251  }
252 
253  return nChanged;
254 }
255 
256 
257 bool Foam::solution::cache(const word& name) const
258 {
259  if (caching_)
260  {
261  DebugInfo<< "Cache: find entry for " << name << endl;
262  return cache_.found(name);
263  }
264 
265  return false;
266 }
267 
268 
270 {
271  DebugInfo
272  << "Field relaxation factor for " << name
273  << " is " << (fieldRelaxDict_.found(name) ? "set" : "unset") << endl;
274 
275  return fieldRelaxDict_.found(name) || fieldRelaxDict_.found("default");
276 }
277 
278 
280 {
281  DebugInfo<< "Find equation relaxation factor for " << name << endl;
282  return eqnRelaxDict_.found(name) || eqnRelaxDict_.found("default");
283 }
284 
285 
287 {
288  DebugInfo<< "Lookup variable relaxation factor for " << name << endl;
289 
290  if (fieldRelaxDict_.found(name))
291  {
293  (
294  fieldRelaxCache_, // cache
295  name,
296  fieldRelaxDict_,
298  )().value(time().timeOutputValue());
299  }
300  else if (fieldRelaxDefault_)
301  {
302  return fieldRelaxDefault_().value(time().timeOutputValue());
303  }
304 
305  FatalIOErrorInFunction(fieldRelaxDict_)
306  << "Cannot find variable relaxation factor for '" << name
307  << "' or a suitable default value." << nl
308  << exit(FatalIOError);
309 
310  return 0;
311 }
312 
313 
315 {
316  DebugInfo<< "Lookup equation relaxation factor for " << name << endl;
317 
318  if (eqnRelaxDict_.found(name))
319  {
321  (
322  eqnRelaxCache_, // cache
323  name,
324  eqnRelaxDict_,
326  )().value(time().timeOutputValue());
327  }
328  else if (eqnRelaxDefault_)
329  {
330  return eqnRelaxDefault_().value(time().timeOutputValue());
331  }
332 
333  FatalIOErrorInFunction(eqnRelaxDict_)
334  << "Cannot find equation relaxation factor for '" << name
335  << "' or a suitable default value."
336  << exit(FatalIOError);
337 
338  return 0;
339 }
340 
341 
343 {
344  if (found("select"))
345  {
346  return subDict(get<word>("select"));
347  }
348 
349  return *this;
350 }
351 
352 
354 {
355  DebugInfo<< "Lookup solver for " << name << endl;
356  return solvers_.subDict(name);
357 }
358 
359 
361 {
362  DebugInfo<< "Lookup solver for " << name << endl;
363  return solvers_.subDict(name);
364 }
365 
366 
368 {
369  if (regIOobject::read())
370  {
371  read(solutionDict());
372 
373  return true;
374  }
375 
376  return false;
377 }
378 
379 
380 // ************************************************************************* //
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
Foam::IOdictionary
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:54
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::solution::solverDict
const dictionary & solverDict(const word &name) const
Return the solver controls dictionary for the given field.
Definition: solution.C:353
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::fileName
A class for handling file names.
Definition: fileName.H:73
Foam::entry::stream
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
Foam::defineDebugSwitchWithName
defineDebugSwitchWithName(pointMVCWeight, "pointMVCWeight", 0)
Foam::solution::cache
bool cache(const word &name) const
Return true if the given field should be cached.
Definition: solution.C:257
Foam::dictionary::dictionary
dictionary()
Default construct, a top-level empty dictionary.
Definition: dictionary.C:75
Function1.H
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
dictName
const word dictName("faMeshDefinition")
Foam::entry::isDict
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
Definition: entry.H:233
Foam::regIOobject::read
virtual bool read()
Read object.
Definition: regIOobjectRead.C:191
solutionDict
fvSolution solutionDict(runTime)
Foam::solution::upgradeSolverDict
static label upgradeSolverDict(dictionary &dict, const bool verbose=true)
Update from older solver controls syntax.
Definition: solution.C:195
Foam::UPstream::master
static bool master(const label communicator=worldComm)
Am I the master process.
Definition: UPstream.H:457
Foam::FatalIOError
IOerror FatalIOError
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::dictionary::set
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:780
Foam::Function1::NewIfPresent
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:212
Foam::Function1
Top level data entry class for use in dictionaries. Provides a mechanism to specify a variable as a c...
Definition: propellerInfo.H:291
subDictNames
static const Foam::List< Foam::word > subDictNames({ "preconditioner", "smoother" })
Foam::objectRegistry
Registry of regIOobjects.
Definition: objectRegistry.H:60
Foam::solution::fieldRelaxationFactor
scalar fieldRelaxationFactor(const word &name) const
Return the relaxation factor for the given field.
Definition: solution.C:286
Foam::ITstream
An input stream of tokens.
Definition: ITstream.H:52
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::IOstream::eof
bool eof() const noexcept
True if end of input seen.
Definition: IOstream.H:239
Foam::dictionary::subDict
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:460
Foam::IOobject::READ_IF_PRESENT
Definition: IOobject.H:187
Foam::solution::read
bool read()
Read the solution dictionary.
Definition: solution.C:367
Foam::Function1::value
virtual Type value(const scalar x) const
Return value as a function of (scalar) independent variable.
Definition: Function1.C:69
Foam::solution::~solution
virtual ~solution()
Destructor.
Definition: solution.C:188
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::solution::relaxEquation
bool relaxEquation(const word &name) const
Return true if the relaxation factor is given for the equation.
Definition: solution.C:279
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
solution.H
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::solution::equationRelaxationFactor
scalar equationRelaxationFactor(const word &name) const
Return the relaxation factor for the given equation.
Definition: solution.C:314
Foam::IOobject::readOpt
readOption readOpt() const noexcept
The read option.
Definition: IOobjectI.H:164
found
bool found
Definition: TABSMDCalcMethod2.H:32
Time.H
Foam::TimePaths::system
const word & system() const
Return system name.
Definition: TimePathsI.H:102
Foam::solution::solutionDict
const dictionary & solutionDict() const
Return the selected sub-dictionary of solvers if the "select".
Definition: solution.C:342
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:382
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::List< Foam::word >
Foam::dictionary::findEntry
entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find for an entry (non-const access) with the given keyword.
Definition: dictionaryI.H:97
HashPtrTable.H
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::keyType::REGEX
Regular expression.
Definition: keyType.H:82
Foam::IOobject::MUST_READ_IF_MODIFIED
Definition: IOobject.H:186
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::dictionary::add
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:640
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::solution::solver
const dictionary & solver(const word &name) const
Return the solver controls dictionary for the given field.
Definition: solution.C:360
Foam::keyType::LITERAL
String literal.
Definition: keyType.H:81
Foam::dictionary::getOrDefault
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:148
Foam::dictionary::clear
void clear()
Clear the dictionary.
Definition: dictionary.C:857
Foam::solution::relaxField
bool relaxField(const word &name) const
Return true if the relaxation factor is given for the field.
Definition: solution.C:269
Foam::objectRegistry::time
const Time & time() const noexcept
Return time registry.
Definition: objectRegistry.H:178
Foam::IOobject::MUST_READ
Definition: IOobject.H:185