lduMatrixATmul.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2019 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Description
28  Multiply a given vector (second argument) by the matrix or its transpose
29  and return the result in the first argument.
30 
31 \*---------------------------------------------------------------------------*/
32 
33 #include "lduMatrix.H"
34 
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 
38 (
39  solveScalarField& Apsi,
40  const tmp<solveScalarField>& tpsi,
41  const FieldField<Field, scalar>& interfaceBouCoeffs,
42  const lduInterfaceFieldPtrsList& interfaces,
43  const direction cmpt
44 ) const
45 {
46  solveScalar* __restrict__ ApsiPtr = Apsi.begin();
47 
48  const solveScalarField& psi = tpsi();
49  const solveScalar* const __restrict__ psiPtr = psi.begin();
50 
51  const scalar* const __restrict__ diagPtr = diag().begin();
52 
53  const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
54  const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
55 
56  const scalar* const __restrict__ upperPtr = upper().begin();
57  const scalar* const __restrict__ lowerPtr = lower().begin();
58 
59  // Initialise the update of interfaced interfaces
60  initMatrixInterfaces
61  (
62  true,
63  interfaceBouCoeffs,
64  interfaces,
65  psi,
66  Apsi,
67  cmpt
68  );
69 
70  const label nCells = diag().size();
71  for (label cell=0; cell<nCells; cell++)
72  {
73  ApsiPtr[cell] = diagPtr[cell]*psiPtr[cell];
74  }
75 
76 
77  const label nFaces = upper().size();
78 
79  for (label face=0; face<nFaces; face++)
80  {
81  ApsiPtr[uPtr[face]] += lowerPtr[face]*psiPtr[lPtr[face]];
82  ApsiPtr[lPtr[face]] += upperPtr[face]*psiPtr[uPtr[face]];
83  }
84 
85  // Update interface interfaces
86  updateMatrixInterfaces
87  (
88  true,
89  interfaceBouCoeffs,
90  interfaces,
91  psi,
92  Apsi,
93  cmpt
94  );
95 
96  tpsi.clear();
97 }
98 
99 
101 (
102  solveScalarField& Tpsi,
103  const tmp<solveScalarField>& tpsi,
104  const FieldField<Field, scalar>& interfaceIntCoeffs,
105  const lduInterfaceFieldPtrsList& interfaces,
106  const direction cmpt
107 ) const
108 {
109  solveScalar* __restrict__ TpsiPtr = Tpsi.begin();
110 
111  const solveScalarField& psi = tpsi();
112  const solveScalar* const __restrict__ psiPtr = psi.begin();
113 
114  const scalar* const __restrict__ diagPtr = diag().begin();
115 
116  const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
117  const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
118 
119  const scalar* const __restrict__ lowerPtr = lower().begin();
120  const scalar* const __restrict__ upperPtr = upper().begin();
121 
122  // Initialise the update of interfaced interfaces
123  initMatrixInterfaces
124  (
125  true,
126  interfaceIntCoeffs,
127  interfaces,
128  psi,
129  Tpsi,
130  cmpt
131  );
132 
133  const label nCells = diag().size();
134  for (label cell=0; cell<nCells; cell++)
135  {
136  TpsiPtr[cell] = diagPtr[cell]*psiPtr[cell];
137  }
138 
139  const label nFaces = upper().size();
140  for (label face=0; face<nFaces; face++)
141  {
142  TpsiPtr[uPtr[face]] += upperPtr[face]*psiPtr[lPtr[face]];
143  TpsiPtr[lPtr[face]] += lowerPtr[face]*psiPtr[uPtr[face]];
144  }
145 
146  // Update interface interfaces
147  updateMatrixInterfaces
148  (
149  true,
150  interfaceIntCoeffs,
151  interfaces,
152  psi,
153  Tpsi,
154  cmpt
155  );
156 
157  tpsi.clear();
158 }
159 
160 
162 (
163  solveScalarField& sumA,
164  const FieldField<Field, scalar>& interfaceBouCoeffs,
165  const lduInterfaceFieldPtrsList& interfaces
166 ) const
167 {
168  solveScalar* __restrict__ sumAPtr = sumA.begin();
169 
170  const scalar* __restrict__ diagPtr = diag().begin();
171 
172  const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
173  const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
174 
175  const scalar* __restrict__ lowerPtr = lower().begin();
176  const scalar* __restrict__ upperPtr = upper().begin();
177 
178  const label nCells = diag().size();
179  const label nFaces = upper().size();
180 
181  for (label cell=0; cell<nCells; cell++)
182  {
183  sumAPtr[cell] = diagPtr[cell];
184  }
185 
186  for (label face=0; face<nFaces; face++)
187  {
188  sumAPtr[uPtr[face]] += lowerPtr[face];
189  sumAPtr[lPtr[face]] += upperPtr[face];
190  }
191 
192  // Add the interface internal coefficients to diagonal
193  // and the interface boundary coefficients to the sum-off-diagonal
194  forAll(interfaces, patchi)
195  {
196  if (interfaces.set(patchi))
197  {
198  const labelUList& pa = lduAddr().patchAddr(patchi);
199  const scalarField& pCoeffs = interfaceBouCoeffs[patchi];
200 
201  forAll(pa, face)
202  {
203  sumAPtr[pa[face]] -= pCoeffs[face];
204  }
205  }
206  }
207 }
208 
209 
211 (
212  solveScalarField& rA,
213  const solveScalarField& psi,
214  const scalarField& source,
215  const FieldField<Field, scalar>& interfaceBouCoeffs,
216  const lduInterfaceFieldPtrsList& interfaces,
217  const direction cmpt
218 ) const
219 {
220  solveScalar* __restrict__ rAPtr = rA.begin();
221 
222  const solveScalar* const __restrict__ psiPtr = psi.begin();
223  const scalar* const __restrict__ diagPtr = diag().begin();
224  const scalar* const __restrict__ sourcePtr = source.begin();
225 
226  const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
227  const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
228 
229  const scalar* const __restrict__ upperPtr = upper().begin();
230  const scalar* const __restrict__ lowerPtr = lower().begin();
231 
232  // Parallel boundary initialisation.
233  // Note: there is a change of sign in the coupled
234  // interface update. The reason for this is that the
235  // internal coefficients are all located at the l.h.s. of
236  // the matrix whereas the "implicit" coefficients on the
237  // coupled boundaries are all created as if the
238  // coefficient contribution is of a source-kind (i.e. they
239  // have a sign as if they are on the r.h.s. of the matrix.
240  // To compensate for this, it is necessary to turn the
241  // sign of the contribution.
242 
243  // Initialise the update of interfaced interfaces
244  initMatrixInterfaces
245  (
246  false,
247  interfaceBouCoeffs,
248  interfaces,
249  psi,
250  rA,
251  cmpt
252  );
253 
254  const label nCells = diag().size();
255  for (label cell=0; cell<nCells; cell++)
256  {
257  rAPtr[cell] = sourcePtr[cell] - diagPtr[cell]*psiPtr[cell];
258  }
259 
260 
261  const label nFaces = upper().size();
262 
263  for (label face=0; face<nFaces; face++)
264  {
265  rAPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]];
266  rAPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]];
267  }
268 
269  // Update interface interfaces
270  updateMatrixInterfaces
271  (
272  false,
273  interfaceBouCoeffs,
274  interfaces,
275  psi,
276  rA,
277  cmpt
278  );
279 }
280 
281 
283 (
284  const solveScalarField& psi,
285  const scalarField& source,
286  const FieldField<Field, scalar>& interfaceBouCoeffs,
287  const lduInterfaceFieldPtrsList& interfaces,
288  const direction cmpt
289 ) const
290 {
291  tmp<solveScalarField> trA(new solveScalarField(psi.size()));
292  residual(trA.ref(), psi, source, interfaceBouCoeffs, interfaces, cmpt);
293  return trA;
294 }
295 
296 
298 {
299  auto tH1 = tmp<scalarField>::New(lduAddr().size(), Zero);
300 
301  if (lowerPtr_ || upperPtr_)
302  {
303  scalar* __restrict__ H1Ptr = tH1.ref().begin();
304 
305  const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
306  const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
307 
308  const scalar* __restrict__ lowerPtr = lower().begin();
309  const scalar* __restrict__ upperPtr = upper().begin();
310 
311  const label nFaces = upper().size();
312 
313  for (label face=0; face<nFaces; face++)
314  {
315  H1Ptr[uPtr[face]] -= lowerPtr[face];
316  H1Ptr[lPtr[face]] -= upperPtr[face];
317  }
318  }
319 
320  return tH1;
321 }
322 
323 
324 // ************************************************************************* //
Foam::lduMatrix::lduAddr
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition: lduMatrix.H:572
Foam::FieldField
A field of fields is a PtrList of fields with reference counting.
Definition: FieldField.H:53
Foam::tmp::clear
void clear() const noexcept
Definition: tmpI.H:325
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:59
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::diag
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
Definition: pointPatchFieldFunctions.H:287
Foam::lduMatrix::upper
scalarField & upper()
Definition: lduMatrix.C:203
Foam::UPtrList::set
const T * set(const label i) const
Return const pointer to element (if set) or nullptr.
Definition: UPtrListI.H:176
lduMatrix.H
Foam::stringOps::lower
string lower(const std::string &str)
Return string transformed with std::tolower on each character.
Definition: stringOps.C:1199
Foam::lduMatrix::Amul
void Amul(solveScalarField &, const tmp< solveScalarField > &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &, const direction cmpt) const
Matrix multiplication with updated interfaces.
Definition: lduMatrixATmul.C:38
Foam::lduAddressing::upperAddr
virtual const labelUList & upperAddr() const =0
Return upper addressing.
Foam::UList::begin
iterator begin()
Return an iterator to begin traversing the UList.
Definition: UListI.H:276
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:258
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:62
Foam::Field< solveScalar >
Foam::stringOps::upper
string upper(const std::string &str)
Return string transformed with std::toupper on each character.
Definition: stringOps.C:1219
Foam::UPtrList< const lduInterfaceField >
Foam::solveScalarField
Field< solveScalar > solveScalarField
Definition: primitiveFieldsFwd.H:53
Foam::lduMatrix::H1
tmp< scalarField > H1() const
Definition: lduMatrixATmul.C:297
Foam::lduMatrix::sumA
void sumA(solveScalarField &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &) const
Sum the coefficients on each row of the matrix.
Definition: lduMatrixATmul.C:162
Foam::lduAddressing::lowerAddr
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
Foam::UList< label >
Foam::tmp::New
static tmp< T > New(Args &&... args)
Construct tmp of T with forwarding arguments.
Foam::direction
uint8_t direction
Definition: direction.H:47
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:74
psi
const volScalarField & psi
Definition: createFieldRefs.H:1
Foam::lduMatrix::Tmul
void Tmul(solveScalarField &, const tmp< solveScalarField > &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &, const direction cmpt) const
Matrix transpose multiplication with updated interfaces.
Definition: lduMatrixATmul.C:101
Foam::lduMatrix::residual
void residual(solveScalarField &rA, const solveScalarField &psi, const scalarField &source, const FieldField< Field, scalar > &interfaceBouCoeffs, const lduInterfaceFieldPtrsList &interfaces, const direction cmpt) const
Definition: lduMatrixATmul.C:211
Foam::lduMatrix::lower
scalarField & lower()
Definition: lduMatrix.C:174
Foam::cell
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:54