1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
5 \\ / A nd | 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 Minimal Polynomial Extrapolation Algebraic Multigrid solver with run-time
26 selection of policy and cycle
29 Hrvoje Jasak, Wikki Ltd. All rights reserved
31 \*---------------------------------------------------------------------------*/
33 #include "mpeAmgSolver.H"
34 #include "scalarMatrices.H"
35 #include "DenseMatrixTools.H"
36 #include "FieldFields.H"
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
43 defineTypeNameAndDebug(mpeAmgSolver, 0);
45 lduSolver::addsymMatrixConstructorToTable<mpeAmgSolver>
46 addmpeAmgSolverSymMatrixConstructorToTable_;
48 lduSolver::addasymMatrixConstructorToTable<mpeAmgSolver>
49 addmpeAmgSolverAsymMatrixConstructorToTable_;
53 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
55 //- Construct from matrix and solver data stream
56 Foam::mpeAmgSolver::mpeAmgSolver
58 const word& fieldName,
59 const lduMatrix& matrix,
60 const FieldField<Field, scalar>& coupleBouCoeffs,
61 const FieldField<Field, scalar>& coupleIntCoeffs,
62 const lduInterfaceFieldPtrsList& interfaces,
63 const dictionary& dict
83 kDimension_(readLabel(dict.lookup("kDimension")))
87 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
89 Foam::lduSolverPerformance Foam::mpeAmgSolver::solve
96 // Prepare solver performance
97 lduSolverPerformance solverPerf(typeName, fieldName());
99 scalar normFactor = this->normFactor(x, b, cmpt);
101 // Calculate initial residual
102 solverPerf.initialResidual() =
103 gSumMag(amg_.residual(x, b, cmpt))/normFactor;
105 solverPerf.finalResidual() = solverPerf.initialResidual();
110 if (!stop(solverPerf))
113 typedef FieldField<Field, scalar> scalarFieldField;
115 scalarFieldField xSave(kDimension_ + 1);
119 xSave.set(i, new scalarField(x.size()));
122 scalarFieldField xFirstDiffs(kDimension_ - 1);
124 forAll (xFirstDiffs, i)
126 xFirstDiffs.set(i, new scalarField(x.size()));
129 scalarField xRhs(x.size());
132 scalarSquareMatrix AN(kDimension_ - 1);
133 scalarField xN(kDimension_ - 1);
134 scalarField bN(kDimension_ - 1);
136 // Remember last extrapolation index
137 label lastExtrapolation = kDimension_;
139 scalarField psiSave(x.size());
143 amg_.cycle(x, b, cmpt);
145 label curIndex = (solverPerf.nIterations()) % (kDimension_ + 1);
152 solverPerf.nIterations() >= lastExtrapolation
153 && curIndex == kDimension_
156 // Calculate differences
157 for (label i = 0; i < kDimension_ - 1; i++)
159 xFirstDiffs[i] = xSave[i] - xSave[kDimension_];
162 // Grab right-hand side
163 xRhs = xSave[kDimension_] - xSave[kDimension_ - 1];
165 // Perform Q-R decomposition
166 DenseMatrixTools::qrDecompose
173 // Solve the normal system
174 for (label i = 0; i < kDimension_ - 1; i++)
176 bN[i] = -gSum(xFirstDiffs[i]*xRhs);
179 DenseMatrixTools::solve(AN, xN, bN);
181 // Reset last interpolation factor
182 xN[kDimension_ - 2] = 1.0;
188 // Re-asemble the solution. HJ, variants?
189 x = xSave[kDimension_];
191 for (label i = 0; i < kDimension_ - 1; i++)
193 xFirstDiffs[0] = xSave[i + 1] - xSave[i];
194 x += xN[i]*xFirstDiffs[0];
197 // Increment last extrapolation
198 lastExtrapolation = solverPerf.nIterations() + kDimension_;
201 // Re-calculate residual
202 solverPerf.finalResidual() =
203 gSumMag(amg_.residual(x, b, cmpt))/normFactor;
204 solverPerf.nIterations()++;
205 } while (!stop(solverPerf));
212 // ************************************************************************* //