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 | Copyright (C) 2011-2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "lduMatrix.H"
27 
28 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
29 
30 template<class Type, class DType, class LUType>
32 {
33  const Field<LUType>& Lower = const_cast<const LduMatrix&>(*this).lower();
34  const Field<LUType>& Upper = const_cast<const LduMatrix&>(*this).upper();
35  Field<DType>& Diag = diag();
36 
37  const unallocLabelList& l = lduAddr().lowerAddr();
38  const unallocLabelList& u = lduAddr().upperAddr();
39 
40  for (label face=0; face<l.size(); face++)
41  {
42  Diag[l[face]] += Lower[face];
43  Diag[u[face]] += Upper[face];
44  }
45 }
46 
47 
48 template<class Type, class DType, class LUType>
50 {
51  const Field<LUType>& Lower = const_cast<const LduMatrix&>(*this).lower();
52  const Field<LUType>& Upper = const_cast<const LduMatrix&>(*this).upper();
53  Field<DType>& Diag = diag();
54 
55  const unallocLabelList& l = lduAddr().lowerAddr();
56  const unallocLabelList& u = lduAddr().upperAddr();
57 
58  for (label face=0; face<l.size(); face++)
59  {
60  Diag[l[face]] -= Lower[face];
61  Diag[u[face]] -= Upper[face];
62  }
63 }
64 
65 
66 template<class Type, class DType, class LUType>
68 (
69  Field<LUType>& sumOff
70 ) const
71 {
72  const Field<LUType>& Lower = const_cast<const LduMatrix&>(*this).lower();
73  const Field<LUType>& Upper = const_cast<const LduMatrix&>(*this).upper();
74 
75  const unallocLabelList& l = lduAddr().lowerAddr();
76  const unallocLabelList& u = lduAddr().upperAddr();
77 
78  for (label face = 0; face < l.size(); face++)
79  {
80  sumOff[u[face]] += cmptMag(Lower[face]);
81  sumOff[l[face]] += cmptMag(Upper[face]);
82  }
83 }
84 
85 
86 template<class Type, class DType, class LUType>
89 {
90  tmp<Field<Type> > tHpsi
91  (
92  new Field<Type>(lduAddr().size(), pTraits<Type>::zero)
93  );
94 
95  if (lowerPtr_ || upperPtr_)
96  {
97  Field<Type> & Hpsi = tHpsi();
98 
99  Type* __restrict__ HpsiPtr = Hpsi.begin();
100 
101  const Type* __restrict__ psiPtr = psi.begin();
102 
103  const label* __restrict__ uPtr = lduAddr().upperAddr().begin();
104  const label* __restrict__ lPtr = lduAddr().lowerAddr().begin();
105 
106  const LUType* __restrict__ lowerPtr = lower().begin();
107  const LUType* __restrict__ upperPtr = upper().begin();
108 
109  const label nFaces = upper().size();
110 
111  for (label face=0; face<nFaces; face++)
112  {
113  HpsiPtr[uPtr[face]] -= lowerPtr[face]*psiPtr[lPtr[face]];
114  HpsiPtr[lPtr[face]] -= upperPtr[face]*psiPtr[uPtr[face]];
115  }
116  }
117 
118  return tHpsi;
119 }
120 
121 template<class Type, class DType, class LUType>
124 {
125  tmp<Field<Type> > tHpsi(H(tpsi()));
126  tpsi.clear();
127  return tHpsi;
128 }
129 
130 
131 template<class Type, class DType, class LUType>
134 {
135  const Field<LUType>& Lower = const_cast<const LduMatrix&>(*this).lower();
136  const Field<LUType>& Upper = const_cast<const LduMatrix&>(*this).upper();
137 
138  // Take refereces to addressing
139  const unallocLabelList& l = lduAddr().lowerAddr();
140  const unallocLabelList& u = lduAddr().upperAddr();
141 
142  tmp<Field<Type> > tfaceHpsi(new Field<Type> (Lower.size()));
143  Field<Type> & faceHpsi = tfaceHpsi();
144 
145  for (label face=0; face<l.size(); face++)
146  {
147  faceHpsi[face] = Upper[face]*psi[u[face]] - Lower[face]*psi[l[face]];
148  }
149 
150  return tfaceHpsi;
151 }
152 
153 
154 template<class Type, class DType, class LUType>
157 {
158  tmp<Field<Type> > tfaceHpsi(faceH(tpsi()));
159  tpsi.clear();
160  return tfaceHpsi;
161 }
162 
163 
164 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
165 
166 template<class Type, class DType, class LUType>
168 {
169  if (this == &A)
170  {
172  (
173  "LduMatrix<Type, DType, LUType>::operator=(const LduMatrix&)"
174  ) << "attempted assignment to self"
175  << abort(FatalError);
176  }
177 
178  if (A.diagPtr_)
179  {
180  diag() = A.diag();
181  }
182 
183  if (A.upperPtr_)
184  {
185  upper() = A.upper();
186  }
187  else if (upperPtr_)
188  {
189  delete upperPtr_;
190  upperPtr_ = NULL;
191  }
192 
193  if (A.lowerPtr_)
194  {
195  lower() = A.lower();
196  }
197  else if (lowerPtr_)
198  {
199  delete lowerPtr_;
200  lowerPtr_ = NULL;
201  }
202 
203  if (A.sourcePtr_)
204  {
205  source() = A.source();
206  }
207 
208  interfacesUpper_ = A.interfacesUpper_;
209  interfacesLower_ = A.interfacesLower_;
210 }
211 
212 
213 template<class Type, class DType, class LUType>
215 {
216  if (diagPtr_)
217  {
218  diagPtr_->negate();
219  }
220 
221  if (upperPtr_)
222  {
223  upperPtr_->negate();
224  }
225 
226  if (lowerPtr_)
227  {
228  lowerPtr_->negate();
229  }
230 
231  if (sourcePtr_)
232  {
233  sourcePtr_->negate();
234  }
235 
236  negate(interfacesUpper_);
237  negate(interfacesLower_);
238 }
239 
240 
241 template<class Type, class DType, class LUType>
243 {
244  if (A.diagPtr_)
245  {
246  diag() += A.diag();
247  }
248 
249  if (A.sourcePtr_)
250  {
251  source() += A.source();
252  }
253 
254  if (symmetric() && A.symmetric())
255  {
256  upper() += A.upper();
257  }
258  else if (symmetric() && A.asymmetric())
259  {
260  if (upperPtr_)
261  {
262  lower();
263  }
264  else
265  {
266  upper();
267  }
268 
269  upper() += A.upper();
270  lower() += A.lower();
271  }
272  else if (asymmetric() && A.symmetric())
273  {
274  if (A.upperPtr_)
275  {
276  lower() += A.upper();
277  upper() += A.upper();
278  }
279  else
280  {
281  lower() += A.lower();
282  upper() += A.lower();
283  }
284 
285  }
286  else if (asymmetric() && A.asymmetric())
287  {
288  lower() += A.lower();
289  upper() += A.upper();
290  }
291  else if (diagonal())
292  {
293  if (A.upperPtr_)
294  {
295  upper() = A.upper();
296  }
297 
298  if (A.lowerPtr_)
299  {
300  lower() = A.lower();
301  }
302  }
303  else if (A.diagonal())
304  {
305  }
306  else
307  {
309  (
310  "LduMatrix<Type, DType, LUType>::operator+=(const LduMatrix& A)"
311  ) << "Unknown matrix type combination"
312  << abort(FatalError);
313  }
314 
315  interfacesUpper_ += A.interfacesUpper_;
316  interfacesLower_ += A.interfacesLower_;
317 }
318 
319 
320 template<class Type, class DType, class LUType>
322 {
323  if (A.diagPtr_)
324  {
325  diag() -= A.diag();
326  }
327 
328  if (A.sourcePtr_)
329  {
330  source() -= A.source();
331  }
332 
333  if (symmetric() && A.symmetric())
334  {
335  upper() -= A.upper();
336  }
337  else if (symmetric() && A.asymmetric())
338  {
339  if (upperPtr_)
340  {
341  lower();
342  }
343  else
344  {
345  upper();
346  }
347 
348  upper() -= A.upper();
349  lower() -= A.lower();
350  }
351  else if (asymmetric() && A.symmetric())
352  {
353  if (A.upperPtr_)
354  {
355  lower() -= A.upper();
356  upper() -= A.upper();
357  }
358  else
359  {
360  lower() -= A.lower();
361  upper() -= A.lower();
362  }
363 
364  }
365  else if (asymmetric() && A.asymmetric())
366  {
367  lower() -= A.lower();
368  upper() -= A.upper();
369  }
370  else if (diagonal())
371  {
372  if (A.upperPtr_)
373  {
374  upper() = -A.upper();
375  }
376 
377  if (A.lowerPtr_)
378  {
379  lower() = -A.lower();
380  }
381  }
382  else if (A.diagonal())
383  {
384  }
385  else
386  {
388  (
389  "LduMatrix<Type, DType, LUType>::operator-=(const LduMatrix& A)"
390  ) << "Unknown matrix type combination"
391  << abort(FatalError);
392  }
393 
394  interfacesUpper_ -= A.interfacesUpper_;
395  interfacesLower_ -= A.interfacesLower_;
396 }
397 
398 
399 template<class Type, class DType, class LUType>
400 void Foam::LduMatrix<Type, DType, LUType>::operator*=
401 (
402  const scalarField& sf
403 )
404 {
405  if (diagPtr_)
406  {
407  *diagPtr_ *= sf;
408  }
409 
410  if (sourcePtr_)
411  {
412  *sourcePtr_ *= sf;
413  }
414 
415  // Non-uniform scaling causes a symmetric matrix
416  // to become asymmetric
417  if (symmetric() || asymmetric())
418  {
419  Field<LUType>& upper = this->upper();
420  Field<LUType>& lower = this->lower();
421 
422  const unallocLabelList& l = lduAddr().lowerAddr();
423  const unallocLabelList& u = lduAddr().upperAddr();
424 
425  for (label face=0; face<upper.size(); face++)
426  {
427  upper[face] *= sf[l[face]];
428  }
429 
430  for (label face=0; face<lower.size(); face++)
431  {
432  lower[face] *= sf[u[face]];
433  }
434  }
435 
437  (
438  "LduMatrix<Type, DType, LUType>::operator*=(const scalarField& sf)"
439  ) << "Scaling a matrix by scalarField is not currently supported\n"
440  "because scaling interfacesUpper_ and interfacesLower_ "
441  "require special transfers"
442  << abort(FatalError);
443 
444  //interfacesUpper_ *= ;
445  //interfacesLower_ *= sf;
446 }
447 
448 
449 template<class Type, class DType, class LUType>
451 {
452  if (diagPtr_)
453  {
454  *diagPtr_ *= s;
455  }
456 
457  if (sourcePtr_)
458  {
459  *sourcePtr_ *= s;
460  }
461 
462  if (upperPtr_)
463  {
464  *upperPtr_ *= s;
465  }
466 
467  if (lowerPtr_)
468  {
469  *lowerPtr_ *= s;
470  }
471 
472  interfacesUpper_ *= s;
473  interfacesLower_ *= s;
474 }
475 
476 
477 // ************************************************************************* //
void operator+=(const LduMatrix< Type, DType, LUType > &)
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){gmvFile<< iter().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 ))
bool symmetric() const
Definition: LduMatrix.H:582
bool asymmetric() const
Definition: LduMatrix.H:587
void negate(FieldField< Field, Type > &res, const FieldField< Field, Type > &f)
Field< DType > & diag()
Definition: LduMatrix.C:190
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:76
void diag(pointPatchField< vector > &, const pointPatchField< tensor > &)
Field< LUType > & lower()
Definition: LduMatrix.C:225
volScalarField sf(fieldObject, mesh)
tmp< Field< Type > > faceH(const Field< Type > &) const
Field< LUType > & upper()
Definition: LduMatrix.C:202
Field< Type > & source()
Definition: LduMatrix.C:248
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
iterator begin()
Return an iterator to begin traversing the UList.
tmp< Field< Type > > H(const Field< Type > &) const
bool diagonal() const
Definition: LduMatrix.H:577
void operator-=(const LduMatrix< Type, DType, LUType > &)
const volScalarField & psi
Definition: createFields.H:24
label size() const
Return the number of elements in the UList.
Definition: UListI.H:299
void operator=(const LduMatrix< Type, DType, LUType > &)
errorManip< error > abort(error &err)
Definition: errorManip.H:131
#define FatalErrorIn(functionName)
Report an error message using Foam::FatalError.
Definition: error.H:314
Traits class for primitives.
Definition: pTraits.H:50
error FatalError
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:60
void cmptMag(FieldField< Field, Type > &cf, const FieldField< Field, Type > &f)
void sumMagOffDiag(Field< LUType > &sumOff) const
void operator*=(const scalarField &)
LduMatrix is a general matrix class in which the coefficients are stored as three arrays...
Definition: LduMatrix.H:69
A class for managing temporary objects.
Definition: PtrList.H:118