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
25 \*---------------------------------------------------------------------------*/
27 #include "LUscalarMatrix.H"
28 #include "lduMatrix.H"
29 #include "procLduMatrix.H"
30 #include "procLduInterface.H"
32 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34 Foam::LUscalarMatrix::LUscalarMatrix(const scalarSquareMatrix& matrix)
36 scalarSquareMatrix(matrix),
39 LUDecompose(*this, pivotIndices_);
43 Foam::LUscalarMatrix::LUscalarMatrix
45 const lduMatrix& ldum,
46 const FieldField<Field, scalar>& interfaceCoeffs,
47 const lduInterfaceFieldPtrsList& interfaces
50 if (Pstream::parRun())
52 PtrList<procLduMatrix> lduMatrices(Pstream::nProcs());
67 if (Pstream::master())
71 int slave=Pstream::firstSlave();
72 slave<=Pstream::lastSlave();
79 new procLduMatrix(IPstream(Pstream::scheduled, slave)())
85 OPstream toMaster(Pstream::scheduled, Pstream::masterNo());
96 if (Pstream::master())
99 forAll(lduMatrices, i)
101 nCells += lduMatrices[i].size();
104 scalarSquareMatrix m(nCells, 0.0);
106 convert(lduMatrices);
111 label nCells = ldum.lduAddr().size();
112 scalarSquareMatrix m(nCells, 0.0);
114 convert(ldum, interfaceCoeffs, interfaces);
117 if (Pstream::master())
119 pivotIndices_.setSize(n());
120 LUDecompose(*this, pivotIndices_);
125 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
127 void Foam::LUscalarMatrix::convert
129 const lduMatrix& ldum,
130 const FieldField<Field, scalar>& interfaceCoeffs,
131 const lduInterfaceFieldPtrsList& interfaces
134 const label* __restrict__ uPtr = ldum.lduAddr().upperAddr().begin();
135 const label* __restrict__ lPtr = ldum.lduAddr().lowerAddr().begin();
137 const scalar* __restrict__ diagPtr = ldum.diag().begin();
138 const scalar* __restrict__ upperPtr = ldum.upper().begin();
139 const scalar* __restrict__ lowerPtr = ldum.lower().begin();
141 register const label nCells = ldum.diag().size();
142 register const label nFaces = ldum.upper().size();
144 for (register label cell=0; cell<nCells; cell++)
146 operator[](cell)[cell] = diagPtr[cell];
149 for (register label face=0; face<nFaces; face++)
151 label uCell = uPtr[face];
152 label lCell = lPtr[face];
154 operator[](uCell)[lCell] = lowerPtr[face];
155 operator[](lCell)[uCell] = upperPtr[face];
158 forAll(interfaces, inti)
160 if (interfaces.set(inti))
162 const lduInterface& interface = interfaces[inti].interface();
164 const label* __restrict__ ulPtr = interface.faceCells().begin();
165 const scalar* __restrict__ upperLowerPtr =
166 interfaceCoeffs[inti].begin();
168 register label inFaces = interface.faceCells().size()/2;
170 for (register label face=0; face<inFaces; face++)
172 label uCell = ulPtr[face];
173 label lCell = ulPtr[face + inFaces];
175 operator[](uCell)[lCell] -= upperLowerPtr[face + inFaces];
176 operator[](lCell)[uCell] -= upperLowerPtr[face];
181 //printDiagonalDominance();
185 void Foam::LUscalarMatrix::convert
187 const PtrList<procLduMatrix>& lduMatrices
190 procOffsets_.setSize(lduMatrices.size() + 1);
193 forAll(lduMatrices, ldumi)
195 procOffsets_[ldumi+1] = procOffsets_[ldumi] + lduMatrices[ldumi].size();
198 forAll(lduMatrices, ldumi)
200 const procLduMatrix& lduMatrixi = lduMatrices[ldumi];
201 label offset = procOffsets_[ldumi];
203 const label* __restrict__ uPtr = lduMatrixi.upperAddr_.begin();
204 const label* __restrict__ lPtr = lduMatrixi.lowerAddr_.begin();
206 const scalar* __restrict__ diagPtr = lduMatrixi.diag_.begin();
207 const scalar* __restrict__ upperPtr = lduMatrixi.upper_.begin();
208 const scalar* __restrict__ lowerPtr = lduMatrixi.lower_.begin();
210 register const label nCells = lduMatrixi.size();
211 register const label nFaces = lduMatrixi.upper_.size();
213 for (register label cell=0; cell<nCells; cell++)
215 label globalCell = cell + offset;
216 operator[](globalCell)[globalCell] = diagPtr[cell];
219 for (register label face=0; face<nFaces; face++)
221 label uCell = uPtr[face] + offset;
222 label lCell = lPtr[face] + offset;
224 operator[](uCell)[lCell] = lowerPtr[face];
225 operator[](lCell)[uCell] = upperPtr[face];
228 const PtrList<procLduInterface>& interfaces =
229 lduMatrixi.interfaces_;
231 forAll(interfaces, inti)
233 const procLduInterface& interface = interfaces[inti];
235 if (interface.myProcNo_ == interface.neighbProcNo_)
237 const label* __restrict__ ulPtr = interface.faceCells_.begin();
239 const scalar* __restrict__ upperLowerPtr =
240 interface.coeffs_.begin();
242 register label inFaces = interface.faceCells_.size()/2;
244 for (register label face=0; face<inFaces; face++)
246 label uCell = ulPtr[face] + offset;
247 label lCell = ulPtr[face + inFaces] + offset;
249 operator[](uCell)[lCell] -= upperLowerPtr[face + inFaces];
250 operator[](lCell)[uCell] -= upperLowerPtr[face];
253 else if (interface.myProcNo_ < interface.neighbProcNo_)
255 const PtrList<procLduInterface>& neiInterfaces =
256 lduMatrices[interface.neighbProcNo_].interfaces_;
258 label neiInterfacei = -1;
260 forAll(neiInterfaces, ninti)
264 neiInterfaces[ninti].neighbProcNo_
265 == interface.myProcNo_
268 neiInterfacei = ninti;
273 if (neiInterfacei == -1)
275 FatalErrorIn("LUscalarMatrix::convert") << exit(FatalError);
278 const procLduInterface& neiInterface =
279 neiInterfaces[neiInterfacei];
281 const label* __restrict__ uPtr = interface.faceCells_.begin();
282 const label* __restrict__ lPtr = neiInterface.faceCells_.begin();
284 const scalar* __restrict__ upperPtr = interface.coeffs_.begin();
285 const scalar* __restrict__ lowerPtr = neiInterface.coeffs_.begin();
287 register label inFaces = interface.faceCells_.size();
288 label neiOffset = procOffsets_[interface.neighbProcNo_];
290 for (register label face=0; face<inFaces; face++)
292 label uCell = uPtr[face] + offset;
293 label lCell = lPtr[face] + neiOffset;
295 operator[](uCell)[lCell] -= lowerPtr[face];
296 operator[](lCell)[uCell] -= upperPtr[face];
302 //printDiagonalDominance();
306 void Foam::LUscalarMatrix::printDiagonalDominance() const
308 for (label i=0; i<n(); i++)
311 for (label j=0; j<n(); j++)
315 sum += operator[](i)[j];
318 Info<< mag(sum)/mag(operator[](i)[i]) << endl;
323 // ************************************************************************* //