From 402e6053912eb7a5769ed5d7dc92ac43c3e666b0 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Tue, 28 Nov 2017 11:46:48 +0100
Subject: [PATCH] ENH: expose solutionControl::maxResiduals as a static with
 simpler parameters

- use a Pair<scalar> with first() / last() residuals
---
 src/OpenFOAM/meshes/data/data.H               | 43 +++++-----
 .../pimpleControl/pimpleControl.C             | 86 +++++++++----------
 .../pimpleControl/pimpleControl.H             | 10 +--
 .../pimpleControl/pimpleControlI.H            | 10 +--
 .../simpleControl/simpleControl.C             | 75 +++++++---------
 .../simpleControl/simpleControl.H             | 14 +--
 .../solutionControl/solutionControl.C         | 82 +++++++++++-------
 .../solutionControl/solutionControl.H         | 52 +++++++----
 .../solutionControl/solutionControlI.H        | 10 +--
 9 files changed, 199 insertions(+), 183 deletions(-)

diff --git a/src/OpenFOAM/meshes/data/data.H b/src/OpenFOAM/meshes/data/data.H
index 61583483644..9671fe30202 100644
--- a/src/OpenFOAM/meshes/data/data.H
+++ b/src/OpenFOAM/meshes/data/data.H
@@ -63,10 +63,10 @@ class data
     // Private Member Functions
 
         //- Disallow default bitwise copy construct
-        data(const data&);
+        data(const data&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const data&);
+        void operator=(const data&) = delete;
 
 
 public:
@@ -83,27 +83,24 @@ public:
 
     // Member Functions
 
-        // Access
-
-            //- Return the dictionary of solver performance data
-            //  which includes initial and final residuals for convergence
-            //  checking
-            const dictionary& solverPerformanceDict() const;
-
-            //- Add/set the solverPerformance entry for the named field
-            template<class Type>
-            void setSolverPerformance
-            (
-                const word& name,
-                const SolverPerformance<Type>&
-            ) const;
-
-            //- Add/set the solverPerformance entry, using its fieldName
-            template<class Type>
-            void setSolverPerformance
-            (
-                const SolverPerformance<Type>&
-            ) const;
+        //- Return the dictionary of solver performance data which
+        //- includes initial and final residuals for convergence checking
+        const dictionary& solverPerformanceDict() const;
+
+        //- Add/set the solverPerformance entry for the named field
+        template<class Type>
+        void setSolverPerformance
+        (
+            const word& name,
+            const SolverPerformance<Type>& sp
+        ) const;
+
+        //- Add/set the solverPerformance entry, using its fieldName
+        template<class Type>
+        void setSolverPerformance
+        (
+            const SolverPerformance<Type>& sp
+        ) const;
 };
 
 
diff --git a/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControl.C b/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControl.C
index 6d031f05b6d..754b7112307 100644
--- a/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControl.C
+++ b/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControl.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -24,7 +24,6 @@ License
 \*---------------------------------------------------------------------------*/
 
 #include "pimpleControl.H"
-#include "Switch.H"
 
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
@@ -42,12 +41,12 @@ void Foam::pimpleControl::read()
 
     const dictionary& pimpleDict = dict();
 
-    solveFlow_ = pimpleDict.lookupOrDefault<Switch>("solveFlow", true);
+    solveFlow_ = pimpleDict.lookupOrDefault("solveFlow", true);
     nCorrPIMPLE_ = pimpleDict.lookupOrDefault<label>("nOuterCorrectors", 1);
     nCorrPISO_ = pimpleDict.lookupOrDefault<label>("nCorrectors", 1);
-    SIMPLErho_ = pimpleDict.lookupOrDefault<Switch>("SIMPLErho", false);
+    SIMPLErho_ = pimpleDict.lookupOrDefault("SIMPLErho", false);
     turbOnFinalIterOnly_ =
-        pimpleDict.lookupOrDefault<Switch>("turbOnFinalIterOnly", true);
+        pimpleDict.lookupOrDefault("turbOnFinalIterOnly", true);
 }
 
 
