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
31 Hrvoje Jasak, Wikki Ltd. All rights reserved
33 \*---------------------------------------------------------------------------*/
35 #include "coarseAmgLevel.H"
37 #include "gmresSolver.H"
40 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
42 // Construct from components
43 Foam::coarseAmgLevel::coarseAmgLevel
45 autoPtr<amgMatrix> matrixPtr,
46 const dictionary& dict,
47 const word& policyType,
48 const label groupSize,
49 const label minCoarseEqns,
50 const word& smootherType
53 matrixPtr_(matrixPtr),
54 x_(matrixPtr_->size()),
55 b_(matrixPtr_->size()),
72 matrixPtr_->coupleBouCoeffs(),
73 matrixPtr_->coupleIntCoeffs(),
74 matrixPtr_->interfaceFields(),
81 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
83 Foam::coarseAmgLevel::~coarseAmgLevel()
87 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
89 Foam::scalarField& Foam::coarseAmgLevel::x()
95 Foam::scalarField& Foam::coarseAmgLevel::b()
101 void Foam::coarseAmgLevel::residual
103 const scalarField& x,
104 const scalarField& b,
105 const direction cmpt,
109 // Calculate residual
110 matrixPtr_->matrix().Amul
114 matrixPtr_->coupleBouCoeffs(),
115 matrixPtr_->interfaceFields(),
122 res[i] = b[i] - res[i];
127 void Foam::coarseAmgLevel::restrictResidual
129 const scalarField& x,
130 const scalarField& b,
131 const direction cmpt,
132 scalarField& xBuffer,
133 scalarField& coarseRes,
139 // Calculate residual
140 scalarField::subField resBuf(xBuffer, x.size());
142 scalarField& res = const_cast<scalarField&>
144 resBuf.operator const scalarField&()
147 residual(x, b, cmpt, res);
149 policyPtr_->restrictResidual(res, coarseRes);
153 // No pre-sweeps done: x = 0 and residual = b
154 policyPtr_->restrictResidual(b, coarseRes);
159 void Foam::coarseAmgLevel::prolongateCorrection
162 const scalarField& coarseX
165 policyPtr_->prolongateCorrection(x, coarseX);
169 void Foam::coarseAmgLevel::smooth
172 const scalarField& b,
173 const direction cmpt,
177 smootherPtr_->smooth(x, b, cmpt, nSweeps);
181 void Foam::coarseAmgLevel::solve
184 const scalarField& b,
185 const direction cmpt,
186 const scalar tolerance,
190 lduSolverPerformance coarseSolverPerf;
192 label maxIter = Foam::min(2*policyPtr_->minCoarseEqns(), 1000);
194 dictionary topLevelDict;
195 topLevelDict.add("nDirections", "5");
196 topLevelDict.add("minIter", 1);
197 topLevelDict.add("maxIter", maxIter);
198 topLevelDict.add("tolerance", tolerance);
199 topLevelDict.add("relTol", relTol);
201 // Avoid issues with round-off on strict tolerance setup
203 x = b/matrixPtr_->matrix().diag();
205 // Do not solve if the number of equations is smaller than 5
206 if (policyPtr_->minCoarseEqns() < 5)
211 // Switch of debug in top-level direct solve
212 label oldDebug = lduMatrix::debug();
214 if (matrixPtr_->matrix().symmetric())
216 topLevelDict.add("preconditioner", "Cholesky");
218 coarseSolverPerf = gmresSolver
221 matrixPtr_->matrix(),
222 matrixPtr_->coupleBouCoeffs(),
223 matrixPtr_->coupleIntCoeffs(),
224 matrixPtr_->interfaceFields(),
230 topLevelDict.add("preconditioner", "ILU0");
232 coarseSolverPerf = gmresSolver
235 matrixPtr_->matrix(),
236 matrixPtr_->coupleBouCoeffs(),
237 matrixPtr_->coupleIntCoeffs(),
238 matrixPtr_->interfaceFields(),
244 lduMatrix::debug = oldDebug;
246 // Escape cases of top-level solver divergence
249 coarseSolverPerf.nIterations() == maxIter
251 coarseSolverPerf.finalResidual()
252 >= coarseSolverPerf.initialResidual()
256 // Top-level solution failed. Attempt rescue
258 x = b/matrixPtr_->matrix().diag();
260 // Print top level correction failure as info for user
261 coarseSolverPerf.print();
264 if (lduMatrix::debug >= 2)
266 coarseSolverPerf.print();
271 void Foam::coarseAmgLevel::scaleX
274 const scalarField& b,
275 const direction cmpt,
280 scalarField::subField Ax(xBuffer, x.size());
282 matrixPtr_->matrix().Amul
284 const_cast<scalarField&>(Ax.operator const scalarField&()),
286 matrixPtr_->coupleBouCoeffs(),
287 matrixPtr_->interfaceFields(),
291 scalar scalingFactorNum = 0.0;
292 scalar scalingFactorDenom = 0.0;
296 scalingFactorNum += x[i]*b[i];
297 scalingFactorDenom += x[i]*xBuffer[i]; // Note: Ax = xBuffer
300 vector2D scalingVector(scalingFactorNum, scalingFactorDenom);
301 reduce(scalingVector, sumOp<vector2D>());
306 mag(scalingVector[0]) > GREAT
307 || mag(scalingVector[1]) > GREAT
308 || scalingVector[0]*scalingVector[1] <= 0
309 || mag(scalingVector[0]) < mag(scalingVector[1])
312 // Factor = 1.0, no scaling
314 else if (mag(scalingVector[0]) > 2*mag(scalingVector[1]))
322 x *= scalingVector[0]/stabilise(scalingVector[1], SMALL);
327 Foam::autoPtr<Foam::amgLevel> Foam::coarseAmgLevel::makeNextLevel() const
329 if (policyPtr_->coarsen())
331 return autoPtr<Foam::amgLevel>
335 policyPtr_->restrictMatrix
337 matrixPtr_->coupleBouCoeffs(),
338 matrixPtr_->coupleIntCoeffs(),
339 matrixPtr_->interfaceFields()
343 policyPtr_->groupSize(),
344 policyPtr_->minCoarseEqns(),
351 // Final level: cannot coarsen
352 return autoPtr<Foam::amgLevel>();
357 // ************************************************************************* //