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-2024 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  const auto& addr = lduAddr();
47 
48  solveScalar* __restrict__ ApsiPtr = Apsi.begin();
49 
50  const solveScalarField& psi = tpsi();
51  const solveScalar* const __restrict__ psiPtr = psi.begin();
52 
53  const scalar* const __restrict__ diagPtr = diag().begin();
54 
55  const label* const __restrict__ uPtr = addr.upperAddr().begin();
56  const label* const __restrict__ lPtr = addr.lowerAddr().begin();
57 
58  const scalar* const __restrict__ upperPtr = upper().begin();
59  const scalar* const __restrict__ lowerPtr = lower().begin();
60 
61  const label startRequest = UPstream::nRequests();
62 
63  // Initialise the update of interfaced interfaces
65  (
66  true,
67  interfaceBouCoeffs,
68  interfaces,
69  psi,
70  Apsi,
71  cmpt
72  );
73 
74  const label nCells = diag().size();
75 
76  if (hasLowerCSR())
77  {
78  // Use cell-based looping
79  if (debug == 2) PoutInFunction<< "cell-based looping" << endl;
80 
81  const label* const __restrict__ oStartPtr =
82  addr.ownerStartAddr().begin();
83  const label* const __restrict__ loStartPtr =
84  addr.losortStartAddr().begin();
85  const label* const __restrict__ lcsrPtr =
86  addr.lowerCSRAddr().begin();
87 
88  // Note: lowerCSR constructed from lower if available, upper otherwise
89  // so is handling symmetric()
90  const scalar* const __restrict__ lowercsrPtr = lowerCSR().begin();
91 
92  for (label cell=0; cell<nCells; cell++)
93  {
94  auto& val = ApsiPtr[cell];
95 
96  val = diagPtr[cell]*psiPtr[cell];
97 
98  // Add lower contributions
99  {
100  const label start = loStartPtr[cell];
101  const label end = loStartPtr[cell+1];
102 
103  for (label i = start; i < end; i++)
104  {
105  const label nbrCell = lcsrPtr[i];
106  val += lowercsrPtr[i]*psiPtr[nbrCell];
107  }
108  }
109  // Add upper contributions
110  {
111  const label start = oStartPtr[cell];
112  const label end = oStartPtr[cell+1];
113 
114  for (label i = start; i < end; i++)
115  {
116  const label nbrCell = uPtr[i];
117  val += upperPtr[i]*psiPtr[nbrCell];
118  }
119  }
120  }
121  }
122  else
123  {
124  for (label cell=0; cell<nCells; cell++)
125  {
126  ApsiPtr[cell] = diagPtr[cell]*psiPtr[cell];
127  }
128 
129 
130  const label nFaces = upper().size();
131 
132  for (label face=0; face<nFaces; face++)
133  {
134  ApsiPtr[uPtr[face]] += lowerPtr[face]*psiPtr[lPtr[face]];
135  ApsiPtr[lPtr[face]] += upperPtr[face]*psiPtr[uPtr[face]];
136  }
137  }
138 
139  // Update interface interfaces
141  (
142  true,
143  interfaceBouCoeffs,
144  interfaces,
145  psi,
146  Apsi,
147  cmpt,
148  startRequest
149  );
151  tpsi.clear();
152 }
153 
154 
156 (
157  solveScalarField& Tpsi,
158  const tmp<solveScalarField>& tpsi,
159  const FieldField<Field, scalar>& interfaceIntCoeffs,
160  const lduInterfaceFieldPtrsList& interfaces,
161  const direction cmpt
162 ) const
163 {
164  solveScalar* __restrict__ TpsiPtr = Tpsi.begin();
165 
166  const solveScalarField& psi = tpsi();
167  const solveScalar* const __restrict__ psiPtr = psi.begin();
168 
169  const scalar* const __restrict__ diagPtr = diag().begin();
170 
171  const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
172  const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
173 
174  const scalar* const __restrict__ lowerPtr = lower().begin();
175  const scalar* const __restrict__ upperPtr = upper().begin();
176 
177  const label startRequest = UPstream::nRequests();
178 
179  // Initialise the update of interfaced interfaces
180  initMatrixInterfaces
181  (
182  true,
183  interfaceIntCoeffs,
184  interfaces,
185  psi,
186  Tpsi,
187  cmpt
188  );
189 
190  const label nCells = diag().size();
191  for (label cell=0; cell<nCells; cell++)
192  {
193  TpsiPtr[cell] = diagPtr[cell]*psiPtr[cell];
194  }
195 
196  const label nFaces = upper().size();
197  for (label face=0; face<nFaces; face++)
198  {
199  TpsiPtr[uPtr[face]] += upperPtr[face]*psiPtr[lPtr[face]];
200  TpsiPtr[lPtr[face]] += lowerPtr[face]*psiPtr[uPtr[face]];
201  }
202 
203  // Update interface interfaces
204  updateMatrixInterfaces
205  (
206  true,
207  interfaceIntCoeffs,
208  interfaces,
209  psi,
210  Tpsi,
211  cmpt,
212  startRequest
213  );
215  tpsi.clear();
216 }
217 
218 
220 (
221  solveScalarField& sumA,
222  const FieldField<Field, scalar>& interfaceBouCoeffs,
223  const lduInterfaceFieldPtrsList& interfaces
224 ) const
225 {
226  solveScalar* __restrict__ sumAPtr = sumA.begin();
227 
228  const scalar* __restrict__ diagPtr = diag().begin();
229 
230  const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
231  const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
232 
233  const scalar* __restrict__ lowerPtr = lower().begin();
234  const scalar* __restrict__ upperPtr = upper().begin();
235 
236  const label nCells = diag().size();
237  const label nFaces = upper().size();
238 
239  for (label cell=0; cell<nCells; cell++)
240  {
241  sumAPtr[cell] = diagPtr[cell];
242  }
243 
244  for (label face=0; face<nFaces; face++)
245  {
246  sumAPtr[uPtr[face]] += lowerPtr[face];
247  sumAPtr[lPtr[face]] += upperPtr[face];
248  }
249 
250  // Add the interface internal coefficients to diagonal
251  // and the interface boundary coefficients to the sum-off-diagonal
252  forAll(interfaces, patchi)
253  {
254  if (interfaces.set(patchi))
255  {
256  const labelUList& pa = lduAddr().patchAddr(patchi);
257  const scalarField& pCoeffs = interfaceBouCoeffs[patchi];
258 
259  forAll(pa, face)
260  {
261  sumAPtr[pa[face]] -= pCoeffs[face];
262  }
263  }
264  }
265 }
266 
267 
269 (
270  solveScalarField& rA,
271  const solveScalarField& psi,
272  const scalarField& source,
273  const FieldField<Field, scalar>& interfaceBouCoeffs,
274  const lduInterfaceFieldPtrsList& interfaces,
275  const direction cmpt
276 ) const
277 {
278  solveScalar* __restrict__ rAPtr = rA.begin();
279 
280  const solveScalar* const __restrict__ psiPtr = psi.begin();
281  const scalar* const __restrict__ diagPtr = diag().begin();
282  const scalar* const __restrict__ sourcePtr = source.begin();
283 
284  const label* const __restrict__ uPtr = lduAddr().upperAddr().begin();
285  const label* const __restrict__ lPtr = lduAddr().lowerAddr().begin();
286 
287  const scalar* const __restrict__ upperPtr = upper().begin();
288  const scalar* const __restrict__ lowerPtr = lower().begin();
289 
290  // Parallel boundary initialisation.
291  // Note: there is a change of sign in the coupled
292  // interface update. The reason for this is that the
293  // internal coefficients are all located at the l.h.s. of
294  // the matrix whereas the "implicit" coefficients on the
295  // coupled boundaries are all created as if the
296  // coefficient contribution is of a source-kind (i.e. they
297  // have a sign as if they are on the r.h.s. of the matrix.
298  // To compensate for this, it is necessary to turn the
299  // sign of the contribution.
300 
301  const label startRequest = UPstream::nRequests();
302 
303  // Initialise the update of interfaced interfaces
304  initMatrixInterfaces
305  (
306  false,
307  interfaceBouCoeffs,
308  interfaces,
309  psi,
310  rA,
311  cmpt
312  );
313 
314  const label nCells = diag().size();
315  for (label cell=0; cell<nCells; cell++)
316  {
317  rAPtr[cell] = sourcePtr[cell] - diagPtr[cell]*psiPtr[cell];
318  }
319 
320 
321  const label nFaces = upper().size();
322 
323  for (label face=0; face<nFaces; face++)
324  {
325  rAPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]];
326  rAPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]];
327  }
328 
329  // Update interface interfaces
330  updateMatrixInterfaces
331  (
332  false,
333  interfaceBouCoeffs,
334  interfaces,
335  psi,
336  rA,
337  cmpt,
338  startRequest
339  );
340 }
341 
342 
344 (
345  const solveScalarField& psi,
346  const scalarField& source,
347  const FieldField<Field, scalar>& interfaceBouCoeffs,
348  const lduInterfaceFieldPtrsList& interfaces,
349  const direction cmpt
350 ) const
351 {
353  residual(trA.ref(), psi, source, interfaceBouCoeffs, interfaces, cmpt);
354  return trA;
355 }
356 
357 
359 {
360  auto tH1 = tmp<scalarField>::New(lduAddr().size(), Zero);
361 
362  if (lowerPtr_ || upperPtr_)
363  {
364  scalar* __restrict__ H1Ptr = tH1.ref().begin();
365 
366  const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
367  const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
368 
369  const scalar* __restrict__ lowerPtr = lower().begin();
370  const scalar* __restrict__ upperPtr = upper().begin();
371 
372  const label nFaces = upper().size();
373 
374  for (label face=0; face<nFaces; face++)
375  {
376  H1Ptr[uPtr[face]] -= lowerPtr[face];
377  H1Ptr[lPtr[face]] -= upperPtr[face];
378  }
379  }
380 
381  return tH1;
382 }
383 
384 
385 // ************************************************************************* //
UPtrList< const lduInterfaceField > lduInterfaceFieldPtrsList
List of coupled interface fields to be used in coupling.
const scalarField & diag() const
Definition: lduMatrix.C:195
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
void Tmul(solveScalarField &, const tmp< solveScalarField > &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &, const direction cmpt) const
Matrix transpose multiplication with updated interfaces.
uint8_t direction
Definition: direction.H:46
bool hasLowerCSR() const noexcept
Definition: lduMatrix.H:803
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
Field< solveScalar > solveScalarField
void residual(solveScalarField &rA, const solveScalarField &psi, const scalarField &source, const FieldField< Field, scalar > &interfaceBouCoeffs, const lduInterfaceFieldPtrsList &interfaces, const direction cmpt) const
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:518
tmp< scalarField > H1() const
UList< label > labelUList
A UList of labels.
Definition: UList.H:76
A field of fields is a PtrList of fields with reference counting.
Definition: FieldField.H:51
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:400
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
void Amul(solveScalarField &, const tmp< solveScalarField > &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &, const direction cmpt) const
Matrix multiplication with updated interfaces.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
void updateMatrixInterfaces(const bool add, const FieldField< Field, scalar > &interfaceCoeffs, const lduInterfaceFieldPtrsList &interfaces, const solveScalarField &psiif, solveScalarField &result, const direction cmpt, const label startRequest) const
Update interfaced interfaces for matrix operations.
void initMatrixInterfaces(const bool add, const FieldField< Field, scalar > &interfaceCoeffs, const lduInterfaceFieldPtrsList &interfaces, const solveScalarField &psiif, solveScalarField &result, const direction cmpt) const
Initialise the update of interfaced interfaces for matrix operations.
const scalarField & lower() const
Definition: lduMatrix.C:306
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:217
void sumA(solveScalarField &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &) const
Sum the coefficients on each row of the matrix.
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:403
int debug
Static debugging option.
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
const scalarField & upper() const
Definition: lduMatrix.C:235
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition: lduMatrix.H:769
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:53
const char * end
Definition: SVGTools.H:223
#define PoutInFunction
Report using Foam::Pout with FUNCTION_NAME prefix.
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: tmpI.H:289
const volScalarField & psi
A class for managing temporary objects.
Definition: HashPtrTable.H:50
const T * set(const label i) const
Return const pointer to element (can be nullptr), or nullptr for out-of-range access (ie...
Definition: UPtrList.H:366
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
const scalarField & lowerCSR() const
Definition: lduMatrix.C:376