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/>.
28 Coarse AMG level stores matrix, x and b locally, for BlockLduMatrix
31 Klas Jareteg, 2012-12-13
33 \*---------------------------------------------------------------------------*/
35 #include "coarseBlockAmgLevel.H"
38 #include "coeffFields.H"
39 #include "BlockSolverPerformance.H"
40 // #include "BlockBiCGStabSolver.H"
41 // #include "BlockCGSolver.H"
42 #include "BlockGMRESSolver.H"
44 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
46 // Construct from components
48 Foam::coarseBlockAmgLevel<Type>::coarseBlockAmgLevel
50 autoPtr<lduPrimitiveMesh> addrPtr,
51 autoPtr<BlockLduMatrix<Type> > matrixPtr,
52 const dictionary& dict,
53 const word& coarseningType,
54 const label groupSize,
55 const label minCoarseEqns
59 matrixPtr_(matrixPtr),
60 x_(matrixPtr_->diag().size(),pTraits<Type>::zero),
61 b_(matrixPtr_->diag().size(),pTraits<Type>::zero),
65 BlockMatrixCoarsening<Type>::New
76 BlockLduSmoother<Type>::New
87 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
90 Foam::coarseBlockAmgLevel<Type>::~coarseBlockAmgLevel()
94 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
97 Foam::Field<Type>& Foam::coarseBlockAmgLevel<Type>::x()
104 Foam::Field<Type>& Foam::coarseBlockAmgLevel<Type>::b()
111 void Foam::coarseBlockAmgLevel<Type>::residual
113 const Field<Type>& x,
114 const Field<Type>& b,
118 // Calculate residual
128 res[i] = b[i] - res[i];
134 void Foam::coarseBlockAmgLevel<Type>::restrictResidual
136 const Field<Type>& x,
137 const Field<Type>& b,
138 Field<Type>& xBuffer,
139 Field<Type>& coarseRes,
145 // Calculate residual
146 // KRJ: 2012-12-14 ::subField removed. Creating buffer locally
147 Field<Type> resBuf(x.size());
149 Field<Type>& res = reinterpret_cast<Field<Type>&>(resBuf);
153 coarseningPtr_->restrictResidual(res, coarseRes);
157 // No pre-sweeps done: x = 0 and residual = b
158 coarseningPtr_->restrictResidual(b, coarseRes);
164 void Foam::coarseBlockAmgLevel<Type>::prolongateCorrection
167 const Field<Type>& coarseX
170 coarseningPtr_->prolongateCorrection(x, coarseX);
175 void Foam::coarseBlockAmgLevel<Type>::smooth
178 const Field<Type>& b,
182 smootherPtr_->smooth(x, b, nSweeps);
187 void Foam::coarseBlockAmgLevel<Type>::solve
190 const Field<Type>& b,
191 const scalar tolerance,
195 BlockSolverPerformance<Type> coarseSolverPerf
197 BlockGMRESSolver<Type>::typeName,
201 label maxIter = Foam::min(2*coarseningPtr_->minCoarseEqns(), 1000);
203 // Create artificial dictionary for top-level solution
204 dictionary topLevelDict;
205 topLevelDict.add("nDirections", "5");
206 topLevelDict.add("minIter", 1);
207 topLevelDict.add("maxIter", maxIter);
208 topLevelDict.add("tolerance", tolerance);
209 topLevelDict.add("relTol", relTol);
211 // Avoid issues with round-off on strict tolerance setup
213 // Create multiplication function object
214 typename BlockCoeff<Type>::multiply mult;
216 // x = inverse(diag) & b
217 CoeffField<Type> invDiag = inv(matrixPtr_->diag());
218 multiply(x, invDiag, b);
220 // Do not solve if the number of equations is smaller than 5
221 if (coarseningPtr_->minCoarseEqns() < 5)
226 // Switch of debug in top-level direct solve
227 label oldDebug = BlockLduMatrix<Type>::debug();
229 if (BlockLduMatrix<Type>::debug >= 4)
231 BlockLduMatrix<Type>::debug = 1;
235 BlockLduMatrix<Type>::debug = 0;
238 if (matrixPtr_->symmetric())
240 topLevelDict.add("preconditioner", "Cholesky");
243 // BlockCGSolver<Type>
244 BlockGMRESSolver<Type>
253 topLevelDict.add("preconditioner", "Cholesky");
256 // BlockBiCGStabSolver<Type>
257 BlockGMRESSolver<Type>
266 BlockLduMatrix<Type>::debug = oldDebug;
268 // Escape cases of top-level solver divergence
271 coarseSolverPerf.nIterations() == maxIter
273 coarseSolverPerf.finalResidual()
274 >= coarseSolverPerf.initialResidual()
278 // Top-level solution failed. Attempt rescue
280 multiply(x, invDiag, b);
282 // Print top level correction failure as info for user
283 coarseSolverPerf.print();
286 if (BlockLduMatrix<Type>::debug >= 2)
288 coarseSolverPerf.print();
294 void Foam::coarseBlockAmgLevel<Type>::scaleX
297 const Field<Type>& b,
301 // KRJ: 2013-02-05: Removed subfield, creating a new field
302 // Initialise and size buffer to avoid multiple allocation.
303 // Buffer is created as private data of AMG level
307 Ax_.setSize(x.size());
310 matrixPtr_->Amul(Ax_, x);
314 // Variant 1 (old): scale complete x with a single scaling factor
315 scalar scalingFactorNum = sumProd(x, b);
316 scalar scalingFactorDenom = sumProd(x, Ax_);
318 vector2D scalingVector(scalingFactorNum, scalingFactorDenom);
319 reduce(scalingVector, sumOp<vector2D>());
324 mag(scalingVector[0]) > GREAT
325 || mag(scalingVector[1]) > GREAT
326 || scalingVector[0]*scalingVector[1] <= 0
327 || mag(scalingVector[0]) < mag(scalingVector[1])
330 // Factor = 1.0, no scaling
332 else if (mag(scalingVector[0]) > 2*mag(scalingVector[1]))
340 x *= scalingVector[0]/stabilise(scalingVector[1], VSMALL);
345 // Variant 2: scale each x individually
347 Type scalingFactorNum = sumCmptProd(x, b);
348 Type scalingFactorDenom = sumCmptProd(x, Ax_);
350 Vector2D<Type> scalingVector(scalingFactorNum, scalingFactorDenom);
351 reduce(scalingVector, sumOp<Vector2D<Type> >());
353 Type scalingFactor = pTraits<Type>::one;
356 for (direction dir = 0; dir < pTraits<Type>::nComponents; dir++)
358 scalar num = component(scalingVector[0], dir);
359 scalar denom = component(scalingVector[1], dir);
363 mag(num) > GREAT || mag(denom) > GREAT
364 || num*denom <= 0 || mag(num) < mag(denom)
367 // Factor = 1.0, no scaling
369 else if (mag(num) > 2*mag(denom))
371 setComponent(scalingFactor, dir) = 2;
376 setComponent(scalingFactor, dir) = num/stabilise(denom, VSMALL);
381 cmptMultiply(x, x, scalingFactor);
388 Foam::autoPtr<Foam::BlockAmgLevel<Type> >
389 Foam::coarseBlockAmgLevel<Type>::makeNextLevel() const
391 if (coarseningPtr_->coarsen())
393 return coarseningPtr_->restrictMatrix();
397 // Final level: cannot coarsen
398 return autoPtr<BlockAmgLevel<Type> >();
403 // ************************************************************************* //