solutionControl: Multi-region and PIMPLE time-loop control

The solution controls have been rewritten for use in multi-region
solvers, and PIMPLE fluid/solid solution controls have been implemented
within this framework.

PIMPLE also now has time-loop convergence control which can be used to
end the simulation once a certain initial residual is reached. This
allows a PIMPLE solver to run with equivalent convergence control to a
SIMPLE solver. Corrector loop convergence control is still available,
and can be used at the same time as the time-loop control.

The "residualControl" sub-dictionary of PIMPLE contains the residual
values required on the first solve of a time-step for the simulation to
end. This behaviour is the same as SIMPLE. The
"outerCorrectorResidualControl" sub-dictionary contains the tolerances
required for the corrector loop to exit. An example specification with
both types of control active is shown below.

PIMPLE
{
    // ...

    residualControl
    {
        p               1e-3;
        U               1e-4;
        "(k|epsilon|omega)" 1e-3;
    }

    outerCorrectorResidualControl
    {
        U
        {
            tolerance       1e-4;
            relTol          0.1;
        }
        "(k|epsilon|omega)"
        {
            tolerance       1e-3;
            relTol          0.1;
        }
    }
}

Note that existing PIMPLE "residualControl" entries will need to be
renamed "outerCorrectorResidualControl".

Application within a solver has also changed slightly. In order to have
convergence control for the time loop as a whole, the
solutionControl::loop(Time&) method (or the equivalent run method) must
be used; i.e.,

    while (simple.loop(runTime))
    {
        Info<< "Time = " << runTime.timeName() << nl << endl;

        // solve ...
    }

or,

    while (pimple.run(runTime))
    {
        // pre-time-increment operations ...

        runTime ++;
        Info<< "Time = " << runTime.timeName() << nl << endl;

        // solve ...
    }
This commit is contained in:
Will Bainbridge
2018-01-12 12:10:01 +00:00
parent 08d5fce8ca
commit 4c8122783a
63 changed files with 4348 additions and 1324 deletions

View File

