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/>.
25 A storage mechanism which allows setting of the fixed value and
26 consequently recovering the equation for a single row of the matrix as
27 well as the source. The equation is taken out of the matrix using a
28 variant of compact matrix storage mechanism.
30 \*---------------------------------------------------------------------------*/
32 #include "constraint.H"
34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
42 template<template<class> class Matrix>
43 void constraint<Type>::setMatrix
45 const Matrix<Type>& matrix
52 "const scalarField& constraint<Type>::setMatrix"
53 ) << "(const Matrix<Type>& matrix)"
54 << "matrix coefficients already set"
58 matrixCoeffsSet_ = true;
62 diagCoeff_ = matrix.diag()[rowID_];
65 source_ = matrix.source()[rowID_];
67 const label startFaceOwn =
68 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_];
69 const label endFaceOwn =
70 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_ + 1];
72 const label startFaceNbr =
73 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_];
74 const label endFaceNbr =
75 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_ + 1];
77 const unallocLabelList& losort = matrix.psi().mesh().lduAddr().losortAddr();
79 if (matrix.hasUpper())
81 // get the upper coefficients
83 const scalarField& matrixUpper = matrix.upper();
86 upperCoeffsOwnerPtr_ = new scalarField(endFaceOwn - startFaceOwn);
88 scalarField& uOwn = *upperCoeffsOwnerPtr_;
90 label faceIndex = startFaceOwn;
94 uOwn[uOwnI] = matrixUpper[faceIndex];
100 upperCoeffsNeighbourPtr_ = new scalarField(endFaceNbr - startFaceNbr);
102 scalarField& uNbr = *upperCoeffsNeighbourPtr_;
104 faceIndex = startFaceNbr;
108 uNbr[uNbrI] = matrixUpper[losort[faceIndex]];
114 if (matrix.hasLower())
116 // get the lower coefficients
118 const scalarField& matrixLower = matrix.lower();
121 lowerCoeffsOwnerPtr_ = new scalarField(endFaceOwn - startFaceOwn);
123 scalarField& lOwn = *lowerCoeffsOwnerPtr_;
125 label faceIndex = startFaceOwn;
129 lOwn[lOwnI] = matrixLower[faceIndex];
135 lowerCoeffsNeighbourPtr_ = new scalarField(endFaceNbr - startFaceNbr);
137 scalarField& lNbr = *lowerCoeffsNeighbourPtr_;
139 faceIndex = startFaceNbr;
143 lNbr[lNbrI] = matrixLower[losort[faceIndex]];
152 template<template<class> class Matrix>
153 void constraint<Type>::eliminateEquation
155 Matrix<Type>& matrix,
160 // Record equation as eliminated
161 matrix.eliminatedEqns().insert(rowID);
163 Field<Type>& source = matrix.source();
165 const label startFaceOwn =
166 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID];
167 const label endFaceOwn =
168 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID + 1];
170 const label startFaceNbr =
171 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID];
172 const label endFaceNbr =
173 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID + 1];
175 const unallocLabelList& owner = matrix.psi().mesh().lduAddr().lowerAddr();
176 const unallocLabelList& neighbour =
177 matrix.psi().mesh().lduAddr().upperAddr();
178 const unallocLabelList& losort =
179 matrix.psi().mesh().lduAddr().losortAddr();
182 if (matrix.symmetric())
184 // get the coefficients
185 scalarField* coeffs = NULL;
187 if (matrix.hasUpper())
189 coeffs = &matrix.upper();
191 else if (matrix.hasLower())
193 coeffs = &matrix.lower();
196 scalarField& matrixCoeffs = *coeffs;
199 label faceIndex = startFaceOwn;
201 while (faceIndex < endFaceOwn)
203 // add contribution to source of the neighbour (I am the owner)
204 source[neighbour[faceIndex]] -= matrixCoeffs[faceIndex]*value;
206 // I am the owner = owner[faceIndex]
207 // set off-diagonal coefficient to zero
208 matrixCoeffs[faceIndex] = 0.0;
214 faceIndex = startFaceNbr;
216 while (faceIndex < endFaceNbr)
218 // add contribution to source of owner (I am the neighbour)
219 source[owner[losort[faceIndex]]] -=
220 matrixCoeffs[losort[faceIndex]]*value;
222 // I am the neighbour = neighbour[losort[faceIndex]]
223 // set off-diagonal coefficient to zero
224 matrixCoeffs[losort[faceIndex]] = 0.0;
229 else if (matrix.asymmetric())
231 scalarField& matrixUpper = matrix.upper();
233 scalarField& matrixLower = matrix.lower();
236 label faceIndex = startFaceOwn;
238 while (faceIndex < endFaceOwn)
240 // add contribution to source of the neighbour (I am the owner)
241 source[neighbour[faceIndex]] -= matrixLower[faceIndex]*value;
243 // set off-diagonal coefficient to zero
244 matrixLower[faceIndex] = 0.0;
250 faceIndex = startFaceNbr;
252 while (faceIndex < endFaceNbr)
254 // add contribution to source of owner (I am the neighbour)
255 source[owner[losort[faceIndex]]] -=
256 matrixUpper[losort[faceIndex]]*value;
258 // set off-diagonal coefficient to zero
259 matrixUpper[losort[faceIndex]] = 0.0;
268 template<template<class> class Matrix>
269 void constraint<Type>::eliminateEquation(Matrix<Type>& matrix) const
271 eliminateEquation(matrix, rowID_, value_);
276 template<template<class> class Matrix>
277 void constraint<Type>::eliminateEquation
279 Matrix<Type>& matrix,
281 scalarField& sourceCmpt
284 // Record equation as eliminated
285 matrix.eliminatedEqns().insert(rowID_);
287 const Type& fc = fixedComponents();
289 const scalar fcOfD = componentOfValue(fc, d);
293 const label startFaceOwn =
294 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_];
295 const label endFaceOwn =
296 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_ + 1];
298 const label startFaceNbr =
299 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_];
300 const label endFaceNbr =
301 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_ + 1];
303 const unallocLabelList& owner =
304 matrix.psi().mesh().lduAddr().lowerAddr();
305 const unallocLabelList& neighbour =
306 matrix.psi().mesh().lduAddr().upperAddr();
307 const unallocLabelList& losort =
308 matrix.psi().mesh().lduAddr().losortAddr();
311 if (matrix.symmetric())
313 // get the coefficients
314 scalarField* coeffs = NULL;
316 if (matrix.hasUpper())
318 coeffs = &matrix.upper();
320 else if (matrix.hasLower())
322 coeffs = &matrix.lower();
325 scalarField& matrixCoeffs = *coeffs;
328 label faceIndex = startFaceOwn;
330 while (faceIndex < endFaceOwn)
332 // add contribution to source of the neighbour (I am the owner)
333 sourceCmpt[neighbour[faceIndex]] -=
334 fcOfD*matrixCoeffs[faceIndex]*componentOfValue(value(), d);
336 // I am the owner = owner[faceIndex]
337 // set off-diagonal coefficient to zero
338 matrixCoeffs[faceIndex] *= 1.0 - fcOfD;
344 faceIndex = startFaceNbr;
346 while (faceIndex < endFaceNbr)
348 // add contribution to source of owner (I am the neighbour)
349 sourceCmpt[owner[losort[faceIndex]]] -=
350 fcOfD*matrixCoeffs[losort[faceIndex]]
351 *componentOfValue(value(), d);
353 // I am the neighbour = neighbour[losort[faceIndex]]
354 // set off-diagonal coefficient to zero
355 matrixCoeffs[losort[faceIndex]] *= 1.0 - fcOfD;
360 else if (matrix.asymmetric())
362 scalarField& matrixUpper = matrix.upper();
364 scalarField& matrixLower = matrix.lower();
367 label faceIndex = startFaceOwn;
369 while (faceIndex < endFaceOwn)
371 // add contribution to source of the neighbour (I am the owner)
372 sourceCmpt[neighbour[faceIndex]] -=
373 fcOfD*matrixLower[faceIndex]*componentOfValue(value(), d);
375 // set off-diagonal coefficient to zero
376 matrixLower[faceIndex] *= 1.0 - fcOfD;
382 faceIndex = startFaceNbr;
384 while (faceIndex < endFaceNbr)
386 // add contribution to source of owner (I am the neighbour)
387 sourceCmpt[owner[losort[faceIndex]]] -=
388 fcOfD*matrixUpper[losort[faceIndex]]
389 *componentOfValue(value(), d);
391 // set off-diagonal coefficient to zero
392 matrixUpper[losort[faceIndex]] *= 1.0 - fcOfD;
402 template<template<class> class Matrix>
403 void constraint<Type>::setSource
405 Matrix<Type>& matrix,
410 matrix.source()[rowID] = matrix.diag()[rowID]*value;
411 matrix.psi()[rowID] = value;
416 template<template<class> class Matrix>
417 void constraint<Type>::setSource(Matrix<Type>& matrix) const
419 setSource(matrix, rowID_, value_);
424 template<template<class> class Matrix>
425 void constraint<Type>::setSourceDiag
427 Matrix<Type>& matrix,
429 scalarField& psiCmpt,
430 scalarField& sourceCmpt
433 const Type& fc = fixedComponents();
435 if (componentOfValue(fc, d) > SMALL)
437 sourceCmpt[rowID()] = componentOfValue(fc, d)*matrix.diag()[rowID()]
438 *componentOfValue(value(), d);
440 // set the solution to the right value as well
442 componentOfValue(fc, d)*componentOfValue(value(), d);
448 template<template<class> class Matrix>
449 void constraint<Type>::reconstructMatrix
454 if (!matrixCoeffsSet_)
458 "void constraint<Type>::reconstructMatrix("
459 "Matrix<Type>& matrix)"
460 ) << "matrix coefficients not set"
461 << abort(FatalError);
464 if (matrix.hasDiag())
466 matrix.diag()[rowID_] = diagCoeff_;
469 const label startFaceOwn =
470 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_];
472 const label startFaceNbr =
473 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_];
475 const unallocLabelList& losort = matrix.psi().mesh().lduAddr().losortAddr();
477 if (matrix.hasUpper())
479 // get the upper coefficients
481 scalarField& matrixUpper = matrix.upper();
484 const scalarField& uOwn = upperCoeffsOwner();
486 label faceIndex = startFaceOwn;
490 matrixUpper[faceIndex] = uOwn[uOwnI];
496 const scalarField& uNbr = upperCoeffsNeighbour();
498 faceIndex = startFaceNbr;
502 matrixUpper[losort[faceIndex]] = uNbr[uNbrI];
508 if (matrix.hasLower())
510 // get the lower coefficients
512 scalarField& matrixLower = matrix.lower();
515 const scalarField& lOwn = lowerCoeffsOwner();
517 label faceIndex = startFaceOwn;
521 matrixLower[faceIndex] = lOwn[lOwnI];
527 const scalarField& lNbr = lowerCoeffsNeighbour();
529 faceIndex = startFaceNbr;
533 matrixLower[losort[faceIndex]] = lNbr[lNbrI];
541 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
543 } // End namespace Foam
545 // ************************************************************************* //