1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
26 A storage mechanism which allows setting of the fixed value and
27 consequently recovering the equation for a single row of the matrix as
28 well as the source. The equation is taken out of the matrix using a
29 variant of compact matrix storage mechanism.
31 \*---------------------------------------------------------------------------*/
33 #include "constraint.H"
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 template<template<class> class Matrix>
44 void constraint<Type>::setMatrix
46 const Matrix<Type>& matrix
53 "const scalarField& constraint<Type>::setMatrix"
54 ) << "(const Matrix<Type>& matrix)"
55 << "matrix coefficients already set"
59 matrixCoeffsSet_ = true;
63 diagCoeff_ = matrix.diag()[rowID_];
66 source_ = matrix.source()[rowID_];
68 const label startFaceOwn =
69 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_];
70 const label endFaceOwn =
71 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_ + 1];
73 const label startFaceNbr =
74 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_];
75 const label endFaceNbr =
76 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_ + 1];
78 const unallocLabelList& losort = matrix.psi().mesh().lduAddr().losortAddr();
80 if (matrix.hasUpper())
82 // get the upper coefficients
84 const scalarField& matrixUpper = matrix.upper();
87 upperCoeffsOwnerPtr_ = new scalarField(endFaceOwn - startFaceOwn);
89 scalarField& uOwn = *upperCoeffsOwnerPtr_;
91 label faceIndex = startFaceOwn;
95 uOwn[uOwnI] = matrixUpper[faceIndex];
101 upperCoeffsNeighbourPtr_ = new scalarField(endFaceNbr - startFaceNbr);
103 scalarField& uNbr = *upperCoeffsNeighbourPtr_;
105 faceIndex = startFaceNbr;
109 uNbr[uNbrI] = matrixUpper[losort[faceIndex]];
115 if (matrix.hasLower())
117 // get the lower coefficients
119 const scalarField& matrixLower = matrix.lower();
122 lowerCoeffsOwnerPtr_ = new scalarField(endFaceOwn - startFaceOwn);
124 scalarField& lOwn = *lowerCoeffsOwnerPtr_;
126 label faceIndex = startFaceOwn;
130 lOwn[lOwnI] = matrixLower[faceIndex];
136 lowerCoeffsNeighbourPtr_ = new scalarField(endFaceNbr - startFaceNbr);
138 scalarField& lNbr = *lowerCoeffsNeighbourPtr_;
140 faceIndex = startFaceNbr;
144 lNbr[lNbrI] = matrixLower[losort[faceIndex]];
153 template<template<class> class Matrix>
154 void constraint<Type>::eliminateEquation
156 Matrix<Type>& matrix,
161 Field<Type>& source = matrix.source();
163 const label startFaceOwn =
164 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID];
165 const label endFaceOwn =
166 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID + 1];
168 const label startFaceNbr =
169 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID];
170 const label endFaceNbr =
171 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID + 1];
173 const unallocLabelList& owner = matrix.psi().mesh().lduAddr().lowerAddr();
174 const unallocLabelList& neighbour =
175 matrix.psi().mesh().lduAddr().upperAddr();
176 const unallocLabelList& losort = matrix.psi().mesh().lduAddr().losortAddr();
179 if (matrix.symmetric())
181 // get the coefficients
182 scalarField* coeffs = NULL;
184 if (matrix.hasUpper())
186 coeffs = &matrix.upper();
188 else if (matrix.hasLower())
190 coeffs = &matrix.lower();
193 scalarField& matrixCoeffs = *coeffs;
196 label faceIndex = startFaceOwn;
198 while (faceIndex < endFaceOwn)
200 // add contribution to source of the neighbour (I am the owner)
201 source[neighbour[faceIndex]] -= matrixCoeffs[faceIndex]*value;
203 // I am the owner = owner[faceIndex]
204 // set off-diagonal coefficient to zero
205 matrixCoeffs[faceIndex] = 0.0;
211 faceIndex = startFaceNbr;
213 while (faceIndex < endFaceNbr)
215 // add contribution to source of owner (I am the neighbour)
216 source[owner[losort[faceIndex]]] -=
217 matrixCoeffs[losort[faceIndex]]*value;
219 // I am the neighbour = neighbour[losort[faceIndex]]
220 // set off-diagonal coefficient to zero
221 matrixCoeffs[losort[faceIndex]] = 0.0;
226 else if (matrix.asymmetric())
228 scalarField& matrixUpper = matrix.upper();
230 scalarField& matrixLower = matrix.lower();
233 label faceIndex = startFaceOwn;
235 while (faceIndex < endFaceOwn)
237 // add contribution to source of the neighbour (I am the owner)
238 source[neighbour[faceIndex]] -= matrixLower[faceIndex]*value;
240 // set off-diagonal coefficient to zero
241 matrixLower[faceIndex] = 0.0;
247 faceIndex = startFaceNbr;
249 while (faceIndex < endFaceNbr)
251 // add contribution to source of owner (I am the neighbour)
252 source[owner[losort[faceIndex]]] -=
253 matrixUpper[losort[faceIndex]]*value;
255 // set off-diagonal coefficient to zero
256 matrixUpper[losort[faceIndex]] = 0.0;
265 template<template<class> class Matrix>
266 void constraint<Type>::eliminateEquation(Matrix<Type>& matrix) const
268 eliminateEquation(matrix, rowID_, value_);
273 template<template<class> class Matrix>
274 void constraint<Type>::eliminateEquation
276 Matrix<Type>& matrix,
278 scalarField& sourceCmpt
281 const Type& fc = fixedComponents();
283 const scalar fcOfD = componentOfValue(fc, d);
287 const label startFaceOwn =
288 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_];
289 const label endFaceOwn =
290 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_ + 1];
292 const label startFaceNbr =
293 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_];
294 const label endFaceNbr =
295 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_ + 1];
297 const unallocLabelList& owner =
298 matrix.psi().mesh().lduAddr().lowerAddr();
299 const unallocLabelList& neighbour =
300 matrix.psi().mesh().lduAddr().upperAddr();
301 const unallocLabelList& losort =
302 matrix.psi().mesh().lduAddr().losortAddr();
305 if (matrix.symmetric())
307 // get the coefficients
308 scalarField* coeffs = NULL;
310 if (matrix.hasUpper())
312 coeffs = &matrix.upper();
314 else if (matrix.hasLower())
316 coeffs = &matrix.lower();
319 scalarField& matrixCoeffs = *coeffs;
322 label faceIndex = startFaceOwn;
324 while (faceIndex < endFaceOwn)
326 // add contribution to source of the neighbour (I am the owner)
327 sourceCmpt[neighbour[faceIndex]] -=
328 fcOfD*matrixCoeffs[faceIndex]*componentOfValue(value(), d);
330 // I am the owner = owner[faceIndex]
331 // set off-diagonal coefficient to zero
332 matrixCoeffs[faceIndex] *= 1.0 - fcOfD;
338 faceIndex = startFaceNbr;
340 while (faceIndex < endFaceNbr)
342 // add contribution to source of owner (I am the neighbour)
343 sourceCmpt[owner[losort[faceIndex]]] -=
344 fcOfD*matrixCoeffs[losort[faceIndex]]
345 *componentOfValue(value(), d);
347 // I am the neighbour = neighbour[losort[faceIndex]]
348 // set off-diagonal coefficient to zero
349 matrixCoeffs[losort[faceIndex]] *= 1.0 - fcOfD;
354 else if (matrix.asymmetric())
356 scalarField& matrixUpper = matrix.upper();
358 scalarField& matrixLower = matrix.lower();
361 label faceIndex = startFaceOwn;
363 while (faceIndex < endFaceOwn)
365 // add contribution to source of the neighbour (I am the owner)
366 sourceCmpt[neighbour[faceIndex]] -=
367 fcOfD*matrixLower[faceIndex]*componentOfValue(value(), d);
369 // set off-diagonal coefficient to zero
370 matrixLower[faceIndex] *= 1.0 - fcOfD;
376 faceIndex = startFaceNbr;
378 while (faceIndex < endFaceNbr)
380 // add contribution to source of owner (I am the neighbour)
381 sourceCmpt[owner[losort[faceIndex]]] -=
382 fcOfD*matrixUpper[losort[faceIndex]]
383 *componentOfValue(value(), d);
385 // set off-diagonal coefficient to zero
386 matrixUpper[losort[faceIndex]] *= 1.0 - fcOfD;
396 template<template<class> class Matrix>
397 void constraint<Type>::setSource
399 Matrix<Type>& matrix,
404 matrix.source()[rowID] = matrix.diag()[rowID]*value;
405 matrix.psi()[rowID] = value;
410 template<template<class> class Matrix>
411 void constraint<Type>::setSource(Matrix<Type>& matrix) const
413 setSource(matrix, rowID_, value_);
418 template<template<class> class Matrix>
419 void constraint<Type>::setSourceDiag
421 Matrix<Type>& matrix,
423 scalarField& psiCmpt,
424 scalarField& sourceCmpt
427 const Type& fc = fixedComponents();
429 if (componentOfValue(fc, d) > SMALL)
431 sourceCmpt[rowID()] = componentOfValue(fc, d)*matrix.diag()[rowID()]
432 *componentOfValue(value(), d);
434 // set the solution to the right value as well
436 componentOfValue(fc, d)*componentOfValue(value(), d);
442 template<template<class> class Matrix>
443 void constraint<Type>::reconstructMatrix
448 if (!matrixCoeffsSet_)
452 "void constraint<Type>::reconstructMatrix("
453 "Matrix<Type>& matrix)"
454 ) << "matrix coefficients not set"
455 << abort(FatalError);
458 if (matrix.hasDiag())
460 matrix.diag()[rowID_] = diagCoeff_;
463 const label startFaceOwn =
464 matrix.psi().mesh().lduAddr().ownerStartAddr()[rowID_];
466 const label startFaceNbr =
467 matrix.psi().mesh().lduAddr().losortStartAddr()[rowID_];
469 const unallocLabelList& losort = matrix.psi().mesh().lduAddr().losortAddr();
471 if (matrix.hasUpper())
473 // get the upper coefficients
475 scalarField& matrixUpper = matrix.upper();
478 const scalarField& uOwn = upperCoeffsOwner();
480 label faceIndex = startFaceOwn;
484 matrixUpper[faceIndex] = uOwn[uOwnI];
490 const scalarField& uNbr = upperCoeffsNeighbour();
492 faceIndex = startFaceNbr;
496 matrixUpper[losort[faceIndex]] = uNbr[uNbrI];
502 if (matrix.hasLower())
504 // get the lower coefficients
506 scalarField& matrixLower = matrix.lower();
509 const scalarField& lOwn = lowerCoeffsOwner();
511 label faceIndex = startFaceOwn;
515 matrixLower[faceIndex] = lOwn[lOwnI];
521 const scalarField& lNbr = lowerCoeffsNeighbour();
523 faceIndex = startFaceNbr;
527 matrixLower[losort[faceIndex]] = lNbr[lNbrI];
535 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
537 } // End namespace Foam
539 // ************************************************************************* //