1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
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 Multiply a given vector (second argument) by the matrix or its transpose
27 and return the result in the first argument.
29 \*---------------------------------------------------------------------------*/
31 #include "lduMatrix.H"
33 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
35 void Foam::lduMatrix::Amul
38 const tmp<scalarField>& tpsi,
39 const FieldField<Field, scalar>& interfaceBouCoeffs,
40 const lduInterfaceFieldPtrsList& interfaces,
44 scalar* __restrict__ ApsiPtr = Apsi.begin();
46 const scalarField& psi = tpsi();
47 const scalar* const __restrict__ psiPtr = psi.begin();
49 const scalar* const __restrict__ diagPtr = diag().begin();
51 const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
52 const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
54 const scalar* const __restrict__ upperPtr = upper().begin();
55 const scalar* const __restrict__ lowerPtr = lower().begin();
57 // Initialise the update of interfaced interfaces
67 register const label nCells = diag().size();
68 for (register label cell=0; cell<nCells; cell++)
70 #ifdef ICC_IA64_PREFETCH
71 __builtin_prefetch (&psiPtr[cell+96],0,1);
72 __builtin_prefetch (&diagPtr[cell+96],0,1);
73 __builtin_prefetch (&ApsiPtr[cell+96],1,1);
76 ApsiPtr[cell] = diagPtr[cell]*psiPtr[cell];
80 register const label nFaces = upper().size();
81 #ifdef ICC_IA64_PREFETCH
84 for (register label face=0; face<nFaces; face++)
86 #ifdef ICC_IA64_PREFETCH
87 __builtin_prefetch (&uPtr[face+32],0,0);
88 __builtin_prefetch (&lPtr[face+32],0,0);
89 __builtin_prefetch (&lowerPtr[face+32],0,1);
90 __builtin_prefetch (&psiPtr[lPtr[face+32]],0,1);
91 __builtin_prefetch (&ApsiPtr[uPtr[face+32]],0,1);
94 ApsiPtr[uPtr[face]] += lowerPtr[face]*psiPtr[lPtr[face]];
96 #ifdef ICC_IA64_PREFETCH
97 __builtin_prefetch (&upperPtr[face+32],0,1);
98 __builtin_prefetch (&psiPtr[uPtr[face+32]],0,1);
99 __builtin_prefetch (&ApsiPtr[lPtr[face+32]],0,1);
102 ApsiPtr[lPtr[face]] += upperPtr[face]*psiPtr[uPtr[face]];
105 // Update interface interfaces
106 updateMatrixInterfaces
119 void Foam::lduMatrix::Tmul
122 const tmp<scalarField>& tpsi,
123 const FieldField<Field, scalar>& interfaceIntCoeffs,
124 const lduInterfaceFieldPtrsList& interfaces,
128 scalar* __restrict__ TpsiPtr = Tpsi.begin();
130 const scalarField& psi = tpsi();
131 const scalar* const __restrict__ psiPtr = psi.begin();
133 const scalar* const __restrict__ diagPtr = diag().begin();
135 const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
136 const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
138 const scalar* const __restrict__ lowerPtr = lower().begin();
139 const scalar* const __restrict__ upperPtr = upper().begin();
141 // Initialise the update of interfaced interfaces
151 register const label nCells = diag().size();
152 for (register label cell=0; cell<nCells; cell++)
154 #ifdef ICC_IA64_PREFETCH
155 __builtin_prefetch (&psiPtr[cell+96],0,1);
156 __builtin_prefetch (&diagPtr[cell+96],0,1);
157 __builtin_prefetch (&TpsiPtr[cell+96],1,1);
160 TpsiPtr[cell] = diagPtr[cell]*psiPtr[cell];
163 register const label nFaces = upper().size();
164 for (register label face=0; face<nFaces; face++)
166 #ifdef ICC_IA64_PREFETCH
167 __builtin_prefetch (&uPtr[face+32],0,0);
168 __builtin_prefetch (&lPtr[face+32],0,0);
169 __builtin_prefetch (&upperPtr[face+32],0,1);
170 __builtin_prefetch (&psiPtr[lPtr[face+32]],0,1);
171 __builtin_prefetch (&TpsiPtr[uPtr[face+32]],0,1);
174 TpsiPtr[uPtr[face]] += upperPtr[face]*psiPtr[lPtr[face]];
176 #ifdef ICC_IA64_PREFETCH
177 __builtin_prefetch (&lowerPtr[face+32],0,1);
178 __builtin_prefetch (&psiPtr[uPtr[face+32]],0,1);
179 __builtin_prefetch (&TpsiPtr[lPtr[face+32]],0,1);
182 TpsiPtr[lPtr[face]] += lowerPtr[face]*psiPtr[uPtr[face]];
185 // Update interface interfaces
186 updateMatrixInterfaces
199 void Foam::lduMatrix::sumA
202 const FieldField<Field, scalar>& interfaceBouCoeffs,
203 const lduInterfaceFieldPtrsList& interfaces
206 scalar* __restrict__ sumAPtr = sumA.begin();
208 const scalar* __restrict__ diagPtr = diag().begin();
210 const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
211 const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
213 const scalar* __restrict__ lowerPtr = lower().begin();
214 const scalar* __restrict__ upperPtr = upper().begin();
216 register const label nCells = diag().size();
217 register const label nFaces = upper().size();
219 for (register label cell=0; cell<nCells; cell++)
221 #ifdef ICC_IA64_PREFETCH
222 __builtin_prefetch (&diagPtr[cell+96],0,1);
223 __builtin_prefetch (&sumAPtr[cell+96],1,1);
226 sumAPtr[cell] = diagPtr[cell];
229 #ifdef ICC_IA64_PREFETCH
233 for (register label face=0; face<nFaces; face++)
235 #ifdef ICC_IA64_PREFETCH
236 __builtin_prefetch (&uPtr[face+32],0,0);
237 __builtin_prefetch (&lPtr[face+32],0,0);
238 __builtin_prefetch (&lowerPtr[face+32],0,1);
239 __builtin_prefetch (&sumAPtr[uPtr[face+32]],0,1);
242 sumAPtr[uPtr[face]] += lowerPtr[face];
244 #ifdef ICC_IA64_PREFETCH
245 __builtin_prefetch (&upperPtr[face+32],0,1);
246 __builtin_prefetch (&sumAPtr[lPtr[face+32]],0,1);
249 sumAPtr[lPtr[face]] += upperPtr[face];
252 // Add the interface internal coefficients to diagonal
253 // and the interface boundary coefficients to the sum-off-diagonal
254 forAll(interfaces, patchI)
256 if (interfaces.set(patchI))
258 const unallocLabelList& pa = lduAddr().patchAddr(patchI);
259 const scalarField& pCoeffs = interfaceBouCoeffs[patchI];
263 sumAPtr[pa[face]] -= pCoeffs[face];
270 void Foam::lduMatrix::residual
273 const scalarField& psi,
274 const scalarField& source,
275 const FieldField<Field, scalar>& interfaceBouCoeffs,
276 const lduInterfaceFieldPtrsList& interfaces,
280 scalar* __restrict__ rAPtr = rA.begin();
282 const scalar* const __restrict__ psiPtr = psi.begin();
283 const scalar* const __restrict__ diagPtr = diag().begin();
284 const scalar* const __restrict__ sourcePtr = source.begin();
286 const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
287 const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
289 const scalar* const __restrict__ upperPtr = upper().begin();
290 const scalar* const __restrict__ lowerPtr = lower().begin();
292 // Parallel boundary initialisation.
293 // Note: there is a change of sign in the coupled
294 // interface update. The reason for this is that the
295 // internal coefficients are all located at the l.h.s. of
296 // the matrix whereas the "implicit" coefficients on the
297 // coupled boundaries are all created as if the
298 // coefficient contribution is of a source-kind (i.e. they
299 // have a sign as if they are on the r.h.s. of the matrix.
300 // To compensate for this, it is necessary to turn the
301 // sign of the contribution.
303 FieldField<Field, scalar> mBouCoeffs(interfaceBouCoeffs.size());
305 forAll(mBouCoeffs, patchi)
307 if (interfaces.set(patchi))
309 mBouCoeffs.set(patchi, -interfaceBouCoeffs[patchi]);
313 // Initialise the update of interfaced interfaces
323 register const label nCells = diag().size();
324 for (register label cell=0; cell<nCells; cell++)
326 #ifdef ICC_IA64_PREFETCH
327 __builtin_prefetch (&psiPtr[cell+96],0,1);
328 __builtin_prefetch (&diagPtr[cell+96],0,1);
329 __builtin_prefetch (&sourcePtr[cell+96],0,1);
330 __builtin_prefetch (&rAPtr[cell+96],1,1);
333 rAPtr[cell] = sourcePtr[cell] - diagPtr[cell]*psiPtr[cell];
337 register const label nFaces = upper().size();
338 #ifdef ICC_IA64_PREFETCH
341 for (register label face=0; face<nFaces; face++)
343 #ifdef ICC_IA64_PREFETCH
344 __builtin_prefetch (&uPtr[face+32],0,0);
345 __builtin_prefetch (&lPtr[face+32],0,0);
346 __builtin_prefetch (&lowerPtr[face+32],0,1);
347 __builtin_prefetch (&psiPtr[lPtr[face+32]],0,1);
348 __builtin_prefetch (&rAPtr[uPtr[face+32]],0,1);
351 rAPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]];
353 #ifdef ICC_IA64_PREFETCH
354 __builtin_prefetch (&upperPtr[face+32],0,1);
355 __builtin_prefetch (&psiPtr[uPtr[face+32]],0,1);
356 __builtin_prefetch (&rAPtr[lPtr[face+32]],0,1);
359 rAPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]];
362 // Update interface interfaces
363 updateMatrixInterfaces
374 Foam::tmp<Foam::scalarField> Foam::lduMatrix::residual
376 const scalarField& psi,
377 const scalarField& source,
378 const FieldField<Field, scalar>& interfaceBouCoeffs,
379 const lduInterfaceFieldPtrsList& interfaces,
383 tmp<scalarField> trA(new scalarField(psi.size()));
384 residual(trA(), psi, source, interfaceBouCoeffs, interfaces, cmpt);
389 // ************************************************************************* //