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 -------------------------------------------------------------------------------
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 \*---------------------------------------------------------------------------*/
28 
29 #include "lduMatrix.H"
30 
31 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
32 
33 template<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 
51 template<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 
69 template<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 
89 template<class Type, class DType, class LUType>
91 Foam::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  }
114  }
115 
116  return tHpsi;
117 }
118 
119 template<class Type, class DType, class LUType>
121 Foam::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 
129 template<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 
152 template<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 
164 template<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 
205 template<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 
223 template<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 
251 template<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 
328 template<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  }
399 
400  interfacesUpper_ -= A.interfacesUpper_;
401  interfacesLower_ -= A.interfacesLower_;
402 }
403 
404 
405 template<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 
453 template<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 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
void sumMagOffDiag(Field< LUType > &sumOff) const
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.
string upper(const std::string &s)
Return string copy transformed with std::toupper on each character.
Definition: stringOps.C:1187
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
Generic templated field type.
Definition: Field.H:62
tmp< Field< Type > > H(const Field< Type > &) const
void operator*=(const scalarField &)
void negate(DimensionedField< Type, GeoMesh > &result, const DimensionedField< Type, GeoMesh > &f1)
errorManip< error > abort(error &err)
Definition: errorManip.H:139
void operator-=(const LduMatrix< Type, DType, LUType > &)
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
const Field< LUType > & upper() const
Definition: LduMatrix.C:178
const Field< LUType > & lower() const
Definition: LduMatrix.C:223
string lower(const std::string &s)
Return string copy transformed with std::tolower on each character.
Definition: stringOps.C:1171
LduMatrix is a general matrix class in which the coefficients are stored as three arrays...
Definition: LduMatrix.H:68
void operator+=(const LduMatrix< Type, DType, LUType > &)
tmp< Field< Type > > faceH(const Field< Type > &) const
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
const volScalarField & psi
A class for managing temporary objects.
Definition: HashPtrTable.H:50
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))
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
volScalarField H(IOobject("H", runTime.timeName(), mesh.thisDb(), IOobject::NO_READ, IOobject::AUTO_WRITE), mesh, dimensionedScalar(dimLength, Zero))
void operator=(const LduMatrix< Type, DType, LUType > &)
Copy assignment.