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 Incomplete Cholesky preconditioning with no fill-in for coupled matrices
31 Hrvoje Jasak, Wikki Ltd. All rights reserved.
33 \*----------------------------------------------------------------------------*/
35 #include "coupledCholeskyPrecon.H"
36 #include "addToRunTimeSelectionTable.H"
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
42 defineTypeNameAndDebug(coupledCholeskyPrecon, 0);
44 addToRunTimeSelectionTable
47 coupledCholeskyPrecon,
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
55 void Foam::coupledCholeskyPrecon::calcPreconDiag()
57 // Precondition the diagonal
58 forAll (matrix_, rowI)
60 const lduMatrix& rowMatrix = matrix_[rowI];
62 preconDiag_.set(rowI, new scalarField(rowMatrix.diag()));
63 scalarField& rowPreconDiag = preconDiag_[rowI];
65 if (rowMatrix.symmetric())
67 const unallocLabelList& upperAddr = rowMatrix.lduAddr().upperAddr();
68 const unallocLabelList& lowerAddr = rowMatrix.lduAddr().lowerAddr();
70 // Get off-diagonal matrix coefficients
71 const scalarField& upper = rowMatrix.upper();
73 forAll (upper, coeffI)
75 rowPreconDiag[upperAddr[coeffI]] -=
76 sqr(upper[coeffI])/rowPreconDiag[lowerAddr[coeffI]];
79 else if (rowMatrix.asymmetric())
81 const unallocLabelList& upperAddr = rowMatrix.lduAddr().upperAddr();
82 const unallocLabelList& lowerAddr = rowMatrix.lduAddr().lowerAddr();
84 // Get off-diagonal matrix coefficients
85 const scalarField& upper = rowMatrix.upper();
86 const scalarField& lower = rowMatrix.lower();
88 forAll (upper, coeffI)
90 rowPreconDiag[upperAddr[coeffI]] -=
91 upper[coeffI]*lower[coeffI]/
92 rowPreconDiag[lowerAddr[coeffI]];
96 // Invert the diagonal for future use
97 forAll (rowPreconDiag, i)
99 rowPreconDiag[i] = 1.0/rowPreconDiag[i];
105 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
107 Foam::coupledCholeskyPrecon::coupledCholeskyPrecon
109 const coupledLduMatrix& matrix,
110 const PtrList<FieldField<Field, scalar> >& bouCoeffs,
111 const PtrList<FieldField<Field, scalar> >& intCoeffs,
112 const lduInterfaceFieldPtrsListList& interfaces
122 preconDiag_(matrix.size())
128 Foam::coupledCholeskyPrecon::coupledCholeskyPrecon
130 const coupledLduMatrix& matrix,
131 const PtrList<FieldField<Field, scalar> >& bouCoeffs,
132 const PtrList<FieldField<Field, scalar> >& intCoeffs,
133 const lduInterfaceFieldPtrsListList& interfaces,
134 const dictionary& dict
144 preconDiag_(matrix.size())
150 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
152 void Foam::coupledCholeskyPrecon::precondition
154 FieldField<Field, scalar>& x,
155 const FieldField<Field, scalar>& b,
159 // Cholesky precondition all matrices
160 forAll (matrix_, rowI)
162 scalarField& rowX = x[rowI];
163 const scalarField& rowB = b[rowI];
165 const lduMatrix& rowMatrix = matrix_[rowI];
166 const scalarField& rowPreconDiag = preconDiag_[rowI];
170 rowX[i] = rowB[i]*rowPreconDiag[i];
173 if (rowMatrix.symmetric())
175 const unallocLabelList& upperAddr = rowMatrix.lduAddr().upperAddr();
176 const unallocLabelList& lowerAddr = rowMatrix.lduAddr().lowerAddr();
178 // Get off-diagonal matrix coefficients
179 const scalarField& upper = rowMatrix.upper();
181 forAll (upper, coeffI)
183 rowX[upperAddr[coeffI]] -=
184 rowPreconDiag[upperAddr[coeffI]]*
185 upper[coeffI]*rowX[lowerAddr[coeffI]];
188 forAllReverse (upper, coeffI)
190 rowX[lowerAddr[coeffI]] -=
191 rowPreconDiag[lowerAddr[coeffI]]*
192 upper[coeffI]*rowX[upperAddr[coeffI]];
195 else if (rowMatrix.asymmetric())
197 const unallocLabelList& upperAddr = rowMatrix.lduAddr().upperAddr();
198 const unallocLabelList& lowerAddr = rowMatrix.lduAddr().lowerAddr();
199 const unallocLabelList& losortAddr =
200 rowMatrix.lduAddr().losortAddr();
202 // Get off-diagonal matrix coefficients
203 const scalarField& upper = rowMatrix.upper();
204 const scalarField& lower = rowMatrix.lower();
208 forAll (lower, coeffI)
210 losortCoeff = losortAddr[coeffI];
212 rowX[upperAddr[losortCoeff]] -=
213 rowPreconDiag[upperAddr[losortCoeff]]*
214 lower[losortCoeff]*rowX[lowerAddr[losortCoeff]];
217 forAllReverse (upper, coeffI)
219 rowX[lowerAddr[coeffI]] -=
220 rowPreconDiag[lowerAddr[coeffI]]*
221 upper[coeffI]*rowX[upperAddr[coeffI]];
228 void Foam::coupledCholeskyPrecon::preconditionT
230 FieldField<Field, scalar>& x,
231 const FieldField<Field, scalar>& b,
235 // Cholesky precondition all matrices
236 forAll (matrix_, rowI)
238 scalarField& rowX = x[rowI];
239 const scalarField& rowB = b[rowI];
241 const lduMatrix& rowMatrix = matrix_[rowI];
242 const scalarField& rowPreconDiag = preconDiag_[rowI];
246 rowX[i] = rowB[i]*rowPreconDiag[i];
249 if (rowMatrix.symmetric())
251 const unallocLabelList& upperAddr = rowMatrix.lduAddr().upperAddr();
252 const unallocLabelList& lowerAddr = rowMatrix.lduAddr().lowerAddr();
254 // Get off-diagonal matrix coefficients
255 const scalarField& upper = rowMatrix.upper();
257 forAll (upper, coeffI)
259 // For symmetric matrix, there is no change. HJ, 19/Jan/2009
260 rowX[upperAddr[coeffI]] -=
261 rowPreconDiag[upperAddr[coeffI]]*
262 upper[coeffI]*rowX[lowerAddr[coeffI]];
265 forAllReverse (upper, coeffI)
267 // For symmetric matrix, there is no change. HJ, 19/Jan/2009
268 rowX[lowerAddr[coeffI]] -=
269 rowPreconDiag[lowerAddr[coeffI]]*
270 upper[coeffI]*rowX[upperAddr[coeffI]];
273 else if (rowMatrix.asymmetric())
275 const unallocLabelList& upperAddr = rowMatrix.lduAddr().upperAddr();
276 const unallocLabelList& lowerAddr = rowMatrix.lduAddr().lowerAddr();
277 const unallocLabelList& losortAddr =
278 rowMatrix.lduAddr().losortAddr();
280 // Get off-diagonal matrix coefficients
281 const scalarField& upper = rowMatrix.upper();
282 const scalarField& lower = rowMatrix.lower();
286 forAll (lower, coeffI)
288 // Transpose multiplication. HJ, 19/Jan/2009
289 rowX[upperAddr[coeffI]] -=
290 rowPreconDiag[upperAddr[coeffI]]*
291 upper[coeffI]*rowX[lowerAddr[coeffI]];
294 forAllReverse (upper, coeffI)
296 losortCoeff = losortAddr[coeffI];
298 // Transpose multiplication. HJ, 19/Jan/2009
299 rowX[lowerAddr[losortCoeff]] -=
300 rowPreconDiag[lowerAddr[losortCoeff]]*
301 lower[coeffI]*rowX[upperAddr[losortCoeff]];
308 // ************************************************************************* //