@@ -60,41 +59,42 @@ bool Foam::pimpleControl::criteriaSatisfied()
     }
 
 
-    bool storeIni = this->storeInitialResiduals();
+    const bool storeIni = this->storeInitialResiduals();
 
     bool achieved = true;
     bool checked = false;    // safety that some checks were indeed performed
 
     const dictionary& solverDict = mesh_.solverPerformanceDict();
-    forAllConstIter(dictionary, solverDict, iter)
+    forAllConstIters(solverDict, iter)
     {
-        const word& variableName = iter().keyword();
-        const label fieldi = applyToField(variableName);
+        const entry& solverPerfDictEntry = *iter;
+
+        const word& fieldName = solverPerfDictEntry.keyword();
+        const label fieldi = applyToField(fieldName);
+
         if (fieldi != -1)
         {
-            scalar residual = 0;
-            const scalar firstResidual =
-                maxResidual(variableName, iter().stream(), residual);
+            Pair<scalar> residuals = maxResidual(solverPerfDictEntry);
 
             checked = true;
 
+            scalar relative = 0.0;
+            bool relCheck = false;
+
+            const bool absCheck =
+                (residuals.last() < residualControl_[fieldi].absTol);
+
             if (storeIni)
             {
-                residualControl_[fieldi].initialResidual = firstResidual;
+                residualControl_[fieldi].initialResidual = residuals.first();
             }
-
-            const bool absCheck = residual < residualControl_[fieldi].absTol;
-            bool relCheck = false;
-
-            scalar relative = 0.0;
-            if (!storeIni)
+            else
             {
                 const scalar iniRes =
-                    residualControl_[fieldi].initialResidual
-                  + ROOTVSMALL;
+                    (residualControl_[fieldi].initialResidual + ROOTVSMALL);
 
-                relative = residual/iniRes;
-                relCheck = relative < residualControl_[fieldi].relTol;
+                relative = residuals.last() / iniRes;
+                relCheck = (relative < residualControl_[fieldi].relTol);
             }
 
             achieved = achieved && (absCheck || relCheck);
@@ -103,11 +103,11 @@ bool Foam::pimpleControl::criteriaSatisfied()
             {
                 Info<< algorithmName_ << " loop:" << endl;
 
-                Info<< "    " << variableName
+                Info<< "    " << fieldName
                     << " PIMPLE iter " << corr_
                     << ": ini res = "
                     << residualControl_[fieldi].initialResidual
-                    << ", abs tol = " << residual
+                    << ", abs tol = " << residuals.last()
                     << " (" << residualControl_[fieldi].absTol << ")"
                     << ", rel tol = " << relative
                     << " (" << residualControl_[fieldi].relTol << ")"
@@ -135,41 +135,37 @@ Foam::pimpleControl::pimpleControl(fvMesh& mesh, const word& dictName)
 {
     read();
 
+    Info<< nl
+        << algorithmName_;
+
     if (nCorrPIMPLE_ > 1)
     {
-        Info<< nl;
         if (residualControl_.empty())
         {
-            Info<< algorithmName_ << ": no residual control data found. "
+            Info<< ": no residual control data found. "
                 << "Calculations will employ " << nCorrPIMPLE_
-                << " corrector loops" << nl << endl;
+                << " corrector loops" << nl;
         }
         else
         {
-            Info<< algorithmName_ << ": max iterations = " << nCorrPIMPLE_
-                << endl;
-            forAll(residualControl_, i)
+            Info<< ": max iterations = " << nCorrPIMPLE_ << nl;
+
+            for (const fieldData& ctrl : residualControl_)
             {
-                Info<< "    field " << residualControl_[i].name << token::TAB
-                    << ": relTol " << residualControl_[i].relTol
-                    << ", tolerance " << residualControl_[i].absTol
+                Info<< "    field " << ctrl.name << token::TAB
+                    << ": relTol " << ctrl.relTol
+                    << ", tolerance " << ctrl.absTol
                     << nl;
             }
-            Info<< endl;
         }
     }
     else
     {
-        Info<< nl << algorithmName_ << ": Operating solver in PISO mode" << nl
-            << endl;
+        Info<< ": Operating solver in PISO mode" << nl;
     }
-}
-
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::pimpleControl::~pimpleControl()
-{}
+    Info<< endl;
+}
 
 
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
@@ -178,7 +174,7 @@ bool Foam::pimpleControl::loop()
 {
     read();
 
-    corr_++;
+    ++corr_;
 
     if (debug)
     {
@@ -187,7 +183,7 @@ bool Foam::pimpleControl::loop()
 
     if (corr_ == nCorrPIMPLE_ + 1)
     {
-        if ((!residualControl_.empty()) && (nCorrPIMPLE_ != 1))
+        if (!residualControl_.empty() && (nCorrPIMPLE_ != 1))
         {
             Info<< algorithmName_ << ": not converged within "
                 << nCorrPIMPLE_ << " iterations" << endl;
diff --git a/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControl.H b/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControl.H
index 5e87b20ea33..73134cdaabb 100644
--- a/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControl.H
+++ b/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControl.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2017 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -57,10 +57,10 @@ class pimpleControl
     // Private member functions
 
         //- Disallow default bitwise copy construct
-        pimpleControl(const pimpleControl&);
+        pimpleControl(const pimpleControl&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const pimpleControl&);
+        void operator=(const pimpleControl&) = delete;
 
 
 protected:
@@ -116,7 +116,7 @@ public:
 
 
     //- Destructor
-    virtual ~pimpleControl();
+    virtual ~pimpleControl() = default;
 
 
     // Member Functions
@@ -151,7 +151,7 @@ public:
             //- Return true for first PIMPLE (outer) iteration
             inline bool firstIter() const;
 
-            //- Return true fore final PIMPLE (outer) iteration
+            //- Return true for final PIMPLE (outer) iteration
             inline bool finalIter() const;
 
             //- Return true for final inner iteration
diff --git a/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControlI.H b/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControlI.H
index 268655c3d92..f283eb2512b 100644
--- a/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControlI.H
+++ b/src/finiteVolume/cfdTools/general/solutionControl/pimpleControl/pimpleControlI.H
@@ -51,7 +51,7 @@ inline bool Foam::pimpleControl::SIMPLErho() const
 
 inline bool Foam::pimpleControl::correct()
 {
-    corrPISO_++;
+    ++corrPISO_;
 
     if (debug)
     {
@@ -62,11 +62,9 @@ inline bool Foam::pimpleControl::correct()
     {
         return true;
     }
-    else
-    {
-        corrPISO_ = 0;
-        return false;
-    }
+
+    corrPISO_ = 0;
+    return false;
 }
 
 
diff --git a/src/finiteVolume/cfdTools/general/solutionControl/simpleControl/simpleControl.C b/src/finiteVolume/cfdTools/general/solutionControl/simpleControl/simpleControl.C
index 3724e38ea42..f0b3d68a5b4 100644
--- a/src/finiteVolume/cfdTools/general/solutionControl/simpleControl/simpleControl.C
+++ b/src/finiteVolume/cfdTools/general/solutionControl/simpleControl/simpleControl.C
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -53,26 +53,29 @@ bool Foam::simpleControl::criteriaSatisfied()
     bool checked = false;    // safety that some checks were indeed performed
 
     const dictionary& solverDict = mesh_.solverPerformanceDict();
-    forAllConstIter(dictionary, solverDict, iter)
+    forAllConstIters(solverDict, iter)
     {
-        const word& variableName = iter().keyword();
-        const label fieldi = applyToField(variableName);
+        const entry& solverPerfDictEntry = *iter;
+
+        const word& fieldName = solverPerfDictEntry.keyword();
+        const label fieldi = applyToField(fieldName);
+
         if (fieldi != -1)
         {
-            scalar lastResidual = 0;
-            const scalar residual =
-                maxResidual(variableName, iter().stream(), lastResidual);
-
+            Pair<scalar> residuals = maxResidual(solverPerfDictEntry);
             checked = true;
 
-            bool absCheck = residual < residualControl_[fieldi].absTol;
+            const bool absCheck =
+                (residuals.first() < residualControl_[fieldi].absTol);
+
             achieved = achieved && absCheck;
 
             if (debug)
             {
                 Info<< algorithmName_ << " solution statistics:" << endl;
 
-                Info<< "    " << variableName << ": tolerance = " << residual
+                Info<< "    " << fieldName << ": tolerance = "
+                    << residuals.first()
                     << " (" << residualControl_[fieldi].absTol << ")"
                     << endl;
             }
@@ -85,64 +88,53 @@ bool Foam::simpleControl::criteriaSatisfied()
 
 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
 
-Foam::simpleControl::simpleControl(fvMesh& mesh)
+Foam::simpleControl::simpleControl(fvMesh& mesh, const word& dictName)
 :
-    solutionControl(mesh, "SIMPLE"),
+    solutionControl(mesh, dictName),
     initialised_(false)
 {
     read();
 
-    Info<< nl;
+    Info<< nl
+        << algorithmName_;
 
     if (residualControl_.empty())
     {
-        Info<< algorithmName_ << ": no convergence criteria found. "
-            << "Calculations will run for "
+        Info<< ": no convergence criteria found. Calculations will run for "
             << mesh_.time().endTime().value() - mesh_.time().startTime().value()
-            << " steps." << nl << endl;
+            << " steps." << nl;
     }
     else
     {
-        Info<< algorithmName_ << ": convergence criteria" << nl;
-        forAll(residualControl_, i)
+        Info<< ": convergence criteria" << nl;
+        for (const fieldData& ctrl : residualControl_)
         {
-            Info<< "    field " << residualControl_[i].name << token::TAB
-                << " tolerance " << residualControl_[i].absTol
+            Info<< "    field " << ctrl.name << token::TAB
+                << " tolerance " << ctrl.absTol
                 << nl;
         }
-        Info<< endl;
     }
+    Info<< endl;
 }
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::simpleControl::~simpleControl()
-{}
-
-
 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
 
 bool Foam::simpleControl::loop()
 {
     read();
 
-    Time& time = const_cast<Time&>(mesh_.time());
+    Time& runTime = const_cast<Time&>(mesh_.time());
 
-    if (initialised_)
+    if (initialised_ && criteriaSatisfied())
     {
-        if (criteriaSatisfied())
-        {
-            Info<< nl << algorithmName_ << " solution converged in "
-                << time.timeName() << " iterations" << nl << endl;
+        Info<< nl
+            << algorithmName_
+            << " solution converged in "
+            << runTime.timeName() << " iterations" << nl << endl;
 
-            // Set to finalise calculation
-            time.writeAndEnd();
-        }
-        else
-        {
-            storePrevIterFields();
-        }
+        // Set to finalise calculation
+        runTime.writeAndEnd();
     }
     else
     {
@@ -150,8 +142,7 @@ bool Foam::simpleControl::loop()
         storePrevIterFields();
     }
 
-
-    return time.loop();
+    return runTime.loop();
 }
 
 
diff --git a/src/finiteVolume/cfdTools/general/solutionControl/simpleControl/simpleControl.H b/src/finiteVolume/cfdTools/general/solutionControl/simpleControl/simpleControl.H
index 8a44079a5c7..36849c75976 100644
--- a/src/finiteVolume/cfdTools/general/solutionControl/simpleControl/simpleControl.H
+++ b/src/finiteVolume/cfdTools/general/solutionControl/simpleControl/simpleControl.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2016 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -74,10 +74,10 @@ private:
     // Private member functions
 
         //- Disallow default bitwise copy construct
-        simpleControl(const simpleControl&);
+        simpleControl(const simpleControl&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const simpleControl&);
+        void operator=(const simpleControl&) = delete;
 
 
 public:
@@ -90,19 +90,19 @@ public:
 
     // Constructors
 
-        //- Construct from mesh
-        simpleControl(fvMesh& mesh);
+        //- Construct from mesh and the name of control sub-dictionary
+        simpleControl(fvMesh& mesh, const word& dictName="SIMPLE");
 
 
     //- Destructor
-    virtual ~simpleControl();
+    virtual ~simpleControl() = default;
 
 
     // Member Functions
 
         // Solution control
 
-            //- Loop loop
+            //- SIMPLE loop
             virtual bool loop();
 };
 
diff --git a/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControl.C b/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControl.C
index c5a47ca61ed..1d3596fb181 100644
--- a/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControl.C
+++ b/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControl.C
@@ -148,11 +148,7 @@ Foam::label Foam::solutionControl::applyToField
 {
     forAll(residualControl_, i)
     {
-        if (useRegEx && residualControl_[i].name.match(fieldName))
-        {
-            return i;
-        }
-        else if (residualControl_[i].name == fieldName)
+        if (residualControl_[i].name.match(fieldName, !useRegEx))
         {
             return i;
         }
@@ -173,42 +169,68 @@ void Foam::solutionControl::storePrevIterFields() const
 }
 
 
-template<class Type>
-void Foam::solutionControl::maxTypeResidual
+Foam::Pair<Foam::scalar> Foam::solutionControl::maxResidual
 (
-    const word& fieldName,
-    ITstream& data,
-    scalar& firstRes,
-    scalar& lastRes
+    const entry& solverPerfDictEntry
 ) const
+{
+    return maxResidual(mesh_, solverPerfDictEntry);
+}
+
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+template<class Type>
+bool Foam::solutionControl::maxTypeResidual
+(
+    const fvMesh& fvmesh,
+    const entry& solverPerfDictEntry,
+    Pair<scalar>& residuals
+)
 {
     typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
 
-    if (mesh_.foundObject<fieldType>(fieldName))
+    const word& fieldName = solverPerfDictEntry.keyword();
+
+    if (fvmesh.foundObject<fieldType>(fieldName))
     {
-        const List<SolverPerformance<Type>> sp(data);
-        firstRes = cmptMax(sp.first().initialResidual());
-        lastRes = cmptMax(sp.last().initialResidual());
+        const List<SolverPerformance<Type>> sp(solverPerfDictEntry.stream());
+
+        residuals.first() = cmptMax(sp.first().initialResidual());
+        residuals.last()  = cmptMax(sp.last().initialResidual());
+
+        return true;
     }
+
+    return false;
 }
 
 
-Foam::scalar Foam::solutionControl::maxResidual
+Foam::Pair<Foam::scalar> Foam::solutionControl::maxResidual
 (
-    const word& fieldName,
-    ITstream& data,
-    scalar& lastRes
-) const
+    const fvMesh& fvmesh,
+    const entry& solverPerfDictEntry
+)
 {
-    scalar firstRes = 0;
+    Pair<scalar> residuals(0,0);
 
-    maxTypeResidual<scalar>(fieldName, data, firstRes, lastRes);
-    maxTypeResidual<vector>(fieldName, data, firstRes, lastRes);
-    maxTypeResidual<sphericalTensor>(fieldName, data, firstRes, lastRes);
-    maxTypeResidual<symmTensor>(fieldName, data, firstRes, lastRes);
-    maxTypeResidual<tensor>(fieldName, data, firstRes, lastRes);
+    // Check with builtin short-circuit
+    const bool ok =
+    (
+        maxTypeResidual<scalar>(fvmesh, solverPerfDictEntry, residuals)
+     || maxTypeResidual<vector>(fvmesh, solverPerfDictEntry, residuals)
+     || maxTypeResidual<sphericalTensor>(fvmesh, solverPerfDictEntry, residuals)
+     || maxTypeResidual<symmTensor>(fvmesh, solverPerfDictEntry, residuals)
+     || maxTypeResidual<tensor>(fvmesh, solverPerfDictEntry, residuals)
+    );
 
-    return firstRes;
+    if (!ok && solutionControl::debug)
+    {
+        Info<<"no residual for " << solverPerfDictEntry.keyword()
+            << " on mesh " << fvmesh.name() << nl;
+    }
+
+    return residuals;
 }
 
 
@@ -235,10 +257,4 @@ Foam::solutionControl::solutionControl(fvMesh& mesh, const word& algorithmName)
 {}
 
 
-// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
-
-Foam::solutionControl::~solutionControl()
-{}
-
-
 // ************************************************************************* //
diff --git a/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControl.H b/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControl.H
index 19b45f724bd..921fbcd2580 100644
--- a/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControl.H
+++ b/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControl.H
@@ -3,7 +3,7 @@
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
     \\  /    A nd           | Copyright (C) 2011-2015 OpenFOAM Foundation
-     \\/     M anipulation  |
+     \\/     M anipulation  | Copyright (C) 2017 OpenCFD Ltd.
 -------------------------------------------------------------------------------
 License
     This file is part of OpenFOAM.
@@ -33,6 +33,7 @@ Description
 #define solutionControl_H
 
 #include "fvMesh.H"
+#include "Pair.H"
 
 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
 
@@ -49,6 +50,7 @@ class solutionControl
 {
 public:
 
+    //- Simple convenient storage of field residuals
     struct fieldData
     {
         wordRe name;
@@ -58,6 +60,20 @@ public:
     };
 
 
+    // Static Member Functions
+
+        //- Extract maximum residual for the solver performance entry,
+        //- provided the corresponding volume field is available on the mesh.
+        //
+        //  \return initial residual as first member, the final residual
+        //      as the second (or last) member
+        static Pair<scalar> maxResidual
+        (
+            const fvMesh& fvmesh,
+            const entry& dataDictEntry
+        );
+
+
 protected:
 
     // Protected data
@@ -126,30 +142,34 @@ protected:
         template<class Type>
         void storePrevIter() const;
 
+        //- Initial and final residual of the specified field-name,
+        //- provided that the corresponding volume field is available
+        //- on the fvMesh.
+        //
+        //  Populate residuals with initial residual as first member and
+        //  the final residual as second (last) member.
         template<class Type>
-        void maxTypeResidual
+        static bool maxTypeResidual
         (
-            const word& fieldName,
-            ITstream& data,
-            scalar& firstRes,
-            scalar& lastRes
-        ) const;
+            const fvMesh& fvmesh,
+            const entry& solverPerfDictEntry,
+            Pair<scalar>& residuals
+        );
 
-        scalar maxResidual
-        (
-            const word& fieldName,
-            ITstream& data,
-            scalar& lastRes
-        ) const;
+        //- Extract the maximum residual for the specified field
+        //
+        //  \return initial residual as first member, the final residual
+        //      as second (last) member
+        Pair<scalar> maxResidual(const entry& solverPerfDictEntry) const;
 
 
 private:
 
         //- Disallow default bitwise copy construct
-        solutionControl(const solutionControl&);
+        solutionControl(const solutionControl&) = delete;
 
         //- Disallow default bitwise assignment
-        void operator=(const solutionControl&);
+        void operator=(const solutionControl&) = delete;
 
 
 public:
@@ -168,7 +188,7 @@ public:
 
 
     //- Destructor
-    virtual ~solutionControl();
+    virtual ~solutionControl() = default;
 
 
     // Member Functions
diff --git a/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControlI.H b/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControlI.H
index d2316407c07..8fb196669b7 100644
--- a/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControlI.H
+++ b/src/finiteVolume/cfdTools/general/solutionControl/solutionControl/solutionControlI.H
@@ -81,7 +81,7 @@ inline bool Foam::solutionControl::frozenFlow() const
 
 inline bool Foam::solutionControl::correctNonOrthogonal()
 {
-    corrNonOrtho_++;
+    ++corrNonOrtho_;
 
     if (debug)
     {
@@ -93,11 +93,9 @@ inline bool Foam::solutionControl::correctNonOrthogonal()
     {
         return true;
     }
-    else
-    {
-        corrNonOrtho_ = 0;
-        return false;
-    }
+
+    corrNonOrtho_ = 0;
+    return false;
 }
 
 
-- 
GitLab