Fixed storing every residual in solvePerformance (increasing solverPerformance list...
[foam-extend-4.0.git] / src / foam / matrices / solution / solution.C
blob7721094c94e1220ea0c1d6867a13eb7f8e066bcb
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     4.0
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "solution.H"
27 #include "objectRegistry.H"
29 // These are for old syntax compatibility:
30 #include "BICCG.H"
31 #include "ICCG.H"
32 #include "IStringStream.H"
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36 Foam::debug::debugSwitch
37 Foam::solution::debug
39     "solution",
40     0
43 // List of sub-dictionaries to rewrite
44 //! @cond localScope
45 static const Foam::List<Foam::word> subDictNames
47     Foam::IStringStream("(preconditioner smoother)")()
49 //! @endcond localScope
52 // * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * * //
54 void Foam::solution::read(const dictionary& dict)
56     if (dict.found("cache"))
57     {
58         cache_ = dict.subDict("cache");
59         caching_ = cache_.lookupOrDefault("active", true);
60     }
62     if (dict.found("relaxationFactors"))
63     {
64         const dictionary& relaxDict(dict.subDict("relaxationFactors"));
65         if (relaxDict.found("fields") || relaxDict.found("equations"))
66         {
67             if (relaxDict.found("fields"))
68             {
69                 fieldRelaxDict_ = relaxDict.subDict("fields");
70             }
72             if (relaxDict.found("equations"))
73             {
74                 eqnRelaxDict_ = relaxDict.subDict("equations");
75             }
76         }
77         else
78         {
79             // backwards compatibility
80             fieldRelaxDict_.clear();
82             const wordList entryNames(relaxDict.toc());
83             forAll(entryNames, i)
84             {
85                 const word& e = entryNames[i];
86                 scalar value = readScalar(relaxDict.lookup(e));
88                 if (e(0, 1) == "p")
89                 {
90                     fieldRelaxDict_.add(e, value);
91                 }
92                 else if (e.length() >= 3)
93                 {
94                     if (e(0, 3) == "rho")
95                     {
96                         fieldRelaxDict_.add(e, value);
97                     }
98                 }
100             }
102             eqnRelaxDict_ = relaxDict;
103         }
105         fieldRelaxDefault_ =
106             fieldRelaxDict_.lookupOrDefault<scalar>("default", 0.0);
108         eqnRelaxDefault_ =
109             eqnRelaxDict_.lookupOrDefault<scalar>("default", 0.0);
111         if (debug)
112         {
113             Info<< "relaxation factors:" << nl
114                 << "fields: " << fieldRelaxDict_ << nl
115                 << "equations: " << eqnRelaxDict_ << endl;
116         }
117     }
120     if (dict.found("solvers"))
121     {
122         solvers_ = dict.subDict("solvers");
123         upgradeSolverDict(solvers_);
124     }
126     if (dict.found("solverPerformance"))
127     {
128         solverPerformance_ = dict.subDict("solverPerformance");
129     }
133 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
135 Foam::solution::solution(const objectRegistry& obr, const fileName& dictName)
137     IOdictionary
138     (
139         IOobject
140         (
141             dictName,
142             obr.time().system(),
143             obr,
144             IOobject::READ_IF_PRESENT,  // Allow default dictionary creation
145             IOobject::NO_WRITE
146         )
147     ),
148     cache_(dictionary::null),
149     caching_(false),
150     fieldRelaxDict_(dictionary::null),
151     eqnRelaxDict_(dictionary::null),
152     fieldRelaxDefault_(0),
153     eqnRelaxDefault_(0),
154     solvers_(dictionary::null),
155     solverPerformance_(dictionary::null),
156     prevTimeIndex_(0)
158     if (!headerOk())
159     {
160         if (debug)
161         {
162             InfoIn
163             (
164                 "Foam::solution::solution(const objectRegistry& obr, "
165                 "const fileName& dictName)"
166             )   << "Solution dictionary not found.  Adding default entries"
167                 << endl;
168         }
169     }
171     read(solutionDict());
173     set("solverPerformance", dictionary());
177 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
179 Foam::label Foam::solution::upgradeSolverDict
181     dictionary& dict,
182     const bool verbose
185     label nChanged = 0;
187     // backward compatibility:
188     // recast primitive entries into dictionary entries
189     forAllIter(dictionary, dict, iter)
190     {
191         if (!iter().isDict())
192         {
193             Istream& is = iter().stream();
194             word name(is);
195             dictionary subdict;
197             if (name == "BICCG")
198             {
199                 // special treatment for very old syntax
200                 subdict = BICCG::solverDict(is);
201             }
202             else if (name == "ICCG")
203             {
204                 // special treatment for very old syntax
205                 subdict = ICCG::solverDict(is);
206             }
207             else
208             {
209                 subdict.add("solver", name);
210                 subdict <<= dictionary(is);
212                 // preconditioner and smoother entries can be
213                 // 1) primitiveEntry w/o settings,
214                 // 2) or a dictionaryEntry.
215                 // transform primitiveEntry with settings -> dictionaryEntry
216                 forAll(subDictNames, dictI)
217                 {
218                     const word& dictName = subDictNames[dictI];
219                     entry* ePtr = subdict.lookupEntryPtr(dictName,false,false);
221                     if (ePtr && !ePtr->isDict())
222                     {
223                         Istream& is = ePtr->stream();
224                         is >> name;
226                         if (!is.eof())
227                         {
228                             dictionary newDict;
229                             newDict.add(dictName, name);
230                             newDict <<= dictionary(is);
232                             subdict.set(dictName, newDict);
233                         }
234                     }
235                 }
236             }
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                     << iter().keyword() << subdict << endl;
244             }
246             // overwrite with dictionary entry
247             dict.set(iter().keyword(), subdict);
249             nChanged++;
250         }
251     }
253     return nChanged;
257 bool Foam::solution::cache(const word& name) const
259     if (caching_)
260     {
261         if (debug)
262         {
263             Info<< "Cache: find entry for " << name
264                 << ": " << Switch(cache_.found(name)) << endl;
265         }
267         return cache_.found(name);
268     }
269     else
270     {
271         return false;
272     }
276 bool Foam::solution::relaxField(const word& name) const
278     if (debug)
279     {
280         Info<< "Field relaxation factor for " << name
281             << " is " << (fieldRelaxDict_.found(name) ? "set" : "unset")
282             << endl;
283     }
285     return fieldRelaxDict_.found(name) || fieldRelaxDict_.found("default");
289 bool Foam::solution::relaxEquation(const word& name) const
291     if (debug)
292     {
293         Info<< "Find equation relaxation factor for " << name << endl;
294     }
296     return eqnRelaxDict_.found(name) || eqnRelaxDict_.found("default");
300 Foam::scalar Foam::solution::fieldRelaxationFactor(const word& name) const
302     if (debug)
303     {
304         Info<< "Lookup variable relaxation factor for " << name << endl;
305     }
307     if (fieldRelaxDict_.found(name))
308     {
309         return readScalar(fieldRelaxDict_.lookup(name));
310     }
311     else if (fieldRelaxDefault_ > SMALL)
312     {
313         return fieldRelaxDefault_;
314     }
315     else
316     {
317         FatalIOErrorIn
318         (
319             "Foam::solution::fieldRelaxationFactor(const word&)",
320             fieldRelaxDict_
321         )   << "Cannot find variable relaxation factor for '" << name
322             << "' or a suitable default value."
323             << exit(FatalIOError);
325         return 0;
326     }
330 Foam::scalar Foam::solution::equationRelaxationFactor(const word& name) const
332     if (debug)
333     {
334         Info<< "Lookup equation relaxation factor for " << name << endl;
335     }
337     if (eqnRelaxDict_.found(name))
338     {
339         return readScalar(eqnRelaxDict_.lookup(name));
340     }
341     else if (eqnRelaxDefault_ > SMALL)
342     {
343         return eqnRelaxDefault_;
344     }
345     else
346     {
347         FatalIOErrorIn
348         (
349             "Foam::solution::eqnRelaxationFactor(const word&)",
350             eqnRelaxDict_
351         )   << "Cannot find equation relaxation factor for '" << name
352             << "' or a suitable default value."
353             << exit(FatalIOError);
355         return 0;
356     }
360 const Foam::dictionary& Foam::solution::solutionDict() const
362     if (found("select"))
363     {
364         return subDict(word(lookup("select")));
365     }
366     else
367     {
368         return *this;
369     }
373 const Foam::dictionary& Foam::solution::solverDict(const word& name) const
375     if (debug)
376     {
377         InfoIn("solution::solverDict(const word&)")
378             << "Lookup solver for " << name << endl;
379     }
381     return solvers_.subDict(name);
385 const Foam::dictionary& Foam::solution::solver(const word& name) const
387     if (debug)
388     {
389         InfoIn("solution::solver(const word&)")
390             << "Lookup solver for " << name << endl;
391     }
393     return solvers_.subDict(name);
397 bool Foam::solution::read()
399     if (regIOobject::read())
400     {
401         read(solutionDict());
403         return true;
404     }
405     else
406     {
407         return false;
408     }
411 bool Foam::solution::writeData(Ostream& os) const
413     // Write direct entries of the solution dictionary
414     // HJ, 16/Feb/2010
415     dictionary::write(os, false);
417     return true;
420 Foam::dictionary& Foam::solution::solverPerformanceDict() const
422     return solverPerformance_;
426 void Foam::solution::setSolverPerformance
428     const word& name,
429     const lduSolverPerformance& sp
430 ) const
432     List<lduSolverPerformance> perfs;
434     if (prevTimeIndex_ != this->time().timeIndex())
435     {
436         // Reset solver performance between iterations
437         prevTimeIndex_ = this->time().timeIndex();
438         solverPerformance_.clear();
439     }
440     else
441     {
442         solverPerformance_.readIfPresent(name, perfs);
443     }
445     // Only the first iteration and the current iteration residuals are
446     // required, so the current iteration residual replaces the previous one and
447     // only the first iteration is always present, VS 2017-11-27
448     if (perfs.size() < 2)
449     {
450         // Append to list
451         perfs.setSize(perfs.size() + 1, sp);
452     }
453     else
454     {
455         perfs.last() = sp;
456     }
458     solverPerformance_.set(name, perfs);
462 void Foam::solution::setSolverPerformance
464     const lduSolverPerformance& sp
465 ) const
467     setSolverPerformance(sp.fieldName(), sp);
470 // ************************************************************************* //