Forward compatibility: flex
[foam-extend-3.2.git] / src / foam / matrices / lduMatrix / solvers / PCG / PCG.C
blob3214760d05d42b5fe0e2d605afb3bf7ef463f9da
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
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 "PCG.H"
28 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 namespace Foam
32     defineTypeNameAndDebug(PCG, 0);
34     lduSolver::addsymMatrixConstructorToTable<PCG>
35         addPCGSymMatrixConstructorToTable_;
39 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
41 Foam::PCG::PCG
43     const word& fieldName,
44     const lduMatrix& matrix,
45     const FieldField<Field, scalar>& coupleBouCoeffs,
46     const FieldField<Field, scalar>& coupleIntCoeffs,
47     const lduInterfaceFieldPtrsList& interfaces,
48     const dictionary& dict
51     lduSolver
52     (
53         fieldName,
54         matrix,
55         coupleBouCoeffs,
56         coupleIntCoeffs,
57         interfaces,
58         dict
59     )
63 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
65 Foam::lduSolverPerformance Foam::PCG::solve
67     scalarField& x,
68     const scalarField& b,
69     const direction cmpt
70 ) const
72     // --- Setup class containing solver performance data
73     lduSolverPerformance solverPerf(typeName, fieldName());
75     register label nCells = x.size();
77     scalar* __restrict__ xPtr = x.begin();
79     scalarField pA(nCells);
80     scalar* __restrict__ pAPtr = pA.begin();
82     scalarField wA(nCells);
83     scalar* __restrict__ wAPtr = wA.begin();
85     // Calculate A.x
86     matrix_.Amul(wA, x, coupleBouCoeffs_, interfaces_, cmpt);
88     // Calculate initial residual field
89     scalarField rA(b - wA);
90     scalar* __restrict__ rAPtr = rA.begin();
92     // Calculate normalisation factor
93     scalar normFactor = this->normFactor(x, b, wA, pA, cmpt);
95     if (lduMatrix::debug >= 2)
96     {
97         Info<< "   Normalisation factor = " << normFactor << endl;
98     }
100     // Calculate normalised residual norm
101     solverPerf.initialResidual() = gSumMag(rA)/normFactor;
102     solverPerf.finalResidual() = solverPerf.initialResidual();
104     // Check convergence, solve if not converged
105     if (!stop(solverPerf))
106     {
107         scalar wArA = matrix_.great_;
108         scalar wArAold = wArA;
110         // Select and construct the preconditioner
111         autoPtr<lduPreconditioner> preconPtr;
113         preconPtr =
114             lduPreconditioner::New
115             (
116                 matrix_,
117                 coupleBouCoeffs_,
118                 coupleIntCoeffs_,
119                 interfaces_,
120                 dict()
121             );
123         // Rename the solver pefformance to include precon name
124         solverPerf.solverName() = preconPtr->type() + typeName;
126         // Solver iteration
127         do
128         {
129             // Store previous wArA
130             wArAold = wArA;
132             // Precondition residual
133             preconPtr->precondition(wA, rA, cmpt);
135             // Update search directions:
136             wArA = gSumProd(wA, rA);
138             if (solverPerf.nIterations() == 0)
139             {
140                 for (register label cell=0; cell<nCells; cell++)
141                 {
142                     pAPtr[cell] = wAPtr[cell];
143                 }
144             }
145             else
146             {
147                 scalar beta = wArA/wArAold;
149                 for (register label cell=0; cell<nCells; cell++)
150                 {
151                     pAPtr[cell] = wAPtr[cell] + beta*pAPtr[cell];
152                 }
153             }
156             // Update preconditioned residual
157             matrix_.Amul(wA, pA, coupleBouCoeffs_, interfaces_, cmpt);
159             scalar wApA = gSumProd(wA, pA);
162             // Test for singularity
163             if (solverPerf.checkSingularity(mag(wApA)/normFactor)) break;
166             // Update solution and residual:
168             scalar alpha = wArA/wApA;
170             for (register label cell=0; cell<nCells; cell++)
171             {
172                 xPtr[cell] += alpha*pAPtr[cell];
173                 rAPtr[cell] -= alpha*wAPtr[cell];
174             }
176             solverPerf.finalResidual() = gSumMag(rA)/normFactor;
177             solverPerf.nIterations()++;
178         } while (!stop(solverPerf));
179     }
181     return solverPerf;
185 // ************************************************************************* //