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-------------------------------------------------------------------------------
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 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
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
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(
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{
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// ************************************************************************* //
A field of fields is a PtrList of fields with reference counting.
Definition: FieldField.H:80
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:329
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
static label nRequests()
Get number of outstanding requests.
Definition: UPstream.C:90
const T * set(const label i) const
Definition: UPtrList.H:248
A cell is defined as a list of faces with extra functionality.
Definition: cell.H:57
tmp< Field< Type > > residual() const
Return the matrix residual.
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
virtual const labelUList & upperAddr() const =0
Return upper addressing.
virtual const labelUList & lowerAddr() const =0
Return lower addressing.
tmp< scalarField > H1() const
scalarField & upper()
Definition: lduMatrix.C:203
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition: lduMatrix.H:578
void Tmul(solveScalarField &, const tmp< solveScalarField > &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &, const direction cmpt) const
Matrix transpose multiplication with updated interfaces.
void initMatrixInterfaces(const bool add, const FieldField< Field, scalar > &interfaceCoeffs, const lduInterfaceFieldPtrsList &interfaces, const solveScalarField &psiif, solveScalarField &result, const direction cmpt) const
void sumA(solveScalarField &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &) const
Sum the coefficients on each row of the matrix.
scalarField & lower()
Definition: lduMatrix.C:174
scalarField & diag()
Definition: lduMatrix.C:192
void Amul(solveScalarField &, const tmp< solveScalarField > &, const FieldField< Field, scalar > &, const lduInterfaceFieldPtrsList &, const direction cmpt) const
Matrix multiplication with updated interfaces.
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:65
void clear() const noexcept
Definition: tmpI.H:287
T & ref() const
Definition: tmpI.H:227
const volScalarField & psi
const labelList nFaces(UPstream::listGatherValues< label >(aMesh.nFaces()))
Field< solveScalar > solveScalarField
uint8_t direction
Definition: direction.H:56
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333