Forward compatibility: flex
[foam-extend-3.2.git] / src / foam / matrices / constraint / constraintTools.C
blob1c3985a0797ba5a41f7070be65f3fe7694d7ac1b
1 /*---------------------------------------------------------------------------*\
2   =========                 |
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 -------------------------------------------------------------------------------
8 License
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/>.
24 Description
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 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 namespace Foam
39 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
41 template<class Type>
42 template<template<class> class Matrix>
43 void constraint<Type>::setMatrix
45     const Matrix<Type>& matrix
48     if (matrixCoeffsSet_)
49     {
50         FatalErrorIn
51         (
52             "const scalarField& constraint<Type>::setMatrix"
53         )   << "(const Matrix<Type>& matrix)"
54             << "matrix coefficients already set"
55             << abort(FatalError);
56     }
58     matrixCoeffsSet_ = true;
60     if (matrix.hasDiag())
61     {
62         diagCoeff_ = matrix.diag()[rowID_];
63     }
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())
80     {
81         // get the upper coefficients
83         const scalarField& matrixUpper = matrix.upper();
85         // owner side
86         upperCoeffsOwnerPtr_ = new scalarField(endFaceOwn - startFaceOwn);
88         scalarField& uOwn = *upperCoeffsOwnerPtr_;
90         label faceIndex = startFaceOwn;
92         forAll(uOwn, uOwnI)
93         {
94             uOwn[uOwnI] = matrixUpper[faceIndex];
96             faceIndex++;
97         }
99         // neighbour side
100         upperCoeffsNeighbourPtr_ = new scalarField(endFaceNbr - startFaceNbr);
102         scalarField& uNbr = *upperCoeffsNeighbourPtr_;
104         faceIndex = startFaceNbr;
106         forAll (uNbr, uNbrI)
107         {
108             uNbr[uNbrI] = matrixUpper[losort[faceIndex]];
110             faceIndex++;
111         }
112     }
114     if (matrix.hasLower())
115     {
116         // get the lower coefficients
118         const scalarField& matrixLower = matrix.lower();
120         // owner side
121         lowerCoeffsOwnerPtr_ = new scalarField(endFaceOwn - startFaceOwn);
123         scalarField& lOwn = *lowerCoeffsOwnerPtr_;
125         label faceIndex = startFaceOwn;
127         forAll (lOwn, lOwnI)
128         {
129             lOwn[lOwnI] = matrixLower[faceIndex];
131             faceIndex++;
132         }
134         // neighbour side
135         lowerCoeffsNeighbourPtr_ = new scalarField(endFaceNbr - startFaceNbr);
137         scalarField& lNbr = *lowerCoeffsNeighbourPtr_;
139         faceIndex = startFaceNbr;
141         forAll (lNbr, lNbrI)
142         {
143             lNbr[lNbrI] = matrixLower[losort[faceIndex]];
145             faceIndex++;
146         }
147     }
151 template<class Type>
152 template<template<class> class Matrix>
153 void constraint<Type>::eliminateEquation
155     Matrix<Type>& matrix,
156     const label rowID,
157     const Type& value
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();
181     // My index =  rowID
182     if (matrix.symmetric())
183     {
184         // get the coefficients
185         scalarField* coeffs = NULL;
187         if (matrix.hasUpper())
188         {
189             coeffs = &matrix.upper();
190         }
191         else if (matrix.hasLower())
192         {
193             coeffs = &matrix.lower();
194         }
196         scalarField& matrixCoeffs = *coeffs;
198         // owner side
199         label faceIndex = startFaceOwn;
201         while (faceIndex < endFaceOwn)
202         {
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;
210             faceIndex++;
211         }
213         // neighbour side
214         faceIndex = startFaceNbr;
216         while (faceIndex < endFaceNbr)
217         {
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;
226             faceIndex++;
227         }
228     }
229     else if (matrix.asymmetric())
230     {
231         scalarField& matrixUpper = matrix.upper();
233         scalarField& matrixLower = matrix.lower();
235         // owner side
236         label faceIndex = startFaceOwn;
238         while (faceIndex < endFaceOwn)
239         {
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;
246             faceIndex++;
247         }
249         // neighbour side
250         faceIndex = startFaceNbr;
252         while (faceIndex < endFaceNbr)
253         {
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;
261             faceIndex++;
262         }
263     }
267 template<class Type>
268 template<template<class> class Matrix>
269 void constraint<Type>::eliminateEquation(Matrix<Type>& matrix) const
271     eliminateEquation(matrix, rowID_, value_);
275 template<class Type>
276 template<template<class> class Matrix>
277 void constraint<Type>::eliminateEquation
279     Matrix<Type>& matrix,
280     const direction d,
281     scalarField& sourceCmpt
282 ) const
284     // Record equation as eliminated
285     matrix.eliminatedEqns().insert(rowID_);
287     const Type& fc = fixedComponents();
289     const scalar fcOfD = componentOfValue(fc, d);
291     if (fcOfD > SMALL)
292     {
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();
310         // My index =  rowID_
311         if (matrix.symmetric())
312         {
313             // get the coefficients
314             scalarField* coeffs = NULL;
316             if (matrix.hasUpper())
317             {
318                 coeffs = &matrix.upper();
319             }
320             else if (matrix.hasLower())
321             {
322                 coeffs = &matrix.lower();
323             }
325             scalarField& matrixCoeffs = *coeffs;
327             // owner side
328             label faceIndex = startFaceOwn;
330             while (faceIndex < endFaceOwn)
331             {
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;
340                 faceIndex++;
341             }
343             // neighbour side
344             faceIndex = startFaceNbr;
346             while (faceIndex < endFaceNbr)
347             {
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;
357                 faceIndex++;
358             }
359         }
360         else if (matrix.asymmetric())
361         {
362             scalarField& matrixUpper = matrix.upper();
364             scalarField& matrixLower = matrix.lower();
366             // owner side
367             label faceIndex = startFaceOwn;
369             while (faceIndex < endFaceOwn)
370             {
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;
378                 faceIndex++;
379             }
381             // neighbour side
382             faceIndex = startFaceNbr;
384             while (faceIndex < endFaceNbr)
385             {
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;
394                 faceIndex++;
395             }
396         }
397     }
401 template<class Type>
402 template<template<class> class Matrix>
403 void constraint<Type>::setSource
405     Matrix<Type>& matrix,
406     const label rowID,
407     const Type& value
410     matrix.source()[rowID] = matrix.diag()[rowID]*value;
411     matrix.psi()[rowID] = value;
415 template<class Type>
416 template<template<class> class Matrix>
417 void constraint<Type>::setSource(Matrix<Type>& matrix) const
419     setSource(matrix, rowID_, value_);
423 template<class Type>
424 template<template<class> class Matrix>
425 void constraint<Type>::setSourceDiag
427     Matrix<Type>& matrix,
428     const direction d,
429     scalarField& psiCmpt,
430     scalarField& sourceCmpt
431 ) const
433     const Type& fc = fixedComponents();
435     if (componentOfValue(fc, d) > SMALL)
436     {
437         sourceCmpt[rowID()] = componentOfValue(fc, d)*matrix.diag()[rowID()]
438             *componentOfValue(value(), d);
440         // set the solution to the right value as well
441         psiCmpt[rowID()] =
442             componentOfValue(fc, d)*componentOfValue(value(), d);
443     }
447 template<class Type>
448 template<template<class> class Matrix>
449 void constraint<Type>::reconstructMatrix
451     Matrix<Type>& matrix
452 ) const
454     if (!matrixCoeffsSet_)
455     {
456         FatalErrorIn
457         (
458             "void constraint<Type>::reconstructMatrix("
459             "Matrix<Type>& matrix)"
460         )   << "matrix coefficients not set"
461             << abort(FatalError);
462     }
464     if (matrix.hasDiag())
465     {
466         matrix.diag()[rowID_] = diagCoeff_;
467     }
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())
478     {
479         // get the upper coefficients
481         scalarField& matrixUpper = matrix.upper();
483         // owner side
484         const scalarField& uOwn = upperCoeffsOwner();
486         label faceIndex = startFaceOwn;
488         forAll(uOwn, uOwnI)
489         {
490             matrixUpper[faceIndex] = uOwn[uOwnI];
492             faceIndex++;
493         }
495         // neighbour side
496         const scalarField& uNbr = upperCoeffsNeighbour();
498         faceIndex = startFaceNbr;
500         forAll (uNbr, uNbrI)
501         {
502             matrixUpper[losort[faceIndex]] = uNbr[uNbrI];
504             faceIndex++;
505         }
506     }
508     if (matrix.hasLower())
509     {
510         // get the lower coefficients
512         scalarField& matrixLower = matrix.lower();
514         // owner side
515         const scalarField& lOwn = lowerCoeffsOwner();
517         label faceIndex = startFaceOwn;
519         forAll (lOwn, lOwnI)
520         {
521             matrixLower[faceIndex] = lOwn[lOwnI];
523             faceIndex++;
524         }
526         // neighbour side
527         const scalarField& lNbr = lowerCoeffsNeighbour();
529         faceIndex = startFaceNbr;
531         forAll (lNbr, lNbrI)
532         {
533             matrixLower[losort[faceIndex]] = lNbr[lNbrI];
535             faceIndex++;
536         }
537     }
541 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
543 } // End namespace Foam
545 // ************************************************************************* //