1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "GAMGSolver.H"
31 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
33 Foam::lduMatrix::solverPerformance Foam::GAMGSolver::solve
36 const scalarField& source,
40 // Setup class containing solver performance data
41 lduMatrix::solverPerformance solverPerf(typeName, fieldName_);
43 // Calculate A.psi used to calculate the initial residual
44 scalarField Apsi(psi.size());
45 matrix_.Amul(Apsi, psi, interfaceBouCoeffs_, interfaces_, cmpt);
47 // Create the storage for the finestCorrection which may be used as a
48 // temporary in normFactor
49 scalarField finestCorrection(psi.size());
51 // Calculate normalisation factor
52 scalar normFactor = this->normFactor(psi, source, Apsi, finestCorrection);
56 Pout<< " Normalisation factor = " << normFactor << endl;
59 // Calculate initial finest-grid residual field
60 scalarField finestResidual(source - Apsi);
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 (!solverPerf.checkConvergence(tolerance_, relTol_))
70 // Create coarse grid correction fields
71 PtrList<scalarField> coarseCorrFields;
73 // Create coarse grid sources
74 PtrList<scalarField> coarseSources;
76 // Create the smoothers for all levels
77 PtrList<lduMatrix::smoother> smoothers;
79 // Initialise the above data structures
80 initVcycle(coarseCorrFields, coarseSources, smoothers);
97 // Calculate finest level residual field
98 matrix_.Amul(Apsi, psi, interfaceBouCoeffs_, interfaces_, cmpt);
99 finestResidual = source;
100 finestResidual -= Apsi;
102 solverPerf.finalResidual() = gSumMag(finestResidual)/normFactor;
110 ++solverPerf.nIterations() < maxIter_
111 && !(solverPerf.checkConvergence(tolerance_, relTol_))
119 void Foam::GAMGSolver::Vcycle
121 const PtrList<lduMatrix::smoother>& smoothers,
123 const scalarField& source,
125 scalarField& finestCorrection,
126 scalarField& finestResidual,
127 PtrList<scalarField>& coarseCorrFields,
128 PtrList<scalarField>& coarseSources,
134 const label coarsestLevel = matrixLevels_.size() - 1;
136 // Restrict finest grid residual for the next level up
137 agglomeration_.restrictField(coarseSources[0], finestResidual, 0);
139 if (debug >= 2 && nPreSweeps_)
141 Pout<< "Pre-smoothing scaling factors: ";
145 // Residual restriction (going to coarser levels)
146 for (label leveli = 0; leveli < coarsestLevel; leveli++)
148 // If the optional pre-smoothing sweeps are selected
149 // smooth the coarse-grid field for the restriced source
152 coarseCorrFields[leveli] = 0.0;
154 smoothers[leveli + 1].smooth
156 coarseCorrFields[leveli],
157 coarseSources[leveli],
162 scalarField::subField ACf
165 coarseCorrFields[leveli].size()
168 // Scale coarse-grid correction field
169 // but not on the coarsest level because it evaluates to 1
170 if (scaleCorrection_ && leveli < coarsestLevel - 1)
172 scalar sf = scalingFactor
174 const_cast<scalarField&>(ACf.operator const scalarField&()),
175 matrixLevels_[leveli],
176 coarseCorrFields[leveli],
177 interfaceLevelsBouCoeffs_[leveli],
178 interfaceLevels_[leveli],
179 coarseSources[leveli],
188 coarseCorrFields[leveli] *= sf;
191 // Correct the residual with the new solution
192 matrixLevels_[leveli].Amul
194 const_cast<scalarField&>(ACf.operator const scalarField&()),
195 coarseCorrFields[leveli],
196 interfaceLevelsBouCoeffs_[leveli],
197 interfaceLevels_[leveli],
201 coarseSources[leveli] -= ACf;
204 // Residual is equal to source
205 agglomeration_.restrictField
207 coarseSources[leveli + 1],
208 coarseSources[leveli],
213 if (debug >= 2 && nPreSweeps_)
219 // Solve Coarsest level with either an iterative or direct solver
222 coarseCorrFields[coarsestLevel],
223 coarseSources[coarsestLevel]
229 Pout<< "Post-smoothing scaling factors: ";
232 // Smoothing and prolongation of the coarse correction fields
233 // (going to finer levels)
234 for (label leveli = coarsestLevel - 1; leveli >= 0; leveli--)
236 // Create a field for the pre-smoothed correction field
237 // as a sub-field of the finestCorrection which is not
238 // currently being used
239 scalarField::subField preSmoothedCoarseCorrField
242 coarseCorrFields[leveli].size()
245 // Only store the preSmoothedCoarseCorrField is pre-smoothing is used
248 preSmoothedCoarseCorrField.assign(coarseCorrFields[leveli]);
251 agglomeration_.prolongField
253 coarseCorrFields[leveli],
254 coarseCorrFields[leveli + 1],
258 // Scale coarse-grid correction field
259 // but not on the coarsest level because it evaluates to 1
260 if (scaleCorrection_ && leveli < coarsestLevel - 1)
262 // Create A.psi for this coarse level as a sub-field of Apsi
263 scalarField::subField ACf
266 coarseCorrFields[leveli].size()
269 scalar sf = scalingFactor
271 const_cast<scalarField&>(ACf.operator const scalarField&()),
272 matrixLevels_[leveli],
273 coarseCorrFields[leveli],
274 interfaceLevelsBouCoeffs_[leveli],
275 interfaceLevels_[leveli],
276 coarseSources[leveli],
286 coarseCorrFields[leveli] *= sf;
289 // Only add the preSmoothedCoarseCorrField is pre-smoothing is used
292 coarseCorrFields[leveli] += preSmoothedCoarseCorrField;
295 smoothers[leveli + 1].smooth
297 coarseCorrFields[leveli],
298 coarseSources[leveli],
300 nPostSweeps_ + leveli
304 // Prolong the finest level correction
305 agglomeration_.prolongField
312 if (scaleCorrection_)
314 // Calculate finest level scaling factor
315 scalar fsf = scalingFactor
333 psi[i] += fsf*finestCorrection[i];
340 psi[i] += finestCorrection[i];
354 void Foam::GAMGSolver::initVcycle
356 PtrList<scalarField>& coarseCorrFields,
357 PtrList<scalarField>& coarseSources,
358 PtrList<lduMatrix::smoother>& smoothers
361 coarseCorrFields.setSize(matrixLevels_.size());
362 coarseSources.setSize(matrixLevels_.size());
363 smoothers.setSize(matrixLevels_.size() + 1);
365 // Create the smoother for the finest level
369 lduMatrix::smoother::New
380 forAll(matrixLevels_, leveli)
387 agglomeration_.meshLevel(leveli + 1).lduAddr().size()
396 agglomeration_.meshLevel(leveli + 1).lduAddr().size()
403 lduMatrix::smoother::New
406 matrixLevels_[leveli],
407 interfaceLevelsBouCoeffs_[leveli],
408 interfaceLevelsIntCoeffs_[leveli],
409 interfaceLevels_[leveli],
417 void Foam::GAMGSolver::solveCoarsestLevel
419 scalarField& coarsestCorrField,
420 const scalarField& coarsestSource
423 if (directSolveCoarsest_)
425 coarsestCorrField = coarsestSource;
426 coarsestLUMatrixPtr_->solve(coarsestCorrField);
430 const label coarsestLevel = matrixLevels_.size() - 1;
431 coarsestCorrField = 0;
432 lduMatrix::solverPerformance coarseSolverPerf;
434 if (matrixLevels_[coarsestLevel].asymmetric())
436 coarseSolverPerf = BICCG
439 matrixLevels_[coarsestLevel],
440 interfaceLevelsBouCoeffs_[coarsestLevel],
441 interfaceLevelsIntCoeffs_[coarsestLevel],
442 interfaceLevels_[coarsestLevel],
453 coarseSolverPerf = ICCG
456 matrixLevels_[coarsestLevel],
457 interfaceLevelsBouCoeffs_[coarsestLevel],
458 interfaceLevelsIntCoeffs_[coarsestLevel],
459 interfaceLevels_[coarsestLevel],
471 coarseSolverPerf.print();
477 // ************************************************************************* //