Loading...
Searching...
No Matches
LduMatrixOperations.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) 2019-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
27\*---------------------------------------------------------------------------*/
28
29#include "lduMatrix.H"
30
31// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
32
33template<class Type, class DType, class LUType>
35{
36 const Field<LUType>& Lower = const_cast<const LduMatrix&>(*this).lower();
37 const Field<LUType>& Upper = const_cast<const LduMatrix&>(*this).upper();
38 Field<DType>& Diag = diag();
39
40 const labelUList& l = lduAddr().lowerAddr();
41 const labelUList& u = lduAddr().upperAddr();
42
43 for (label face=0; face<l.size(); face++)
44 {
45 Diag[l[face]] += Lower[face];
46 Diag[u[face]] += Upper[face];
47 }
48}
49
50
51template<class Type, class DType, class LUType>
53{
54 const Field<LUType>& Lower = const_cast<const LduMatrix&>(*this).lower();
55 const Field<LUType>& Upper = const_cast<const LduMatrix&>(*this).upper();
56 Field<DType>& Diag = diag();
57
58 const labelUList& l = lduAddr().lowerAddr();
59 const labelUList& u = lduAddr().upperAddr();
60
61 for (label face=0; face<l.size(); face++)
62 {
63 Diag[l[face]] -= Lower[face];
64 Diag[u[face]] -= Upper[face];
65 }
66}
67
68
69template<class Type, class DType, class LUType>
71(
72 Field<LUType>& sumOff
73) const
74{
75 const Field<LUType>& Lower = const_cast<const LduMatrix&>(*this).lower();
76 const Field<LUType>& Upper = const_cast<const LduMatrix&>(*this).upper();
77
78 const labelUList& l = lduAddr().lowerAddr();
79 const labelUList& u = lduAddr().upperAddr();
80
81 for (label face = 0; face < l.size(); face++)
82 {
83 sumOff[u[face]] += cmptMag(Lower[face]);
84 sumOff[l[face]] += cmptMag(Upper[face]);
85 }
86}
87
88
89template<class Type, class DType, class LUType>
91Foam::LduMatrix<Type, DType, LUType>::H(const Field<Type>& psi) const
92{
93 auto tHpsi = tmp<Field<Type>>::New(lduAddr().size(), Foam::zero{});
94
95 if (hasLower() || hasUpper())
96 {
97 Type* __restrict__ HpsiPtr = tHpsi.ref().begin();
98
99 const Type* __restrict__ psiPtr = psi.begin();
100
101 const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
102 const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
103
104 const LUType* __restrict__ lowerPtr = lower().begin();
105 const LUType* __restrict__ upperPtr = upper().begin();
106
107 const label nFaces = upper().size();
108
109 for (label face=0; face<nFaces; face++)
110 {
111 HpsiPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]];
112 HpsiPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]];
113 }
115
116 return tHpsi;
117}
118
119template<class Type, class DType, class LUType>
121Foam::LduMatrix<Type, DType, LUType>::H(const tmp<Field<Type>>& tpsi) const
122{
123 tmp<Field<Type>> tHpsi(H(tpsi()));
124 tpsi.clear();
125 return tHpsi;
126}
127
128
129template<class Type, class DType, class LUType>
132{
133 const Field<LUType>& Lower = const_cast<const LduMatrix&>(*this).lower();
134 const Field<LUType>& Upper = const_cast<const LduMatrix&>(*this).upper();
135
136 // Take references to addressing
137 const labelUList& l = lduAddr().lowerAddr();
138 const labelUList& u = lduAddr().upperAddr();
139
140 auto tfaceHpsi = tmp<Field<Type>>::New(Lower.size());
141 auto& faceHpsi = tfaceHpsi.ref();
142
143 for (label face=0; face<l.size(); face++)
144 {
145 faceHpsi[face] = Upper[face]*psi[u[face]] - Lower[face]*psi[l[face]];
146 }
148 return tfaceHpsi;
149}
150
151
152template<class Type, class DType, class LUType>
155{
156 tmp<Field<Type>> tfaceHpsi(faceH(tpsi()));
157 tpsi.clear();
158 return tfaceHpsi;
159}
160
161
162// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
163
164template<class Type, class DType, class LUType>
166{
167 if (this == &A)
168 {
169 return; // Self-assignment is a no-op
170 }
171
172 if (A.hasDiag())
173 {
174 diag() = A.diag();
175 }
176
177 if (A.hasUpper())
178 {
179 upper() = A.upper();
180 }
181 else
182 {
183 upperPtr_.reset(nullptr);
184 }
185
186 if (A.hasLower())
187 {
188 lower() = A.lower();
189 }
190 else
191 {
192 lowerPtr_.reset(nullptr);
193 }
194
195 if (A.hasSource())
196 {
197 source() = A.source();
198 }
199
200 interfacesUpper_ = A.interfacesUpper_;
201 interfacesLower_ = A.interfacesLower_;
202}
203
204
205template<class Type, class DType, class LUType>
207{
208 if (this == &A)
209 {
210 return; // Self-assignment is a no-op
211 }
212
213 diagPtr_ = std::move(A.diagPtr_);
214 upperPtr_ = std::move(A.upperPtr_);
215 lowerPtr_ = std::move(A.lowerPtr_);
216 sourcePtr_ = std::move(A.sourcePtr_);
218 interfacesUpper_ = std::move(A.interfacesUpper_);
219 interfacesLower_ = std::move(A.interfacesLower_);
220}
221
222
223template<class Type, class DType, class LUType>
225{
226 if (diagPtr_)
227 {
228 diagPtr_->negate();
229 }
230
231 if (upperPtr_)
232 {
233 upperPtr_->negate();
234 }
235
236 if (lowerPtr_)
237 {
238 lowerPtr_->negate();
239 }
240
241 if (sourcePtr_)
242 {
243 sourcePtr_->negate();
244 }
246 negate(interfacesUpper_);
247 negate(interfacesLower_);
248}
249
250
251template<class Type, class DType, class LUType>
253{
254 if (A.hasDiag())
255 {
256 diag() += A.diag();
257 }
258
259 if (A.hasSource())
260 {
261 source() += A.source();
262 }
263
264 if (symmetric() && A.symmetric())
265 {
266 upper() += A.upper();
267 }
268 else if (symmetric() && A.asymmetric())
269 {
270 if (upperPtr_)
271 {
272 lower();
273 }
274 else
275 {
276 upper();
277 }
278
279 upper() += A.upper();
280 lower() += A.lower();
281 }
282 else if (asymmetric() && A.symmetric())
283 {
284 if (A.hasUpper())
285 {
286 lower() += A.upper();
287 upper() += A.upper();
288 }
289 else
290 {
291 lower() += A.lower();
292 upper() += A.lower();
293 }
294
295 }
296 else if (asymmetric() && A.asymmetric())
297 {
298 lower() += A.lower();
299 upper() += A.upper();
300 }
301 else if (diagonal())
302 {
303 if (A.hasUpper())
304 {
305 upper() = A.upper();
306 }
307
308 if (A.hasLower())
309 {
310 lower() = A.lower();
311 }
312 }
313 else if (A.diagonal())
314 {
315 }
316 else
317 {
319 << "Unknown matrix type combination"
320 << abort(FatalError);
321 }
323 interfacesUpper_ += A.interfacesUpper_;
324 interfacesLower_ += A.interfacesLower_;
325}
326
327
328template<class Type, class DType, class LUType>
330{
331 if (A.hasDiag())
332 {
333 diag() -= A.diag();
334 }
335
336 if (A.hasSource())
337 {
338 source() -= A.source();
339 }
340
341 if (symmetric() && A.symmetric())
342 {
343 upper() -= A.upper();
344 }
345 else if (symmetric() && A.asymmetric())
346 {
347 if (upperPtr_)
348 {
349 lower();
350 }
351 else
352 {
353 upper();
354 }
355
356 upper() -= A.upper();
357 lower() -= A.lower();
358 }
359 else if (asymmetric() && A.symmetric())
360 {
361 if (A.hasUpper())
362 {
363 lower() -= A.upper();
364 upper() -= A.upper();
365 }
366 else
367 {
368 lower() -= A.lower();
369 upper() -= A.lower();
370 }
371
372 }
373 else if (asymmetric() && A.asymmetric())
374 {
375 lower() -= A.lower();
376 upper() -= A.upper();
377 }
378 else if (diagonal())
379 {
380 if (A.hasUpper())
381 {
382 upper() = -A.upper();
383 }
384
385 if (A.hasLower())
386 {
387 lower() = -A.lower();
388 }
389 }
390 else if (A.diagonal())
391 {
392 }
393 else
394 {
396 << "Unknown matrix type combination"
397 << abort(FatalError);
398 }
400 interfacesUpper_ -= A.interfacesUpper_;
401 interfacesLower_ -= A.interfacesLower_;
402}
403
404
405template<class Type, class DType, class LUType>
407(
408 const scalarField& sf
409)
410{
411 if (diagPtr_)
412 {
413 *diagPtr_ *= sf;
414 }
415
416 if (sourcePtr_)
417 {
418 *sourcePtr_ *= sf;
419 }
420
421 // Non-uniform scaling causes a symmetric matrix
422 // to become asymmetric
423 if (symmetric() || asymmetric())
424 {
425 Field<LUType>& upper = this->upper();
426 Field<LUType>& lower = this->lower();
427
428 const labelUList& l = lduAddr().lowerAddr();
429 const labelUList& u = lduAddr().upperAddr();
430
431 for (label face=0; face<upper.size(); face++)
432 {
433 upper[face] *= sf[l[face]];
434 }
435
436 for (label face=0; face<lower.size(); face++)
437 {
438 lower[face] *= sf[u[face]];
439 }
440 }
441
443 << "Scaling a matrix by scalarField is not currently supported\n"
444 "because scaling interfacesUpper_ and interfacesLower_ "
445 "require special transfers"
446 << abort(FatalError);
448 //interfacesUpper_ *= ;
449 //interfacesLower_ *= sf;
450}
451
452
453template<class Type, class DType, class LUType>
455{
456 if (diagPtr_)
457 {
458 *diagPtr_ *= s;
459 }
460
461 if (sourcePtr_)
462 {
463 *sourcePtr_ *= s;
464 }
465
466 if (upperPtr_)
467 {
468 *upperPtr_ *= s;
469 }
470
471 if (lowerPtr_)
472 {
473 *lowerPtr_ *= s;
474 }
475
476 interfacesUpper_ *= s;
477 interfacesLower_ *= s;
478}
479
480
481// ************************************************************************* //
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
LduMatrix is a general matrix class in which the coefficients are stored as three arrays,...
Definition LduMatrix.H:84
bool hasUpper() const noexcept
Definition LduMatrix.H:690
const Field< LUType > & upper() const
Definition LduMatrix.C:178
const lduAddressing & lduAddr() const
Return the LDU addressing.
Definition LduMatrix.H:616
const Field< Type > & source() const
Definition LduMatrix.C:267
bool asymmetric() const noexcept
Matrix is asymmetric (ie, full).
Definition LduMatrix.H:713
tmp< Field< Type > > H(const Field< Type > &) const
bool symmetric() const noexcept
Matrix is symmetric.
Definition LduMatrix.H:705
const Field< DType > & diag() const
Definition LduMatrix.C:151
void operator+=(const LduMatrix< Type, DType, LUType > &)
void operator=(const LduMatrix< Type, DType, LUType > &)
Copy assignment.
void operator*=(const scalarField &)
bool diagonal() const noexcept
Matrix has diagonal only.
Definition LduMatrix.H:697
void sumMagOffDiag(Field< LUType > &sumOff) const
LduMatrix(const lduMesh &mesh)
Construct given an LDU addressed mesh.
Definition LduMatrix.C:28
bool hasLower() const noexcept
Definition LduMatrix.H:691
tmp< Field< Type > > faceH(const Field< Type > &) const
void operator-=(const LduMatrix< Type, DType, LUType > &)
const Field< LUType > & lower() const
Definition LduMatrix.C:223
friend Ostream & operator(Ostream &, const LduMatrix< Type, DType, LUType > &)
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
A face is a list of labels corresponding to mesh vertices.
Definition face.H:71
A class for managing temporary objects.
Definition tmp.H:75
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
const volScalarField & psi
volScalarField H(IOobject("H", runTime.timeName(), mesh.thisDb(), IOobject::NO_READ, IOobject::AUTO_WRITE), mesh, dimensionedScalar(dimLength, Zero))
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
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.
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
errorManip< error > abort(error &err)
Definition errorManip.H:139
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
UList< label > labelUList
A UList of labels.
Definition UList.H:75