Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
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{
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
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
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
149const Foam::dictionary& Foam::solution::selectedDict() const
150{
151 word select;
152
153 if (readIfPresent("select", select, keyType::LITERAL))
154 {
155 return subDict(select);
156 }
158 return *this;
159}
160
161
162// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
163
164Foam::solution::solution
165(
166 const objectRegistry& obr,
168 const fileName& dictName,
169 const dictionary* fallback
170)
171:
173 (
175 (
176 dictName,
177 obr.time().system(),
178 obr,
179 rOpt,
180 IOobjectOption::NO_WRITE
181 ),
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 (
207 {
208 read(selectedDict());
209 }
210}
211
212
213Foam::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(
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;
291 }
292
293 return nChanged;
294}
295
296
297bool 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
320bool Foam::solution::relaxField(const word& name) const
321{
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
337bool 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
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
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
379bool 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
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
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
421Foam::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
438Foam::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// ************************************************************************* //
propsDict readIfPresent("fields", acceptFields)
bool empty() const noexcept
True if the list is empty.
Definition DLListBase.H:189
static autoPtr< Function1< Type > > NewIfPresent(const word &entryName, const dictionary &dict, const word &redirectType, const objectRegistry *obrPtr=nullptr)
An optional selector, with fallback redirection.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
IOdictionary(const IOobject &io, const dictionary *fallback=nullptr)
Construct given an IOobject and optional fallback dictionary content.
A simple container of IOobject preferences. Can also be used for general handling of read/no-read/rea...
bool isReadOptional() const noexcept
True if (LAZY_READ) bits are set [same as READ_IF_PRESENT].
readOption readOpt() const noexcept
Get the read option.
readOption
Enumeration defining read preferences.
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
const Time & time() const noexcept
Return Time associated with the objectRegistry.
Definition IOobject.C:456
const objectRegistry & db() const noexcept
Return the local objectRegistry.
Definition IOobject.C:450
bool eof() const noexcept
True if end of input seen.
Definition IOstream.H:289
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:72
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
const word & name() const
Name function is needed to disambiguate those inherited from regIOobject and dictionary.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
dictionary()
Default construct, a top-level empty dictionary.
Definition dictionary.C:68
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.
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition dictionary.C:625
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition dictionary.C:765
word dictName() const
The local dictionary name (final part of scoped name).
Definition dictionaryI.H:53
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
A class for handling file names.
Definition fileName.H:75
@ LITERAL
String literal.
Definition keyType.H:82
@ REGEX
Regular expression.
Definition keyType.H:83
Registry of regIOobjects.
bool headerOk()
Read and check header info. Does not check the headerClassName.
virtual void addWatch()
Add file watch on object (if registered and READ_IF_MODIFIED).
virtual bool read()
Read object.
Selector class for relaxation factors, solver type and solution.
Definition solution.H:95
bool cache(const word &name) const
True if the given field should be cached.
Definition solution.C:290
virtual ~solution()
Destructor. Non-default in header (incomplete types).
Definition solution.C:220
const dictionary & solver(const word &name) const
The solver controls dictionary for the given field. Same as solverDict(...).
Definition solution.C:474
const dictionary & solversDict() const
The solver controls dictionary (all fields).
Definition solution.C:461
bool relaxField(const word &name) const
True if the relaxation factor is given for the field.
Definition solution.C:313
scalar fieldRelaxationFactor(const word &name) const
Get the relaxation factor for the given field. Fatal if not found.
Definition solution.C:414
const dictionary & solverDict(const word &name) const
The solver controls dictionary for the given field. Same as solversDict().subDict(....
Definition solution.C:467
static label upgradeSolverDict(dictionary &dict, const bool verbose=true)
Update from older solver controls syntax.
Definition solution.C:227
scalar equationRelaxationFactor(const word &name) const
Get the relaxation factor for the given equation. Fatal if not found.
Definition solution.C:431
bool relaxEquation(const word &name) const
True if the relaxation factor is given for the equation.
Definition solution.C:323
const dictionary & solutionDict() const
The entire dictionary or the optional "select" sub-dictionary.
Definition solution.C:448
bool read()
Read the solution dictionary.
Definition solution.C:481
A class for handling words, derived from Foam::string.
Definition word.H:66
#define registerDebugSwitchWithName(Type, Tag, Name)
Define the debug information, lookup as Name.
#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:629
const word dictName("faMeshDefinition")
auto & name
const auto & fallback
#define DebugInfo
Report an information message using Foam::Info.
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:139
Namespace for OpenFOAM.
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition int32.H:127
int system(const std::string &command, const bool bg=false)
Execute the specified command via the shell.
Definition POSIX.C:1704
messageStream Info
Information stream (stdout output on master, null elsewhere).
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
dictionary dict
static const Foam::List< Foam::word > subDictNames({ "preconditioner", "smoother" })
volScalarField & e