1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-6 H. Jasak All rights reserved
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 Vector-matrix multiplication operations for a block matrix
28 \*---------------------------------------------------------------------------*/
30 #include "BlockLduMatrix.H"
32 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 void Foam::BlockLduMatrix<Type>::Amul
41 // Initialise the update of coupled interfaces
42 initInterfaces(Ax, x);
46 // Update coupled interfaces
47 updateInterfaces(coupleUpper_, Ax, x);
52 void Foam::BlockLduMatrix<Type>::AmulCore
58 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
59 typedef typename TypeCoeffField::linearTypeField linearTypeField;
60 typedef typename TypeCoeffField::squareTypeField squareTypeField;
62 const unallocLabelList& u = lduAddr().upperAddr();
63 const unallocLabelList& l = lduAddr().lowerAddr();
65 const TypeCoeffField& Diag = this->diag();
66 const TypeCoeffField& Upper = this->upper();
68 // Diagonal multiplication, no indirection
69 multiply(Ax, Diag, x);
71 // Create multiplication function object
72 typename BlockCoeff<Type>::multiply mult;
74 // Lower multiplication
78 if (Upper.activeType() == blockCoeffBase::SCALAR)
80 const scalarTypeField& activeUpper = Upper.asScalar();
82 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
84 Ax[u[coeffI]] += mult(activeUpper[coeffI], x[l[coeffI]]);
87 else if (Upper.activeType() == blockCoeffBase::LINEAR)
89 const linearTypeField& activeUpper = Upper.asLinear();
91 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
93 Ax[u[coeffI]] += mult(activeUpper[coeffI], x[l[coeffI]]);
96 else if (Upper.activeType() == blockCoeffBase::SQUARE)
98 const squareTypeField& activeUpper = Upper.asSquare();
100 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
102 // Use transpose upper coefficient
104 mult(activeUpper[coeffI].T(), x[l[coeffI]]);
108 else // Asymmetric matrix
110 const TypeCoeffField& Lower = this->lower();
112 if (Lower.activeType() == blockCoeffBase::SCALAR)
114 const scalarTypeField& activeLower = Lower.asScalar();
116 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
118 Ax[u[coeffI]] += mult(activeLower[coeffI], x[l[coeffI]]);
121 else if (Lower.activeType() == blockCoeffBase::LINEAR)
123 const linearTypeField& activeLower = Lower.asLinear();
125 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
127 Ax[u[coeffI]] += mult(activeLower[coeffI], x[l[coeffI]]);
130 else if (Lower.activeType() == blockCoeffBase::SQUARE)
132 const squareTypeField& activeLower = Lower.asSquare();
134 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
136 Ax[u[coeffI]] += mult(activeLower[coeffI], x[l[coeffI]]);
142 // Upper multiplication
144 if (Upper.activeType() == blockCoeffBase::SCALAR)
146 const scalarTypeField& activeUpper = Upper.asScalar();
148 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
150 Ax[l[coeffI]] += mult(activeUpper[coeffI], x[u[coeffI]]);
153 else if (Upper.activeType() == blockCoeffBase::LINEAR)
155 const linearTypeField& activeUpper = Upper.asLinear();
157 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
159 Ax[l[coeffI]] += mult(activeUpper[coeffI], x[u[coeffI]]);
162 else if (Upper.activeType() == blockCoeffBase::SQUARE)
164 const squareTypeField& activeUpper = Upper.asSquare();
166 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
168 Ax[l[coeffI]] += mult(activeUpper[coeffI], x[u[coeffI]]);
175 void Foam::BlockLduMatrix<Type>::Tmul
181 // Initialise the update of coupled interfaces
182 initInterfaces(Ax, x);
186 // Update coupled interfaces
187 updateInterfaces(coupleLower_, Ax, x);
192 void Foam::BlockLduMatrix<Type>::TmulCore
198 typedef typename TypeCoeffField::scalarTypeField scalarTypeField;
199 typedef typename TypeCoeffField::linearTypeField linearTypeField;
200 typedef typename TypeCoeffField::squareTypeField squareTypeField;
202 const unallocLabelList& u = lduAddr().upperAddr();
203 const unallocLabelList& l = lduAddr().lowerAddr();
205 const TypeCoeffField& Diag = this->diag();
206 const TypeCoeffField& Upper = this->upper();
208 // Diagonal multiplication, no indirection
209 multiply(Tx, Diag, x);
211 // Create multiplication function object
212 typename BlockCoeff<Type>::multiply mult;
214 // Upper multiplication
216 if (Upper.activeType() == blockCoeffBase::SCALAR)
218 const scalarTypeField& activeUpper = Upper.asScalar();
220 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
222 Tx[u[coeffI]] += mult(activeUpper[coeffI], x[l[coeffI]]);
225 else if (Upper.activeType() == blockCoeffBase::LINEAR)
227 const linearTypeField& activeUpper = Upper.asLinear();
229 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
231 Tx[u[coeffI]] += mult(activeUpper[coeffI], x[l[coeffI]]);
234 else if (Upper.activeType() == blockCoeffBase::SQUARE)
236 const squareTypeField& activeUpper = Upper.asSquare();
238 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
240 Tx[u[coeffI]] += mult(activeUpper[coeffI], x[l[coeffI]]);
244 // Lower multiplication
248 if (Upper.activeType() == blockCoeffBase::SCALAR)
250 const scalarTypeField& activeUpper = Upper.asScalar();
252 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
254 Tx[l[coeffI]] += mult(activeUpper[coeffI], x[u[coeffI]]);
257 else if (Upper.activeType() == blockCoeffBase::LINEAR)
259 const linearTypeField& activeUpper = Upper.asLinear();
261 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
263 Tx[l[coeffI]] += mult(activeUpper[coeffI], x[u[coeffI]]);
266 else if (Upper.activeType() == blockCoeffBase::SQUARE)
268 const squareTypeField& activeUpper = Upper.asSquare();
270 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
272 // Use transpose upper coefficient
274 mult(activeUpper[coeffI].T(), x[u[coeffI]]);
278 else // Asymmetric matrix
280 const TypeCoeffField& Lower = this->lower();
282 if (Lower.activeType() == blockCoeffBase::SCALAR)
284 const scalarTypeField& activeLower = Lower.asScalar();
286 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
288 Tx[l[coeffI]] += mult(activeLower[coeffI], x[u[coeffI]]);
291 else if (Lower.activeType() == blockCoeffBase::LINEAR)
293 const linearTypeField& activeLower = Lower.asLinear();
295 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
297 Tx[l[coeffI]] += mult(activeLower[coeffI], x[u[coeffI]]);
300 else if (Lower.activeType() == blockCoeffBase::SQUARE)
302 const squareTypeField& activeLower = Lower.asSquare();
304 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
306 Tx[l[coeffI]] += mult(activeLower[coeffI], x[u[coeffI]]);
314 void Foam::BlockLduMatrix<Type>::segregateB
320 typedef typename TypeCoeffField::linearType linearType;
321 typedef typename TypeCoeffField::squareType squareType;
323 typedef typename TypeCoeffField::linearTypeField linearTypeField;
324 typedef typename TypeCoeffField::squareTypeField squareTypeField;
326 const unallocLabelList& u = lduAddr().upperAddr();
327 const unallocLabelList& l = lduAddr().lowerAddr();
329 // Diagonal multiplication
332 if (diag().activeType() == blockCoeffBase::SQUARE)
334 const squareTypeField& activeDiag = this->diag().asSquare();
335 linearTypeField lf(activeDiag.size());
336 squareTypeField sf(activeDiag.size());
338 // Expand and contract
339 contractLinear(lf, activeDiag);
340 expandLinear(sf, lf);
342 sMul -= (activeDiag - sf) & x;
346 // Lower multiplication
350 if (lower().activeType() == blockCoeffBase::SQUARE)
352 const squareTypeField& activeLower = this->lower().asSquare();
354 // Auxiliary variables used in expand/contract
358 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
360 contractLinear(lt, activeLower[coeffI]);
361 expandLinear(st, lt);
363 sMul[u[coeffI]] -= (activeLower[coeffI] - st) & x[l[coeffI]];
368 // Upper multiplication
372 if (upper().activeType() == blockCoeffBase::SQUARE)
374 const squareTypeField& activeUpper = this->upper().asSquare();
376 // Auxiliary variables used in expand/contract
380 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
382 contractLinear(lt, activeUpper[coeffI]);
383 expandLinear(st, lt);
385 sMul[l[coeffI]] -= (activeUpper[coeffI] - st) & x[u[coeffI]];
388 // If the matrix is symmetric, the lower triangular product
392 for (register label coeffI = 0; coeffI < u.size(); coeffI++)
394 // Use transpose upper coefficient
395 contractLinear(lt, activeUpper[coeffI]);
396 expandLinear(st, lt);
398 (activeUpper[coeffI].T() - st) & x[l[coeffI]];
406 // ************************************************************************* //