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  const label startRequest = Pstream::nRequests();
60 
61  // Initialise the update of interfaced interfaces
62  initMatrixInterfaces
63  (
64  true,
65  interfaceBouCoeffs,
66  interfaces,
67  psi,
68  Apsi,
69  cmpt
70  );
71 
72  const label nCells = diag().size();
73  for (label cell=0; cell<nCells; cell++)
74  {
75  ApsiPtr[cell] = diagPtr[cell]*psiPtr[cell];
76  }
77 
78 
79  const label nFaces = upper().size();
80 
81  for (label face=0; face<nFaces; face++)
82  {
83  ApsiPtr[uPtr[face]] += lowerPtr[face]*psiPtr[lPtr[face]];
84  ApsiPtr[lPtr[face]] += upperPtr[face]*psiPtr[uPtr[face]];
85  }
86 
87  // Update interface interfaces
88  updateMatrixInterfaces
89  (
90  true,
91  interfaceBouCoeffs,
92  interfaces,
93  psi,
94  Apsi,
95  cmpt,
96  startRequest
97  );
98 
99  tpsi.clear();
100 }
101 
102 
104 (
105  solveScalarField& Tpsi,
106  const tmp<solveScalarField>& tpsi,
107  const FieldField<Field, scalar>& interfaceIntCoeffs,
108  const lduInterfaceFieldPtrsList& interfaces,
109  const direction cmpt
110 ) const
111 {
112  solveScalar* __restrict__ TpsiPtr = Tpsi.begin();
113 
114  const solveScalarField& psi = tpsi();
115  const solveScalar* const __restrict__ psiPtr = psi.begin();
116 
117  const scalar* const __restrict__ diagPtr = diag().begin();
118 
119  const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
120  const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
121 
122  const scalar* const __restrict__ lowerPtr = lower().begin();
123  const scalar* const __restrict__ upperPtr = upper().begin();
124 
125  const label startRequest = Pstream::nRequests();
126 
127  // Initialise the update of interfaced interfaces
128  initMatrixInterfaces
129  (
130  true,
131  interfaceIntCoeffs,
132  interfaces,
133  psi,
134  Tpsi,
135  cmpt
136  );
137 
138  const label nCells = diag().size();
139  for (label cell=0; cell<nCells; cell++)
140  {
141  TpsiPtr[cell] = diagPtr[cell]*psiPtr[cell];
142  }
143 
144  const label nFaces = upper().size();
145  for (label face=0; face<nFaces; face++)
146  {
147  TpsiPtr[uPtr[face]] += upperPtr[face]*psiPtr[lPtr[face]];
148  TpsiPtr[lPtr[face]] += lowerPtr[face]*psiPtr[uPtr[face]];
149  }
150 
151  // Update interface interfaces
152  updateMatrixInterfaces
153  (
154  true,
155  interfaceIntCoeffs,
156  interfaces,
157  psi,
158  Tpsi,
159  cmpt,
160  startRequest
161  );
162 
163  tpsi.clear();
164 }
165 
166 
168 (
169  solveScalarField& sumA,
170  const FieldField<Field, scalar>& interfaceBouCoeffs,
171  const lduInterfaceFieldPtrsList& interfaces
172 ) const
173 {
174  solveScalar* __restrict__ sumAPtr = sumA.begin();
175 
176  const scalar* __restrict__ diagPtr = diag().begin();
177 
178  const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
179  const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
180 
181  const scalar* __restrict__ lowerPtr = lower().begin();
182  const scalar* __restrict__ upperPtr = upper().begin();
183 
184  const label nCells = diag().size();
185  const label nFaces = upper().size();
186 
187  for (label cell=0; cell<nCells; cell++)
188  {
189  sumAPtr[cell] = diagPtr[cell];
190  }
191 
192  for (label face=0; face<nFaces; face++)
193  {
194  sumAPtr[uPtr[face]] += lowerPtr[face];
195  sumAPtr[lPtr[face]] += upperPtr[face];
196  }
197 
198  // Add the interface internal coefficients to diagonal
199  // and the interface boundary coefficients to the sum-off-diagonal
200  forAll(interfaces, patchi)
201  {
202  if (interfaces.set(patchi))
203  {
204  const labelUList& pa = lduAddr().patchAddr(patchi);
205  const scalarField& pCoeffs = interfaceBouCoeffs[patchi];
206 
207  forAll(pa, face)
208  {
209  sumAPtr[pa[face]] -= pCoeffs[face];
210  }
211  }
212  }
213 }
214 
215 
217 (
218  solveScalarField& rA,
219  const solveScalarField& psi,
220  const scalarField& source,
221  const FieldField<Field, scalar>& interfaceBouCoeffs,
222  const lduInterfaceFieldPtrsList& interfaces,
223  const direction cmpt
224 ) const
225 {
226  solveScalar* __restrict__ rAPtr = rA.begin();
227 
228  const solveScalar* const __restrict__ psiPtr = psi.begin();
229  const scalar* const __restrict__ diagPtr = diag().begin();
230  const scalar* const __restrict__ sourcePtr = source.begin();
231 
232  const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
233  const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
234 
235  const scalar* const __restrict__ upperPtr = upper().begin();
236  const scalar* const __restrict__ lowerPtr = lower().begin();
237 
238  // Parallel boundary initialisation.
239  // Note: there is a change of sign in the coupled
240  // interface update. The reason for this is that the
241  // internal coefficients are all located at the l.h.s. of
242  // the matrix whereas the "implicit" coefficients on the
243  // coupled boundaries are all created as if the
244  // coefficient contribution is of a source-kind (i.e. they
245  // have a sign as if they are on the r.h.s. of the matrix.
246  // To compensate for this, it is necessary to turn the
247  // sign of the contribution.
248 
249  const label startRequest = Pstream::nRequests();
250 
251  // Initialise the update of interfaced interfaces
252  initMatrixInterfaces
253  (
254  false,
255  interfaceBouCoeffs,
256  interfaces,
257  psi,
258  rA,
259  cmpt
260  );
261 
262  const label nCells = diag().size();
263  for (label cell=0; cell<nCells; cell++)
264  {
265  rAPtr[cell] = sourcePtr[cell] - diagPtr[cell]*psiPtr[cell];
266  }
267 
268 
269  const label nFaces = upper().size();
270 
271  for (label face=0; face<nFaces; face++)
272  {
273  rAPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]];
274  rAPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]];
275  }
276 
277  // Update interface interfaces
278  updateMatrixInterfaces
279  (
280  false,
281  interfaceBouCoeffs,
282  interfaces,
283  psi,
284  rA,
285  cmpt,
286  startRequest
287  );
288 }
289 
290 
292 (
293  const solveScalarField& psi,
294  const scalarField& source,
295  const FieldField<Field, scalar>& interfaceBouCoeffs,
296  const lduInterfaceFieldPtrsList& interfaces,
297  const direction cmpt
298 ) const
299 {
300  tmp<solveScalarField> trA(new solveScalarField(psi.size()));
301  residual(trA.ref(), psi, source, interfaceBouCoeffs, interfaces, cmpt);
302  return trA;
303 }
304 
305 
307 {
308  auto tH1 = tmp<scalarField>::New(lduAddr().size(), Zero);
309 
310  if (lowerPtr_ || upperPtr_)
311  {
312  scalar* __restrict__ H1Ptr = tH1.ref().begin();
313 
314  const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
315  const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
316 
317  const scalar* __restrict__ lowerPtr = lower().begin();
318  const scalar* __restrict__ upperPtr = upper().begin();
319 
320  const label nFaces = upper().size();
321 
322  for (label face=0; face<nFaces; face++)
323  {
324  H1Ptr[uPtr[face]] -= lowerPtr[face];
325  H1Ptr[lPtr[face]] -= upperPtr[face];
326  }
327  }
328 
329  return tH1;
330 }
331 
332 
333 // ************************************************************************* //
Foam::lduMatrix::lduAddr
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition: lduMatrix.H:578
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:287
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::diag
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
Definition: pointPatchFieldFunctions.H:287
Foam::lduMatrix::upper
scalarField & upper()
Definition: lduMatrix.C:203
lduMatrix.H
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.
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::UList::begin
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:329
Foam::tmp::ref
T & ref() const
Definition: tmpI.H:227
Foam::stringOps::lower
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1184
Foam::Field< solveScalar >
Foam::UPtrList< const lduInterfaceField >
Foam::solveScalarField
Field< solveScalar > solveScalarField
Definition: primitiveFieldsFwd.H:53
Foam::lduMatrix::H1
tmp< scalarField > H1() const
Definition: lduMatrixATmul.C:306
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:168
Foam::UPtrList::set
const T * set(const label i) const
Definition: UPtrList.H:176
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:52
Foam::face
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:72
Foam::stringOps::upper
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1200
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:104
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:217
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