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/>.
24 \*---------------------------------------------------------------------------*/
26 #include "GAMGSolver.H"
31 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
33 Foam::lduMatrix::solverPerformance Foam::GAMGSolver::solve
40 // Setup class containing solver performance data
41 lduSolverPerformance solverPerf(typeName, fieldName());
43 // Calculate A.x used to calculate the initial residual
44 scalarField Ax(x.size());
45 matrix_.Amul(Ax, x, coupleBouCoeffs_, interfaces_, cmpt);
47 // Create the storage for the finestCorrection which may be used as a
48 // temporary in normFactor
49 scalarField finestCorrection(x.size());
51 // Calculate normalisation factor
52 scalar normFactor = this->normFactor(x, b, Ax, finestCorrection, cmpt);
56 Info<< " Normalisation factor = " << normFactor << endl;
59 // Calculate initial finest-grid residual field
60 scalarField finestResidual(b - Ax);
62 // Calculate normalised residual for convergence test
63 solverPerf.initialResidual() = gSumMag(finestResidual)/normFactor;
64 solverPerf.finalResidual() = solverPerf.initialResidual();
67 // Check convergence, solve if not converged
68 if (!stop(solverPerf))
70 // Create coarse grid correction fields
71 PtrList<scalarField> coarseCorrX;
73 // Create coarse grid bs
74 PtrList<scalarField> coarseB;
76 // Create the smoothers for all levels
77 PtrList<lduSmoother> smoothers;
79 // Initialise the above data structures
80 initVcycle(coarseCorrX, coarseB, smoothers);
97 // Calculate finest level residual field
98 matrix_.Amul(Ax, x, coupleBouCoeffs_, interfaces_, cmpt);
100 finestResidual -= Ax;
102 solverPerf.finalResidual() = gSumMag(finestResidual)/normFactor;
103 solverPerf.nIterations()++;
108 } while (!stop(solverPerf));
115 void Foam::GAMGSolver::Vcycle
117 const PtrList<lduSmoother>& smoothers,
119 const scalarField& b,
121 scalarField& finestCorrection,
122 scalarField& finestResidual,
123 PtrList<scalarField>& coarseCorrX,
124 PtrList<scalarField>& coarseB,
130 const label coarsestLevel = matrixLevels_.size() - 1;
132 // Restrict finest grid residual for the next level up
133 agglomeration_.restrictField(coarseB[0], finestResidual, 0);
135 if (debug >= 2 && nPreSweeps_)
137 Pout<< "Pre-smoothing scaling factors: ";
141 // Residual restriction (going to coarser levels)
142 for (label leveli = 0; leveli < coarsestLevel; leveli++)
144 // If the optional pre-smoothing sweeps are selected
145 // smooth the coarse-grid field for the restricted b
148 coarseCorrX[leveli] = 0.0;
150 smoothers[leveli + 1].smooth
158 scalarField::subField ACf
161 coarseCorrX[leveli].size()
164 // Scale coarse-grid correction field
165 // but not on the coarsest level because it evaluates to 1
166 if (scaleCorrection_ && leveli < coarsestLevel - 1)
168 scalar sf = scalingFactor
170 const_cast<scalarField&>(ACf.operator const scalarField&()),
171 matrixLevels_[leveli],
173 coupleLevelsBouCoeffs_[leveli],
174 interfaceLevels_[leveli],
184 coarseCorrX[leveli] *= sf;
187 // Correct the residual with the new solution
188 matrixLevels_[leveli].Amul
190 const_cast<scalarField&>(ACf.operator const scalarField&()),
192 coupleLevelsBouCoeffs_[leveli],
193 interfaceLevels_[leveli],
197 coarseB[leveli] -= ACf;
200 // Residual is equal to b
201 agglomeration_.restrictField
209 if (debug >= 2 && nPreSweeps_)
215 // Solve Coarsest level with either an iterative or direct solver
218 coarseCorrX[coarsestLevel],
219 coarseB[coarsestLevel]
225 Pout<< "Post-smoothing scaling factors: ";
228 // Smoothing and prolongation of the coarse correction fields
229 // (going to finer levels)
230 for (label leveli = coarsestLevel - 1; leveli >= 0; leveli--)
232 // Create a field for the pre-smoothed correction field
233 // as a sub-field of the finestCorrection which is not
234 // currently being used
235 scalarField::subField preSmoothedCoarseCorrField
238 coarseCorrX[leveli].size()
241 // Only store the preSmoothedCoarseCorrField is pre-smoothing is used
244 preSmoothedCoarseCorrField.assign(coarseCorrX[leveli]);
247 agglomeration_.prolongField
250 coarseCorrX[leveli + 1],
254 // Scale coarse-grid correction field
255 // but not on the coarsest level because it evaluates to 1
256 if (scaleCorrection_ && leveli < coarsestLevel - 1)
258 // Create A.x for this coarse level as a sub-field of Ax
259 scalarField::subField ACf
262 coarseCorrX[leveli].size()
265 scalar sf = scalingFactor
267 const_cast<scalarField&>(ACf.operator const scalarField&()),
268 matrixLevels_[leveli],
270 coupleLevelsBouCoeffs_[leveli],
271 interfaceLevels_[leveli],
282 coarseCorrX[leveli] *= sf;
285 // Only add the preSmoothedCoarseCorrField is pre-smoothing is used
288 coarseCorrX[leveli] += preSmoothedCoarseCorrField;
291 smoothers[leveli + 1].smooth
296 nPostSweeps_ + leveli
300 // Prolong the finest level correction
301 agglomeration_.prolongField
308 if (scaleCorrection_)
310 // Calculate finest level scaling factor
311 scalar fsf = scalingFactor
329 x[i] += fsf*finestCorrection[i];
336 x[i] += finestCorrection[i];
350 void Foam::GAMGSolver::initVcycle
352 PtrList<scalarField>& coarseCorrX,
353 PtrList<scalarField>& coarseB,
354 PtrList<lduSmoother>& smoothers
357 coarseCorrX.setSize(matrixLevels_.size());
358 coarseB.setSize(matrixLevels_.size());
359 smoothers.setSize(matrixLevels_.size() + 1);
361 // Create the smoother for the finest level
375 forAll (matrixLevels_, leveli)
382 agglomeration_.meshLevel(leveli + 1).lduAddr().size()
391 agglomeration_.meshLevel(leveli + 1).lduAddr().size()
400 matrixLevels_[leveli],
401 coupleLevelsBouCoeffs_[leveli],
402 coupleLevelsIntCoeffs_[leveli],
403 interfaceLevels_[leveli],
411 void Foam::GAMGSolver::solveCoarsestLevel
413 scalarField& coarsestCorrX,
414 const scalarField& coarsestB
417 if (directSolveCoarsest_)
419 coarsestCorrX = coarsestB;
420 coarsestLUMatrixPtr_->solve(coarsestCorrX);
424 const label coarsestLevel = matrixLevels_.size() - 1;
426 lduSolverPerformance coarseSolverPerf;
428 if (matrixLevels_[coarsestLevel].asymmetric())
430 coarseSolverPerf = BICCG
433 matrixLevels_[coarsestLevel],
434 coupleLevelsBouCoeffs_[coarsestLevel],
435 coupleLevelsIntCoeffs_[coarsestLevel],
436 interfaceLevels_[coarsestLevel],
447 coarseSolverPerf = ICCG
450 matrixLevels_[coarsestLevel],
451 coupleLevelsBouCoeffs_[coarsestLevel],
452 coupleLevelsIntCoeffs_[coarsestLevel],
453 interfaceLevels_[coarsestLevel],
465 coarseSolverPerf.print();
471 // ************************************************************************* //