1 /*---------------------------------------------------------------------------*\
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 -------------------------------------------------------------------------------
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/>.
25 Preconditioned Generalised Minimal Residual solver with
26 run-time selectable preconditioning
28 \*---------------------------------------------------------------------------*/
30 #include "BlockGMRESSolver.H"
31 #include "FieldField.H"
32 #include "scalarMatrices.H"
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 void Foam::BlockGMRESSolver<Type>::givensRotation
50 else if (mag(beta) > mag(h))
53 s = 1.0/Foam::sqrt(1.0 + sqr(tau));
59 c = 1.0/Foam::sqrt(1.0 + sqr(tau));
65 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
67 //- Construct from matrix and solver data stream
69 Foam::BlockGMRESSolver<Type>::BlockGMRESSolver
71 const word& fieldName,
72 const BlockLduMatrix<Type>& matrix,
73 const dictionary& dict
76 BlockIterativeSolver<Type>
84 BlockLduPrecon<Type>::New
90 nDirs_(readLabel(this->dict().lookup("nDirections")))
94 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
97 typename Foam::BlockSolverPerformance<Type>
98 Foam::BlockGMRESSolver<Type>::solve
104 // Create local references to avoid the spread this-> ugliness
105 const BlockLduMatrix<Type>& matrix = this->matrix_;
107 // Prepare solver performance
108 BlockSolverPerformance<Type> solverPerf
114 scalar norm = this->normFactor(x, b);
116 Field<Type> wA(x.size());
118 // Calculate initial residual
120 Field<Type> rA(b - wA);
122 solverPerf.initialResidual() = gSum(cmptMag(rA))/norm;
123 solverPerf.finalResidual() = solverPerf.initialResidual();
125 // Check convergence, solve if not converged
127 if (!this->stop(solverPerf))
129 // Create the Hesenberg matrix
130 scalarSquareMatrix H(nDirs_, 0);
132 // Create y and b for Hessenberg matrix
133 scalarField yh(nDirs_, 0);
134 scalarField bh(nDirs_ + 1, 0);
136 // Givens rotation vectors
137 scalarField c(nDirs_, 0);
138 scalarField s(nDirs_, 0);
140 // Allocate Krylov space vectors
141 FieldField<Field, Type> V(nDirs_ + 1);
145 V.set(i, new Field<Type>(x.size(), pTraits<Type>::zero));
150 // Execute preconditioning
151 preconPtr_->precondition(wA, rA);
153 // Calculate beta and scale first vector
154 scalar beta = Foam::sqrt(gSumProd(wA, wA));
156 // Set initial rhs and bh[0] = beta
160 for (label i = 0; i < nDirs_; i++)
162 // Set search direction
167 matrix.Amul(rA, V[i]);
169 // Execute preconditioning
170 preconPtr_->precondition(wA, rA);
172 for (label j = 0; j <= i; j++)
174 beta = gSumProd(wA, V[j]);
180 wA[wI] -= beta*V[j][wI];
184 beta = Foam::sqrt(gSumProd(wA, wA));
186 // Apply previous Givens rotations to new column of H.
187 for (label j = 0; j < i; j++)
189 const scalar Hji = H[j][i];
190 H[j][i] = c[j]*Hji - s[j]*H[j + 1][i];
191 H[j + 1][i] = s[j]*Hji + c[j]*H[j + 1][i];
194 // Apply Givens rotation to current row.
195 givensRotation(H[i][i], beta, c[i], s[i]);
197 const scalar bhi = bh[i];
198 bh[i] = c[i]*bhi - s[i]*bh[i + 1];
199 bh[i + 1] = s[i]*bhi + c[i]*bh[i + 1];
200 H[i][i] = c[i]*H[i][i] - s[i]*beta;
203 // Back substitute to solve Hy = b
204 for (label i = nDirs_ - 1; i >= 0; i--)
208 for (label j = i + 1; j < nDirs_; j++)
210 sum -= H[i][j]*yh[j];
218 for (label i = 0; i < nDirs_; i++)
220 const Field<Type>& Vi = V[i];
221 const scalar& yi = yh[i];
229 // Re-calculate the residual
234 rA[raI] = b[raI] - wA[raI];
237 solverPerf.finalResidual() = gSum(cmptMag(rA))/norm;
238 solverPerf.nIterations()++;
239 } while (!this->stop(solverPerf));
246 // ************************************************************************* //