@ -0,0 +1,99 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "convergenceControl.H"
#include "volFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(convergenceControl, 0);
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::convergenceControl::getInitialResiduals
(
const fvMesh& mesh,
const word& fieldName,
const label solvei,
ITstream& data,
scalar& r0,
scalar& r
)
{
getInitialTypeResiduals<scalar>(mesh, fieldName, solvei, data, r0, r);
getInitialTypeResiduals<vector>(mesh, fieldName, solvei, data, r0, r);
getInitialTypeResiduals<sphericalTensor>
(
mesh,
fieldName,
solvei,
data,
r0,
r
);
getInitialTypeResiduals<symmTensor>(mesh, fieldName, solvei, data, r0, r);
getInitialTypeResiduals<tensor>(mesh, fieldName, solvei, data, r0, r);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::convergenceControl::convergenceControl(const solutionControl& control)
:
control_(control)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::convergenceControl::~convergenceControl()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::convergenceControl::converged()
{
if
(
control_.time().timeIndex() != control_.time().startTimeIndex()
&& criteriaSatisfied()
)
{
Info<< nl << control_.algorithmName() << " solution converged in "
<< control_.time().timeName() << " iterations" << nl << endl;
return true;
}
return false;
}
// ************************************************************************* //

View File

@ -0,0 +1,174 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::convergenceControl
Description
Convergence control class. Provides methods to check the convergence of the
time loop against an absolute residual tolerance.
SourceFiles
convergenceControl.C
convergenceControlTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef convergenceControl_H
#define convergenceControl_H
#include "fvMesh.H"
#include "solutionControl.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class convergenceControl Declaration
\*---------------------------------------------------------------------------*/
class convergenceControl
{
public:
//- Classes
//- Residual data structure
struct residualData
{
wordRe name;
scalar absTol;
};
// Static Functions
//- Get the initial residuals for the first and the i-th solves in this
// time-step
static void getInitialResiduals
(
const fvMesh& mesh,
const word& fieldName,
const label solvei,
ITstream& data,
scalar& r0,
scalar& r
);
// Static Template Functions
//- Return the index of the named field in residual control data, or -1
// if not present
template<class ResidualData>
static label residualControlIndex
(
const word& fieldName,
const List<ResidualData>& residualControl,
const bool useRegEx=true
);
//- Get the initial residuals for the first and the i-th solves in this
// time-step
template<class Type>
static void getInitialTypeResiduals
(
const fvMesh& mesh,
const word& fieldName,
const label solvei,
ITstream& data,
scalar& r0,
scalar& r
);
private:
// Private Member Functions
//- Disallow default bitwise copy construct
convergenceControl(const convergenceControl&);
//- Disallow default bitwise assignment
void operator=(const convergenceControl&);
protected:
// Protected data
//- Reference to the solution control
const solutionControl& control_;
public:
// Static Data Members
//- Run-time type information
TypeName("convergenceControl");
// Constructors
//- Construct from a solution control
convergenceControl(const solutionControl& control);
//- Destructor
virtual ~convergenceControl();
// Member Functions
// Evolution
//- Return true if residual controls are present
virtual bool hasResidualControls() const = 0;
//- Return true if all convergence checks are satisfied
virtual bool criteriaSatisfied() const = 0;
//- Flag to indicate whether convergance has been reached
bool converged();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "convergenceControlTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,74 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class ResidualData>
Foam::label Foam::convergenceControl::residualControlIndex
(
const word& fieldName,
const List<ResidualData>& residualControl,
const bool useRegEx
)
{
forAll(residualControl, i)
{
if (useRegEx && residualControl[i].name.match(fieldName))
{
return i;
}
else if (residualControl[i].name == fieldName)
{
return i;
}
}
return -1;
}
template<class Type>
void Foam::convergenceControl::getInitialTypeResiduals
(
const fvMesh& mesh,
const word& fieldName,
const label solvei,
ITstream& data,
scalar& r0,
scalar& r
)
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
if (mesh.foundObject<fieldType>(fieldName))
{
const List<SolverPerformance<Type>> sp(data);
r0 = cmptMax(sp[0].initialResidual());
r = cmptMax(sp[solvei].initialResidual());
}
}
// ************************************************************************* //

View File

@ -0,0 +1,74 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "correctorConvergenceControl.H"
#include "volFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(correctorConvergenceControl, 0);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::correctorConvergenceControl::getNSolves
(
const fvMesh& mesh,
const word& fieldName,
ITstream& data,
label& n
)
{
getNTypeSolves<scalar>(mesh, fieldName, data, n);
getNTypeSolves<vector>(mesh, fieldName, data, n);
getNTypeSolves<sphericalTensor>(mesh, fieldName, data, n);
getNTypeSolves<symmTensor>(mesh, fieldName, data, n);
getNTypeSolves<tensor>(mesh, fieldName, data, n);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::correctorConvergenceControl::correctorConvergenceControl
(
const solutionControl& control,
const word& loopName
)
:
control_(control),
loopName_(loopName)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::correctorConvergenceControl::~correctorConvergenceControl()
{}
// ************************************************************************* //

View File

@ -0,0 +1,170 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::correctorConvergenceControl
Description
Corrector convergence control class. Provides methods to check the
convergence of an inner iteration loop (e.g., PIMPLE) against both absolute
and relative residual tolerances.
SourceFiles
correctorConvergenceControl.C
correctorConvergenceControlTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef correctorConvergenceControl_H
#define correctorConvergenceControl_H
#include "fvMesh.H"
#include "solutionControl.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class correctorConvergenceControl Declaration
\*---------------------------------------------------------------------------*/
class correctorConvergenceControl
{
public:
//- Residual correction data structure
struct corrResidualData
{
wordRe name;
scalar absTol;
scalar relTol;
label solveIndex;
};
private:
// Private Member Functions
//- Disallow default bitwise copy construct
correctorConvergenceControl(const correctorConvergenceControl&);
//- Disallow default bitwise assignment
void operator=(const correctorConvergenceControl&);
protected:
// Protected data
//- Reference to the solution control
const solutionControl& control_;
//- Name of the corrector loop
const word loopName_;
// Protected Member Functions
//- Get the number of solves that have happened for this variable in
// this time-step
static void getNSolves
(
const fvMesh& mesh,
const word& fieldName,
ITstream& data,
label& n
);
// Protected Static Template Functions
//- Get the number of solves that have happened for this variable in
// this time-step
template<class Type>
static void getNTypeSolves
(
const fvMesh& mesh,
const word& fieldName,
ITstream& data,
label& n
);
public:
// Static Data Members
//- Run-time type information
TypeName("correctorConvergenceControl");
// Constructors
//- Construct from a solution control and the loop name
correctorConvergenceControl
(
const solutionControl& control,
const word& loopName
);
//- Destructor
virtual ~correctorConvergenceControl();
// Member Functions
// Evolution
//- Return true if corrector residual controls are present
virtual bool hasCorrResidualControls() const = 0;
//- Return true if all correction convergence checks are satisfied
virtual bool corrCriteriaSatisfied() const = 0;
//- Reset the solve index in the correction residual control data
virtual void resetCorrSolveIndex() = 0;
//- Update the solve index in the correction residual control data
virtual void updateCorrSolveIndex() = 0;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "correctorConvergenceControlTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,47 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
void Foam::correctorConvergenceControl::getNTypeSolves
(
const fvMesh& mesh,
const word& fieldName,
ITstream& data,
label& n
)
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
if (mesh.foundObject<fieldType>(fieldName))
{
const List<SolverPerformance<Type>> sp(data);
n = sp.size();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,193 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "singleRegionConvergenceControl.H"
#include "volFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(singleRegionConvergenceControl, 0);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::singleRegionConvergenceControl::singleRegionConvergenceControl
(
const singleRegionSolutionControl& control
)
:
convergenceControl(control),
mesh_(control.mesh()),
residualControl_()
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::singleRegionConvergenceControl::~singleRegionConvergenceControl()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::singleRegionConvergenceControl::readResidualControls()
{
const dictionary residualDict
(
control_.dict().subOrEmptyDict("residualControl")
);
DynamicList<residualData> data(residualControl_);
forAllConstIter(dictionary, residualDict, iter)
{
const word& fName = iter().keyword();
if (iter().isDict())
{
FatalErrorInFunction
<< "Solution convergence criteria specified in "
<< control_.algorithmName() << '.' << residualDict.dictName()
<< " must be given as single values. Corrector loop "
<< "convergence criteria, if appropriate, are specified as "
<< "dictionaries in " << control_.algorithmName()
<< ".<loopName>ResidualControl." << exit(FatalError);
}
const label fieldi =
residualControlIndex(fName, residualControl_, false);
if (fieldi == -1)
{
residualData rd;
rd.name = fName.c_str();
rd.absTol = readScalar(residualDict.lookup(fName));
data.append(rd);
}
else
{
residualData& rd = data[fieldi];
rd.absTol = readScalar(residualDict.lookup(fName));
}
}
residualControl_.transfer(data);
if (control_.debug > 1)
{
forAll(residualControl_, i)
{
const residualData& rd = residualControl_[i];
Info<< residualDict.dictName() << '[' << i << "]:" << nl
<< " name : " << rd.name << nl
<< " absTol : " << rd.absTol << endl;
}
}
return true;
}
void Foam::singleRegionConvergenceControl::printResidualControls() const
{
Info<< nl;
Info<< control_.algorithmName() << ": "
<< (residualControl_.empty() ? "No c" : "C")
<< "onvergence criteria found" << nl;
forAll(residualControl_, i)
{
Info<< control_.algorithmSpace() << " " << residualControl_[i].name
<< ": tolerance " << residualControl_[i].absTol << nl;
}
Info << endl;
}
bool Foam::singleRegionConvergenceControl::hasResidualControls() const
{
return !residualControl_.empty();
}
bool Foam::singleRegionConvergenceControl::criteriaSatisfied() const
{
if (!hasResidualControls())
{
return false;
}
bool achieved = true;
bool checked = false; // ensure that some checks were actually performed
if (control_.debug)
{
Info<< control_.algorithmName() << ": Residuals" << endl;
}
const dictionary& solverDict = mesh_.solverPerformanceDict();
forAllConstIter(dictionary, solverDict, iter)
{
const word& variableName = iter().keyword();
const label fieldi =
residualControlIndex(variableName, residualControl_);
if (fieldi != -1)
{
scalar residual;
getInitialResiduals
(
mesh_,
variableName,
0,
iter().stream(),
residual,
residual
);
checked = true;
bool absCheck = residual < residualControl_[fieldi].absTol;
achieved = achieved && absCheck;
if (control_.debug)
{
Info<< control_.algorithmSpace() << " " << variableName
<< ": tolerance " << residual << " ("
<< residualControl_[fieldi].absTol << ")"
<< (absCheck ? " CONVERGED" : "") << endl;
}
}
}
return checked && achieved;
}
// ************************************************************************* //

View File

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::singleRegionConvergenceControl
Description
Single-region-specific derivation of the convergence control class
SourceFiles
singleRegionConvergenceControl.C
\*---------------------------------------------------------------------------*/
#ifndef singleRegionConvergenceControl_H
#define singleRegionConvergenceControl_H
#include "convergenceControl.H"
#include "singleRegionSolutionControl.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class singleRegionConvergenceControl Declaration
\*---------------------------------------------------------------------------*/
class singleRegionConvergenceControl
:
public convergenceControl
{
protected:
// Protected data
//- Reference to the mesh
const fvMesh& mesh_;
//- List of residual data per field
List<residualData> residualControl_;
public:
// Static Data Members
//- Run-time type information
TypeName("singleRegionConvergenceControl");
// Constructors
//- Construct from a solution control
singleRegionConvergenceControl
(
const singleRegionSolutionControl& control
);
//- Destructor
virtual ~singleRegionConvergenceControl();
// Member Functions
// IO
//- Read residual controls
bool readResidualControls();
//- Print the residual controls
void printResidualControls() const;
// Evolution
//- Return true if residual controls are present
virtual bool hasResidualControls() const;
//- Return true if all convergence checks are satisfied
virtual bool criteriaSatisfied() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,272 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "singleRegionCorrectorConvergenceControl.H"
#include "convergenceControl.H"
#include "volFields.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(singleRegionCorrectorConvergenceControl, 0);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::singleRegionCorrectorConvergenceControl::
singleRegionCorrectorConvergenceControl
(
const singleRegionSolutionControl& control,
const word& loopName
)
:
correctorConvergenceControl(control, loopName),
mesh_(control.mesh()),
corrResidualControl_()
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::singleRegionCorrectorConvergenceControl::
~singleRegionCorrectorConvergenceControl()
{}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::singleRegionCorrectorConvergenceControl::readCorrResidualControls()
{
const dictionary residualDict
(
control_.dict().subOrEmptyDict(loopName_ + "ResidualControl")
);
DynamicList<corrResidualData> data(corrResidualControl_);
forAllConstIter(dictionary, residualDict, iter)
{
const word& fName = iter().keyword();
if (!iter().isDict())
{
FatalErrorInFunction
<< "Corrector loop convergence criteria specified in "
<< control_.algorithmName() << '.' << residualDict.dictName()
<< " must be given as dictionaries containing \"tolerance\" "
<< "and \"relTol\" entries. Solution convergence criteria are "
<< "specified as single numbers in " << control_.algorithmName()
<< ".residualControl." << exit(FatalError);
}
const label fieldi =
convergenceControl::residualControlIndex
(
fName,
corrResidualControl_,
false
);
if (fieldi == -1)
{
corrResidualData rd;
const dictionary& fieldDict(iter().dict());
rd.name = fName.c_str();
rd.absTol = readScalar(fieldDict.lookup("tolerance"));
rd.relTol = readScalar(fieldDict.lookup("relTol"));
rd.solveIndex = 0;
data.append(rd);
}
else
{
corrResidualData& rd = data[fieldi];
const dictionary& fieldDict(iter().dict());
rd.absTol = readScalar(fieldDict.lookup("tolerance"));
rd.relTol = readScalar(fieldDict.lookup("relTol"));
}
}
corrResidualControl_.transfer(data);
if (control_.debug > 1)
{
forAll(corrResidualControl_, i)
{
const corrResidualData& rd = corrResidualControl_[i];
Info<< residualDict.dictName() << '[' << i << "]:" << nl
<< " name : " << rd.name << nl
<< " absTol : " << rd.absTol << nl
<< " relTol : " << rd.relTol << endl;
}
}
return true;
}
void Foam::singleRegionCorrectorConvergenceControl::printCorrResidualControls
(
const label n
) const
{
Info<< nl;
Info<< control_.algorithmName() << ": "
<< (corrResidualControl_.empty() ? "No c" : "C")
<< "orrector convergence criteria found" << nl;
forAll(corrResidualControl_, i)
{
Info<< control_.algorithmSpace() << " "
<< corrResidualControl_[i].name << ": tolerance "
<< corrResidualControl_[i].absTol << ", relTol "
<< corrResidualControl_[i].relTol << nl;
}
Info<< control_.algorithmSpace() << " Calclations will do " << n
<< " corrections" << (corrResidualControl_.empty() ? "" :
" if the convergence criteria are not met") << nl << endl;
}
bool Foam::singleRegionCorrectorConvergenceControl::
hasCorrResidualControls() const
{
return !corrResidualControl_.empty();
}
bool Foam::singleRegionCorrectorConvergenceControl::
corrCriteriaSatisfied() const
{
if (!hasCorrResidualControls())
{
return false;
}
bool achieved = true;
bool checked = false; // ensure that some checks were actually performed
if (control_.debug)
{
Info<< control_.algorithmName() << ": Correction residuals" << endl;
}
const dictionary& solverDict = mesh_.solverPerformanceDict();
forAllConstIter(dictionary, solverDict, iter)
{
const word& variableName = iter().keyword();
const label fieldi =
convergenceControl::residualControlIndex
(
variableName,
corrResidualControl_
);
if (fieldi != -1)
{
scalar firstResidual, residual;
convergenceControl::getInitialResiduals
(
mesh_,
variableName,
corrResidualControl_[fieldi].solveIndex,
iter().stream(),
firstResidual,
residual
);
const scalar relativeResidual =
residual/(firstResidual + ROOTVSMALL);
const bool absCheck =
residual < corrResidualControl_[fieldi].absTol;
const bool relCheck =
relativeResidual < corrResidualControl_[fieldi].relTol;
checked = true;
achieved = achieved && (absCheck || relCheck);
if (control_.debug)
{
Info<< control_.algorithmSpace() << " " << variableName
<< ": tolerance " << residual << " ("
<< corrResidualControl_[fieldi].absTol << ")"
<< ", relTol " << relativeResidual << " ("
<< corrResidualControl_[fieldi].relTol << ")"
<< (absCheck || relCheck ? " CONVERGED" : "") << endl;
}
}
}
return checked && achieved;
}
void Foam::singleRegionCorrectorConvergenceControl::resetCorrSolveIndex()
{
const dictionary& solverDict = mesh_.solverPerformanceDict();
forAllConstIter(dictionary, solverDict, iter)
{
const word& variableName = iter().keyword();
const label fieldi =
convergenceControl::residualControlIndex
(
variableName,
corrResidualControl_
);
if (fieldi != -1)
{
corrResidualControl_[fieldi].solveIndex = 0;
}
}
}
void Foam::singleRegionCorrectorConvergenceControl::updateCorrSolveIndex()
{
const dictionary& solverDict = mesh_.solverPerformanceDict();
forAllConstIter(dictionary, solverDict, iter)
{
const word& variableName = iter().keyword();
const label fieldi =
convergenceControl::residualControlIndex
(
variableName,
corrResidualControl_
);
if (fieldi != -1)
{
getNSolves
(
mesh_,
variableName,
iter().stream(),
corrResidualControl_[fieldi].solveIndex
);
}
}
}
// ************************************************************************* //

View File

@ -0,0 +1,123 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::singleRegionCorrectorConvergenceControl
Description
Single-region-specific derivation of the corrector convergence control
class
SourceFiles
singleRegionCorrectorConvergenceControl.C
\*---------------------------------------------------------------------------*/
#ifndef singleRegionCorrectorConvergenceControl_H
#define singleRegionCorrectorConvergenceControl_H
#include "correctorConvergenceControl.H"
#include "singleRegionSolutionControl.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class singleRegionCorrectorConvergenceControl Declaration
\*---------------------------------------------------------------------------*/
class singleRegionCorrectorConvergenceControl
:
public correctorConvergenceControl
{
protected:
// Protected data
//- Reference to the mesh
const fvMesh& mesh_;
//- List of residual data per field
List<corrResidualData> corrResidualControl_;
public:
// Static Data Members
//- Run-time type information
TypeName("singleRegionCorrectorConvergenceControl");
// Constructors
//- Construct from a solution control and the loop name
singleRegionCorrectorConvergenceControl
(
const singleRegionSolutionControl& control,
const word& loopName
);
//- Destructor
virtual ~singleRegionCorrectorConvergenceControl();
// Member Functions
// IO
//- Read residual controls
bool readCorrResidualControls();
//- Print the residual controls
void printCorrResidualControls(const label n) const;
// Evolution
//- Return true if corrector residual controls are present
virtual bool hasCorrResidualControls() const;
//- Return true if all correction convergence checks are satisfied
virtual bool corrCriteriaSatisfied() const;
//- Reset the solve index in the correction residual control data
virtual void resetCorrSolveIndex();
//- Update the solve index in the correction residual control data
virtual void updateCorrSolveIndex();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //