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-------------------------------------------------------------------------------
11License
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
36namespace Foam
37{
39}
40
41// List of sub-dictionaries to rewrite
43({
44 "preconditioner", "smoother"
45});
46
47
48// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
49
50void 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
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
144(
145 const objectRegistry& obr,
146 const IOobject::readOption rOpt,
147 const fileName& dictName,
148 const dictionary* fallback
149)
150:
152 (
154 (
155 dictName,
156 obr.time().system(),
157 obr,
158 rOpt,
159 IOobject::NO_WRITE
160 ),
161 fallback
162 ),
163 cache_(),
164 caching_(false),
165 fieldRelaxDict_(),
166 eqnRelaxDict_(),
167 solvers_()
168{
169 // Treat as MUST_READ_IF_MODIFIED whenever possible
170 if
171 (
174 )
175 {
177 addWatch();
178 }
179
181 {
183 }
184}
185
186
188(
189 const objectRegistry& obr,
190 const fileName& dictName,
191 const dictionary* fallback
192)
193:
194 solution(obr, obr.readOpt(), dictName, fallback)
195{}
196
197
198// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
199
200// A non-default destructor since we had incomplete types in the header
202{}
203
204
205// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
206
208(
210 const bool verbose
211)
212{
213 label nChanged = 0;
214
215 // backward compatibility:
216 // recast primitive entries into dictionary entries
217 for (const entry& dEntry : dict)
218 {
219 if (!dEntry.isDict())
220 {
221 ITstream& is = dEntry.stream();
222 word name(is);
223 dictionary subdict;
224
225 subdict.add("solver", name);
226 subdict <<= dictionary(is);
227
228 // preconditioner and smoother entries can be
229 // 1) primitiveEntry w/o settings,
230 // 2) or a dictionaryEntry.
231 // transform primitiveEntry with settings -> dictionaryEntry
232 for (const word& dictName : subDictNames)
233 {
234 entry* eptr = subdict.findEntry(dictName, keyType::LITERAL);
235
236 if (eptr && !eptr->isDict())
237 {
238 ITstream& is = eptr->stream();
239 is >> name;
240
241 if (!is.eof())
242 {
243 dictionary newDict;
244 newDict.add(dictName, name);
245 newDict <<= dictionary(is);
246
247 subdict.set(dictName, newDict);
248 }
249 }
250 }
251
252 // write out information to help people adjust to the new syntax
253 if (verbose && Pstream::master())
254 {
255 Info<< "// using new solver syntax:\n"
256 << dEntry.keyword() << subdict << endl;
257 }
258
259 // overwrite with dictionary entry
260 dict.set(dEntry.keyword(), subdict);
261
262 ++nChanged;
263 }
264 }
265
266 return nChanged;
267}
268
269
271{
272 if (caching_)
273 {
274 DebugInfo<< "Cache: find entry for " << name << endl;
275 return cache_.found(name);
276 }
277
278 return false;
279}
280
281
283{
285 << "Field relaxation factor for " << name
286 << " is " << (fieldRelaxDict_.found(name) ? "set" : "unset") << endl;
287
288 return fieldRelaxDict_.found(name) || fieldRelaxDict_.found("default");
289}
290
291
293{
294 DebugInfo<< "Find equation relaxation factor for " << name << endl;
295 return eqnRelaxDict_.found(name) || eqnRelaxDict_.found("default");
296}
297
298
300{
301 DebugInfo<< "Lookup variable relaxation factor for " << name << endl;
302
303 if (fieldRelaxDict_.found(name))
304 {
306 (
307 fieldRelaxCache_, // cache
308 name,
309 fieldRelaxDict_,
311 )().value(time().timeOutputValue());
312 }
313 else if (fieldRelaxDefault_)
314 {
315 return fieldRelaxDefault_().value(time().timeOutputValue());
316 }
317
318 FatalIOErrorInFunction(fieldRelaxDict_)
319 << "Cannot find variable relaxation factor for '" << name
320 << "' or a suitable default value." << nl
321 << exit(FatalIOError);
322
323 return 0;
324}
325
326
328{
329 DebugInfo<< "Lookup equation relaxation factor for " << name << endl;
330
331 if (eqnRelaxDict_.found(name))
332 {
334 (
335 eqnRelaxCache_, // cache
336 name,
337 eqnRelaxDict_,
339 )().value(time().timeOutputValue());
340 }
341 else if (eqnRelaxDefault_)
342 {
343 return eqnRelaxDefault_().value(time().timeOutputValue());
344 }
345
346 FatalIOErrorInFunction(eqnRelaxDict_)
347 << "Cannot find equation relaxation factor for '" << name
348 << "' or a suitable default value."
349 << exit(FatalIOError);
350
351 return 0;
352}
353
354
356{
357 if (found("select"))
358 {
359 return subDict(get<word>("select"));
360 }
361
362 return *this;
363}
364
365
367{
368 DebugInfo<< "Lookup solver for " << name << endl;
369 return solvers_.subDict(name);
370}
371
372
374{
375 DebugInfo<< "Lookup solver for " << name << endl;
376 return solvers_.subDict(name);
377}
378
379
381{
382 if (regIOobject::read())
383 {
385
386 return true;
387 }
388
389 return false;
390}
391
392
393// ************************************************************************* //
bool found
fvSolution solutionDict(runTime)
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
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:57
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
readOption readOpt() const noexcept
The read option.
Definition: IOobjectI.H:164
readOption
Enumeration defining the read options.
Definition: IOobject.H:177
@ MUST_READ_IF_MODIFIED
Definition: IOobject.H:180
bool eof() const noexcept
True if end of input seen.
Definition: IOstream.H:239
An input stream of tokens.
Definition: ITstream.H:56
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:460
dictionary()
Default construct, a top-level empty dictionary.
Definition: dictionary.C:75
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
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
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
void clear()
Clear the dictionary.
Definition: dictionary.C:857
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:640
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:780
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
Definition: entry.H:233
A class for handling file names.
Definition: fileName.H:76
const dictionary & solverDict() const
Return the solver dictionary taking into account finalIteration.
Definition: fvMatrix.C:1558
@ LITERAL
String literal.
Definition: keyType.H:81
@ REGEX
Regular expression.
Definition: keyType.H:82
Abstract base-class for lduMatrix solvers.
Definition: lduMatrix.H:99
Registry of regIOobjects.
bool headerOk()
Read and check header info. Does not check the headerClassName.
Definition: regIOobject.C:438
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED)
Definition: regIOobject.C:267
virtual bool read()
Read object.
Selector class for relaxation factors, solver type and solution.
Definition: solution.H:66
bool cache(const word &name) const
Return true if the given field should be cached.
Definition: solution.C:270
virtual ~solution()
Destructor.
Definition: solution.C:201
bool relaxField(const word &name) const
Return true if the relaxation factor is given for the field.
Definition: solution.C:282
scalar fieldRelaxationFactor(const word &name) const
Return the relaxation factor for the given field.
Definition: solution.C:299
static label upgradeSolverDict(dictionary &dict, const bool verbose=true)
Update from older solver controls syntax.
Definition: solution.C:208
scalar equationRelaxationFactor(const word &name) const
Return the relaxation factor for the given equation.
Definition: solution.C:327
bool relaxEquation(const word &name) const
Return true if the relaxation factor is given for the equation.
Definition: solution.C:292
const dictionary & solutionDict() const
Definition: solution.C:355
bool read()
Read the solution dictionary.
Definition: solution.C:380
splitCell * master() const
Definition: splitCell.H:113
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineDebugSwitchWithName(Type, Name, Value)
Define the debug information, lookup as Name.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
const word dictName("faMeshDefinition")
#define DebugInfo
Report an information message using Foam::Info.
Namespace for OpenFOAM.
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition: MSwindows.C:1158
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
IOerror FatalIOError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
dictionary dict
static const Foam::List< Foam::word > subDictNames({ "preconditioner", "smoother" })
volScalarField & e
Definition: createFields.H:11