Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
11License
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
27Description
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 );
150
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 );
214
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];
263 }
264 }
265}
266
267
269(
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{
352 auto trA = tmp<solveScalarField>::New(psi.size());
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// ************************************************************************* //
A field of fields is a PtrList of fields with reference counting.
Definition FieldField.H:77
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition UListI.H:410
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static label nRequests() noexcept
Number of outstanding requests (on the internal list of requests).
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
A cell is defined as a list of faces with extra functionality.
Definition cell.H:56
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
tmp< scalarField > H1() const
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition lduMatrix.H:769
void residual(solveScalarField &rA, const solveScalarField &psi, const scalarField &source, const FieldField< Field, scalar > &interfaceBouCoeffs, const lduInterfaceFieldPtrsList &interfaces, const direction cmpt) const
void Tmul(solveScalarField &, const tmp< solveScalarField > &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &, const direction cmpt) const
Matrix transpose multiplication with updated interfaces.
const scalarField & diag() const
Definition lduMatrix.C:195
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 & upper() const
Definition lduMatrix.C:235
void sumA(solveScalarField &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &) const
Sum the coefficients on each row of the matrix.
const scalarField & lowerCSR() const
Definition lduMatrix.C:376
const scalarField & lower() const
Definition lduMatrix.C:306
void Amul(solveScalarField &, const tmp< solveScalarField > &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &, const direction cmpt) const
Matrix multiplication with updated interfaces.
bool hasLowerCSR() const noexcept
Definition lduMatrix.H:803
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.
A class for managing temporary objects.
Definition tmp.H:75
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition tmpI.H:289
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition tmp.H:215
const volScalarField & psi
#define PoutInFunction
Report using Foam::Pout with FUNCTION_NAME prefix.
Namespace for handling debugging switches.
Definition debug.C:45
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
Field< solveScalar > solveScalarField
uint8_t direction
Definition direction.H:49
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
UList< label > labelUList
A UList of labels.
Definition UList.H:75
UPtrList< const lduInterfaceField > lduInterfaceFieldPtrsList
List of coupled interface fields to be used in coupling.
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299