PBiCGStab: New preconditioned bi-conjugate gradient stabilized solver for asymmetric lduMatrices
using a run-time selectable preconditioner
References:
Van der Vorst, H. A. (1992).
Bi-CGSTAB: A fast and smoothly converging variant of Bi-CG
for the solution of nonsymmetric linear systems.
SIAM Journal on scientific and Statistical Computing, 13(2), 631-644.
Barrett, R., Berry, M. W., Chan, T. F., Demmel, J., Donato, J.,
Dongarra, J., Eijkhout, V., Pozo, R., Romine, C. & Van der Vorst, H.
(1994).
Templates for the solution of linear systems:
building blocks for iterative methods
(Vol. 43). Siam.
See also: https://en.wikipedia.org/wiki/Biconjugate_gradient_stabilized_method
Tests have shown that PBiCGStab with the DILU preconditioner is more
robust, reliable and shows faster convergence (~2x) than PBiCG with
DILU, in particular in parallel where PBiCG occasionally diverges.
This commit is contained in:
parent
168b29e2cf
commit
1ca4bbf1d2
3 changed files with 376 additions and 0 deletions
|
|
@ -271,6 +271,7 @@ $(lduMatrix)/solvers/diagonalSolver/diagonalSolver.C
|
|||
$(lduMatrix)/solvers/smoothSolver/smoothSolver.C
|
||||
$(lduMatrix)/solvers/PCG/PCG.C
|
||||
$(lduMatrix)/solvers/PBiCG/PBiCG.C
|
||||
$(lduMatrix)/solvers/PBiCGStab/PBiCGStab.C
|
||||
|
||||
$(lduMatrix)/smoothers/GaussSeidel/GaussSeidelSmoother.C
|
||||
$(lduMatrix)/smoothers/symGaussSeidel/symGaussSeidelSmoother.C
|
||||
|
|
|
|||
252
src/OpenFOAM/matrices/lduMatrix/solvers/PBiCGStab/PBiCGStab.C
Normal file
252
src/OpenFOAM/matrices/lduMatrix/solvers/PBiCGStab/PBiCGStab.C
Normal file
|
|
@ -0,0 +1,252 @@
|
|||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2016 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 "PBiCGStab.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
defineTypeNameAndDebug(PBiCGStab, 0);
|
||||
|
||||
lduMatrix::solver::addasymMatrixConstructorToTable<PBiCGStab>
|
||||
addPBiCGStabAsymMatrixConstructorToTable_;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::PBiCGStab::PBiCGStab
|
||||
(
|
||||
const word& fieldName,
|
||||
const lduMatrix& matrix,
|
||||
const FieldField<Field, scalar>& interfaceBouCoeffs,
|
||||
const FieldField<Field, scalar>& interfaceIntCoeffs,
|
||||
const lduInterfaceFieldPtrsList& interfaces,
|
||||
const dictionary& solverControls
|
||||
)
|
||||
:
|
||||
lduMatrix::solver
|
||||
(
|
||||
fieldName,
|
||||
matrix,
|
||||
interfaceBouCoeffs,
|
||||
interfaceIntCoeffs,
|
||||
interfaces,
|
||||
solverControls
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::solverPerformance Foam::PBiCGStab::solve
|
||||
(
|
||||
scalarField& psi,
|
||||
const scalarField& source,
|
||||
const direction cmpt
|
||||
) const
|
||||
{
|
||||
// --- Setup class containing solver performance data
|
||||
solverPerformance solverPerf
|
||||
(
|
||||
lduMatrix::preconditioner::getName(controlDict_) + typeName,
|
||||
fieldName_
|
||||
);
|
||||
|
||||
const label nCells = psi.size();
|
||||
|
||||
scalar* __restrict__ psiPtr = psi.begin();
|
||||
|
||||
scalarField pA(nCells);
|
||||
scalar* __restrict__ pAPtr = pA.begin();
|
||||
|
||||
scalarField yA(nCells);
|
||||
scalar* __restrict__ yAPtr = yA.begin();
|
||||
|
||||
// --- Calculate A.psi
|
||||
matrix_.Amul(yA, psi, interfaceBouCoeffs_, interfaces_, cmpt);
|
||||
|
||||
// --- Calculate initial residual field
|
||||
scalarField rA(source - yA);
|
||||
scalar* __restrict__ rAPtr = rA.begin();
|
||||
|
||||
// --- Calculate normalisation factor
|
||||
const scalar normFactor = this->normFactor(psi, source, yA, pA);
|
||||
|
||||
if (lduMatrix::debug >= 2)
|
||||
{
|
||||
Info<< " Normalisation factor = " << normFactor << endl;
|
||||
}
|
||||
|
||||
// --- Calculate normalised residual norm
|
||||
solverPerf.initialResidual() =
|
||||
gSumMag(rA, matrix().mesh().comm())
|
||||
/normFactor;
|
||||
solverPerf.finalResidual() = solverPerf.initialResidual();
|
||||
|
||||
// --- Check convergence, solve if not converged
|
||||
if
|
||||
(
|
||||
minIter_ > 0
|
||||
|| !solverPerf.checkConvergence(tolerance_, relTol_)
|
||||
)
|
||||
{
|
||||
scalarField AyA(nCells);
|
||||
scalar* __restrict__ AyAPtr = AyA.begin();
|
||||
|
||||
scalarField sA(nCells);
|
||||
scalar* __restrict__ sAPtr = sA.begin();
|
||||
|
||||
scalarField zA(nCells);
|
||||
scalar* __restrict__ zAPtr = zA.begin();
|
||||
|
||||
scalarField tA(nCells);
|
||||
scalar* __restrict__ tAPtr = tA.begin();
|
||||
|
||||
// --- Store initial residual
|
||||
const scalarField rA0(rA);
|
||||
|
||||
// --- Initial values not used
|
||||
scalar rA0rA = 0;
|
||||
scalar alpha = 0;
|
||||
scalar omega = 0;
|
||||
|
||||
// --- Select and construct the preconditioner
|
||||
autoPtr<lduMatrix::preconditioner> preconPtr =
|
||||
lduMatrix::preconditioner::New
|
||||
(
|
||||
*this,
|
||||
controlDict_
|
||||
);
|
||||
|
||||
// --- Solver iteration
|
||||
do
|
||||
{
|
||||
// --- Store previous rA0rA
|
||||
const scalar rA0rAold = rA0rA;
|
||||
|
||||
rA0rA = gSumProd(rA0, rA, matrix().mesh().comm());
|
||||
|
||||
// --- Test for singularity
|
||||
if (solverPerf.checkSingularity(mag(rA0rA)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// --- Update pA
|
||||
if (solverPerf.nIterations() == 0)
|
||||
{
|
||||
for (label cell=0; cell<nCells; cell++)
|
||||
{
|
||||
pAPtr[cell] = rAPtr[cell];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// --- Test for singularity
|
||||
if (solverPerf.checkSingularity(mag(omega)))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
const scalar beta = (rA0rA/rA0rAold)*(alpha/omega);
|
||||
|
||||
for (label cell=0; cell<nCells; cell++)
|
||||
{
|
||||
pAPtr[cell] =
|
||||
rAPtr[cell] + beta*(pAPtr[cell] - omega*AyAPtr[cell]);
|
||||
}
|
||||
}
|
||||
|
||||
// --- Precondition pA
|
||||
preconPtr->precondition(yA, pA, cmpt);
|
||||
|
||||
// --- Calculate AyA
|
||||
matrix_.Amul(AyA, yA, interfaceBouCoeffs_, interfaces_, cmpt);
|
||||
|
||||
const scalar rA0AyA = gSumProd(rA0, AyA, matrix().mesh().comm());
|
||||
|
||||
alpha = rA0rA/rA0AyA;
|
||||
|
||||
// --- Calculate sA
|
||||
for (label cell=0; cell<nCells; cell++)
|
||||
{
|
||||
sAPtr[cell] = rAPtr[cell] - alpha*AyAPtr[cell];
|
||||
}
|
||||
|
||||
// --- Test sA for convergence
|
||||
solverPerf.finalResidual() =
|
||||
gSumMag(sA, matrix().mesh().comm())/normFactor;
|
||||
|
||||
if (solverPerf.checkConvergence(tolerance_, relTol_))
|
||||
{
|
||||
for (label cell=0; cell<nCells; cell++)
|
||||
{
|
||||
psiPtr[cell] += alpha*yAPtr[cell];
|
||||
}
|
||||
|
||||
solverPerf.nIterations()++;
|
||||
|
||||
return solverPerf;
|
||||
}
|
||||
|
||||
// --- Precondition sA
|
||||
preconPtr->precondition(zA, sA, cmpt);
|
||||
|
||||
// --- Calculate tA
|
||||
matrix_.Amul(tA, zA, interfaceBouCoeffs_, interfaces_, cmpt);
|
||||
|
||||
const scalar tAtA = gSumSqr(tA, matrix().mesh().comm());
|
||||
|
||||
// --- Calculate omega from tA and sA
|
||||
// (cheaper than using zA with preconditioned tA)
|
||||
omega = gSumProd(tA, sA)/tAtA;
|
||||
|
||||
// --- Update solution and residual
|
||||
for (label cell=0; cell<nCells; cell++)
|
||||
{
|
||||
psiPtr[cell] += alpha*yAPtr[cell] + omega*zAPtr[cell];
|
||||
rAPtr[cell] = sAPtr[cell] - omega*tAPtr[cell];
|
||||
}
|
||||
|
||||
solverPerf.finalResidual() =
|
||||
gSumMag(rA, matrix().mesh().comm())
|
||||
/normFactor;
|
||||
} while
|
||||
(
|
||||
(
|
||||
solverPerf.nIterations()++ < maxIter_
|
||||
&& !solverPerf.checkConvergence(tolerance_, relTol_)
|
||||
)
|
||||
|| solverPerf.nIterations() < minIter_
|
||||
);
|
||||
}
|
||||
|
||||
return solverPerf;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
123
src/OpenFOAM/matrices/lduMatrix/solvers/PBiCGStab/PBiCGStab.H
Normal file
123
src/OpenFOAM/matrices/lduMatrix/solvers/PBiCGStab/PBiCGStab.H
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2016 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::PBiCGStab
|
||||
|
||||
Description
|
||||
Preconditioned bi-conjugate gradient stabilized solver for asymmetric
|
||||
lduMatrices using a run-time selectable preconditioner.
|
||||
|
||||
References:
|
||||
\verbatim
|
||||
Van der Vorst, H. A. (1992).
|
||||
Bi-CGSTAB: A fast and smoothly converging variant of Bi-CG
|
||||
for the solution of nonsymmetric linear systems.
|
||||
SIAM Journal on scientific and Statistical Computing, 13(2), 631-644.
|
||||
|
||||
Barrett, R., Berry, M. W., Chan, T. F., Demmel, J., Donato, J.,
|
||||
Dongarra, J., Eijkhout, V., Pozo, R., Romine, C. & Van der Vorst, H.
|
||||
(1994).
|
||||
Templates for the solution of linear systems:
|
||||
building blocks for iterative methods
|
||||
(Vol. 43). Siam.
|
||||
\endverbatim
|
||||
|
||||
SourceFiles
|
||||
PBiCGStab.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef PBiCGStab_H
|
||||
#define PBiCGStab_H
|
||||
|
||||
#include "lduMatrix.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class PBiCGStab Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class PBiCGStab
|
||||
:
|
||||
public lduMatrix::solver
|
||||
{
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
PBiCGStab(const PBiCGStab&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const PBiCGStab&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("PBiCGStab");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct from matrix components and solver data stream
|
||||
PBiCGStab
|
||||
(
|
||||
const word& fieldName,
|
||||
const lduMatrix& matrix,
|
||||
const FieldField<Field, scalar>& interfaceBouCoeffs,
|
||||
const FieldField<Field, scalar>& interfaceIntCoeffs,
|
||||
const lduInterfaceFieldPtrsList& interfaces,
|
||||
const dictionary& solverControls
|
||||
);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~PBiCGStab()
|
||||
{}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Solve the matrix with this solver
|
||||
virtual solverPerformance solve
|
||||
(
|
||||
scalarField& psi,
|
||||
const scalarField& source,
|
||||
const direction cmpt=0
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
Loading…
Add table
Reference in a new issue