Matrix.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2026 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 "Matrix.H"
27 #include "MatrixSpace.H"
28 
29 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
30 
31 template<class Form, class Type>
33 {
34  if (mRows_ && nCols_)
35  {
36  v_ = new Type[size()];
37  }
38 }
39 
40 
41 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
42 
43 template<class Form, class Type>
45 :
46  mRows_(m),
47  nCols_(n),
48  v_(nullptr)
49 {
50  if (mRows_ < 0 || nCols_ < 0)
51  {
53  << "Incorrect m, n " << mRows_ << ", " << nCols_
54  << abort(FatalError);
55  }
56 
57  allocate();
58 }
59 
60 
61 template<class Form, class Type>
63 :
64  mRows_(m),
65  nCols_(n),
66  v_(nullptr)
67 {
68  if (mRows_ < 0 || nCols_ < 0)
69  {
71  << "Incorrect m, n " << mRows_ << ", " << nCols_
72  << abort(FatalError);
73  }
74 
75  allocate();
76 
77  if (v_)
78  {
79  const label mn = size();
80  for (label i=0; i<mn; i++)
81  {
82  v_[i] = Zero;
83  }
84  }
85 }
86 
87 
88 template<class Form, class Type>
89 Foam::Matrix<Form, Type>::Matrix(const label m, const label n, const Type& s)
90 :
91  mRows_(m),
92  nCols_(n),
93  v_(nullptr)
94 {
95  if (mRows_ < 0 || nCols_ < 0)
96  {
98  << "Incorrect m, n " << mRows_ << ", " << nCols_
99  << abort(FatalError);
100  }
101 
102  allocate();
103 
104  if (v_)
105  {
106  const label mn = size();
107  for (label i=0; i<mn; i++)
108  {
109  v_[i] = s;
110  }
111  }
112 }
113 
114 
115 template<class Form, class Type>
116 template<class InputIterator>
118 (
119  const label m,
120  const label n,
121  InputIterator first,
122  InputIterator last
123 )
124 :
125  mRows_(m),
126  nCols_(n),
127  v_(nullptr)
128 {
129  if (mRows_ < 0 || nCols_ < 0)
130  {
132  << "Incorrect m, n " << mRows_ << ", " << nCols_
133  << abort(FatalError);
134  }
135 
136  if (std::distance(first, last) != mRows_*nCols_)
137  {
139  << "Number of values provided " << std::distance(first, last)
140  << " is not the same as the number of matrix elements "
141  << mRows_*nCols_
143  }
144 
145  allocate();
146 
147  if (v_)
148  {
149  const label mn = size();
150  InputIterator iter = first;
151  for (label i=0; i<mn; i++)
152  {
153  v_[i] = *iter;
154  ++iter;
155  }
156  }
157 }
158 
159 
160 template<class Form, class Type>
162 (
163  const label m,
164  const label n,
165  std::initializer_list<Type> lst
166 )
167 :
168  Matrix(m, n, lst.begin(), lst.end())
169 {}
170 
171 
172 template<class Form, class Type>
174 (
175  std::initializer_list<std::initializer_list<Type>> lstLst
176 )
177 :
178  mRows_(lstLst.size()),
179  nCols_(lstLst.begin()->size())
180 {
181  allocate();
182 
183  label rowi = 0;
184  label i = 0;
185 
186  for (const std::initializer_list<Type>& lst : lstLst)
187  {
188  if (label(lst.size()) != nCols_)
189  {
191  << "Number of columns in row " << rowi
192  << " is not equal to " << nCols_
193  << abort(FatalError);
194  }
195 
196  for (const Type& v : lst)
197  {
198  v_[i++] = v;
199  }
200 
201  rowi++;
202  }
203 }
204 
205 
206 template<class Form, class Type>
208 :
209  mRows_(M.mRows_),
210  nCols_(M.nCols_),
211  v_(nullptr)
212 {
213  if (M.v_)
214  {
215  allocate();
216 
217  const label mn = size();
218  for (label i=0; i<mn; i++)
219  {
220  v_[i] = M.v_[i];
221  }
222  }
223 }
224 
225 
226 template<class Form, class Type>
227 template<class Form2>
229 :
230  mRows_(M.m()),
231  nCols_(M.n()),
232  v_(nullptr)
233 {
234  if (M.v())
235  {
236  allocate();
237 
238  const label mn = size();
239  for (label i=0; i<mn; i++)
240  {
241  v_[i] = M.v()[i];
242  }
243  }
244 }
245 
246 
247 template<class Form, class Type>
248 template<class MatrixType>
250 (
252 )
253 :
254  mRows_(Mb.m()),
255  nCols_(Mb.n())
256 {
257  allocate();
258 
259  for (label i=0; i<mRows_; i++)
260  {
261  for (label j=0; j<nCols_; j++)
262  {
263  (*this)(i,j) = Mb(i,j);
264  }
265  }
266 }
267 
268 
269 template<class Form, class Type>
270 template<class MatrixType>
272 (
273  const MatrixBlock<MatrixType>& Mb
274 )
275 :
276  mRows_(Mb.m()),
277  nCols_(Mb.n())
278 {
279  allocate();
280 
281  for (label i=0; i<mRows_; i++)
282  {
283  for (label j=0; j<nCols_; j++)
284  {
285  (*this)(i,j) = Mb(i,j);
286  }
287  }
288 }
289 
290 
291 template<class Form, class Type>
292 template<class MSForm, Foam::direction Mrows, Foam::direction Ncols>
294 (
296 )
297 :
298  mRows_(Mrows),
299  nCols_(Ncols)
300 {
301  allocate();
302 
303  for (label i=0; i<mRows_; i++)
304  {
305  for (label j=0; j<nCols_; j++)
306  {
307  (*this)(i,j) = Ms(i,j);
308  }
309  }
310 }
311 
312 
313 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
314 
315 template<class Form, class Type>
317 {
318  if (v_)
319  {
320  delete[] v_;
321  }
322 }
323 
324 
325 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
326 
327 template<class Form, class Type>
329 {
330  if (v_)
331  {
332  delete[] v_;
333  v_ = nullptr;
334  }
335 
336  mRows_ = 0;
337  nCols_ = 0;
338 }
339 
340 
341 template<class Form, class Type>
343 {
344  clear();
345 
346  mRows_ = M.mRows_;
347  M.mRows_ = 0;
348 
349  nCols_ = M.nCols_;
350  M.nCols_ = 0;
351 
352  v_ = M.v_;
353  M.v_ = nullptr;
354 }
355 
356 
357 template<class Form, class Type>
359 {
360  mType newMatrix(m, n, Zero);
361 
362  label minM = min(m, mRows_);
363  label minN = min(n, nCols_);
364 
365  for (label i=0; i<minM; i++)
366  {
367  for (label j=0; j<minN; j++)
368  {
369  newMatrix(i, j) = (*this)(i, j);
370  }
371  }
372 
373  transfer(newMatrix);
374 }
375 
376 
377 template<class Form, class Type>
379 {
380  const Matrix<Form, Type>& A = *this;
381  Form At(n(), m());
382 
383  for (label i=0; i<m(); i++)
384  {
385  for (label j=0; j<n(); j++)
386  {
387  At(j, i) = A(i, j);
388  }
389  }
390 
391  return At;
392 }
393 
394 
395 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
396 
397 template<class Form, class Type>
399 {
400  if (this == &M)
401  {
403  << "Attempted assignment to self"
404  << abort(FatalError);
405  }
406 
407  if (mRows_ != M.mRows_ || nCols_ != M.nCols_)
408  {
409  clear();
410  mRows_ = M.mRows_;
411  nCols_ = M.nCols_;
412  allocate();
413  }
414 
415  if (v_)
416  {
417  const label mn = size();
418  for (label i=0; i<mn; i++)
419  {
420  v_[i] = M.v_[i];
421  }
422  }
423 }
424 
425 
426 template<class Form, class Type>
427 template<class MatrixType>
429 (
431 )
432 {
433  for (label i=0; i<mRows_; i++)
434  {
435  for (label j=0; j<nCols_; j++)
436  {
437  (*this)(i,j) = Mb(i,j);
438  }
439  }
440 }
441 
442 
443 template<class Form, class Type>
444 template<class MatrixType>
446 (
447  const MatrixBlock<MatrixType>& Mb
448 )
449 {
450  for (label i=0; i<mRows_; i++)
451  {
452  for (label j=0; j<nCols_; j++)
453  {
454  (*this)(i,j) = Mb(i,j);
455  }
456  }
457 }
458 
459 
460 template<class Form, class Type>
462 {
463  if (v_)
464  {
465  const label mn = size();
466  for (label i=0; i<mn; i++)
467  {
468  v_[i] = s;
469  }
470  }
471 }
472 
473 
474 template<class Form, class Type>
476 {
477  if (v_)
478  {
479  const label mn = size();
480  for (label i=0; i<mn; i++)
481  {
482  v_[i] = Zero;
483  }
484  }
485 }
486 
487 
488 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
489 
490 template<class Form, class Type>
491 const Type& Foam::max(const Matrix<Form, Type>& M)
492 {
493  const label mn = M.size();
494 
495  if (mn)
496  {
497  label curMaxI = 0;
498  const Type* Mv = M.v();
499 
500  for (label i=1; i<mn; i++)
501  {
502  if (Mv[i] > Mv[curMaxI])
503  {
504  curMaxI = i;
505  }
506  }
507 
508  return Mv[curMaxI];
509  }
510  else
511  {
513  << "Matrix is empty"
514  << abort(FatalError);
515 
516  // Return in error to keep compiler happy
517  return M(0, 0);
518  }
519 }
520 
521 
522 template<class Form, class Type>
523 const Type& Foam::min(const Matrix<Form, Type>& M)
524 {
525  const label mn = M.size();
526 
527  if (mn)
528  {
529  label curMinI = 0;
530  const Type* Mv = M.v();
531 
532  for (label i=1; i<mn; i++)
533  {
534  if (Mv[i] < Mv[curMinI])
535  {
536  curMinI = i;
537  }
538  }
539 
540  return Mv[curMinI];
541  }
542  else
543  {
545  << "Matrix is empty"
546  << abort(FatalError);
547 
548  // Return in error to keep compiler happy
549  return M(0, 0);
550  }
551 }
552 
553 
554 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
555 
556 template<class Form, class Type>
558 {
559  Form nM(M.m(), M.n());
560 
561  if (M.m() && M.n())
562  {
563  Type* nMv = nM.v();
564  const Type* Mv = M.v();
565 
566  const label mn = M.size();
567  for (label i=0; i<mn; i++)
568  {
569  nMv[i] = -Mv[i];
570  }
571  }
572 
573  return nM;
574 }
575 
576 
577 template<class Form, class Type>
579 {
580  if (A.m() != B.m())
581  {
583  << "Attempt to add matrices with different numbers of rows: "
584  << A.m() << ", " << B.m()
585  << abort(FatalError);
586  }
587 
588  if (A.n() != B.n())
589  {
591  << "Attempt to add matrices with different numbers of columns: "
592  << A.n() << ", " << B.n()
593  << abort(FatalError);
594  }
595 
596  Form AB(A.m(), A.n());
597 
598  Type* ABv = AB.v();
599  const Type* Av = A.v();
600  const Type* Bv = B.v();
601 
602  const label mn = A.size();
603  for (label i=0; i<mn; i++)
604  {
605  ABv[i] = Av[i] + Bv[i];
606  }
607 
608  return AB;
609 }
610 
611 
612 template<class Form, class Type>
614 {
615  if (A.m() != B.m())
616  {
618  << "Attempt to add matrices with different numbers of rows: "
619  << A.m() << ", " << B.m()
620  << abort(FatalError);
621  }
622 
623  if (A.n() != B.n())
624  {
626  << "Attempt to add matrices with different numbers of columns: "
627  << A.n() << ", " << B.n()
628  << abort(FatalError);
629  }
630 
631  Form AB(A.m(), A.n());
632 
633  Type* ABv = AB.v();
634  const Type* Av = A.v();
635  const Type* Bv = B.v();
636 
637  const label mn = A.size();
638  for (label i=0; i<mn; i++)
639  {
640  ABv[i] = Av[i] - Bv[i];
641  }
642 
643  return AB;
644 }
645 
646 
647 template<class Form, class Type>
648 Form Foam::operator*(const scalar s, const Matrix<Form, Type>& M)
649 {
650  Form sM(M.m(), M.n());
651 
652  if (M.m() && M.n())
653  {
654  Type* sMv = sM.v();
655  const Type* Mv = M.v();
656 
657  const label mn = M.size();
658  for (label i=0; i<mn; i++)
659  {
660  sMv[i] = s*Mv[i];
661  }
662  }
663 
664  return sM;
665 }
666 
667 
668 template<class Form, class Type>
669 Form Foam::operator*(const Matrix<Form, Type>& M, const scalar s)
670 {
671  Form sM(M.m(), M.n());
672 
673  if (M.m() && M.n())
674  {
675  Type* sMv = sM.v();
676  const Type* Mv = M.v();
677 
678  const label mn = M.size();
679  for (label i=0; i<mn; i++)
680  {
681  sMv[i] = Mv[i]*s;
682  }
683  }
684 
685  return sM;
686 }
687 
688 
689 template<class Form, class Type>
690 Form Foam::operator/(const Matrix<Form, Type>& M, const scalar s)
691 {
692  Form sM(M.m(), M.n());
693 
694  if (M.m() && M.n())
695  {
696  Type* sMv = sM.v();
697  const Type* Mv = M.v();
698 
699  const label mn = M.size();
700  for (label i=0; i<mn; i++)
701  {
702  sMv[i] = Mv[i]/s;
703  }
704  }
705 
706  return sM;
707 }
708 
709 
710 template<class Form1, class Form2, class Type>
712 Foam::operator*
713 (
714  const Matrix<Form1, Type>& A,
715  const Matrix<Form2, Type>& B
716 )
717 {
718  if (A.n() != B.m())
719  {
721  << "Attempt to multiply incompatible matrices:" << nl
722  << "Matrix A : " << A.m() << " x " << A.n() << nl
723  << "Matrix B : " << B.m() << " x " << B.n() << nl
724  << "In order to multiply matrices, columns of A must equal "
725  << "rows of B"
726  << abort(FatalError);
727  }
728 
730  (
731  A.m(),
732  B.n(),
733  Zero
734  );
735 
736  for (label i=0; i<AB.m(); i++)
737  {
738  for (label j=0; j<AB.n(); j++)
739  {
740  for (label k=0; k<B.m(); k++)
741  {
742  AB(i, j) += A(i, k)*B(k, j);
743  }
744  }
745  }
746 
747  return AB;
748 }
749 
750 
751 template<class Form, class Type>
752 inline Foam::tmp<Foam::Field<Type>> Foam::operator*
753 (
754  const Matrix<Form, Type>& M,
755  const Field<Type>& f
756 )
757 {
758  if (M.n() != f.size())
759  {
761  << "Attempt to multiply incompatible matrix and field:" << nl
762  << "Matrix : " << M.m() << " x " << M.n() << nl
763  << "Field : " << f.size() << " rows" << nl
764  << "In order to multiply a matrix M and field f, "
765  "columns of M must equal rows of f"
766  << abort(FatalError);
767  }
768 
769  tmp<Field<Type>> tMf(new Field<Type>(M.m(), Zero));
770  Field<Type>& Mf = tMf.ref();
771 
772  for (label i=0; i<M.m(); i++)
773  {
774  for (label j=0; j<M.n(); j++)
775  {
776  Mf[i] += M(i, j)*f[j];
777  }
778  }
779 
780  return tMf;
781 }
782 
783 
784 // * * * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * //
785 
786 #include "MatrixIO.C"
787 
788 // ************************************************************************* //
label k
#define M(I)
label n
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
A templated block of an (m x n) matrix of type <MatrixType>.
Definition: MatrixBlock.H:116
label n() const
Return the number of columns in the block.
Definition: MatrixBlockI.H:114
label m() const
Return the number of rows in the block.
Definition: MatrixBlockI.H:107
Templated matrix space.
Definition: MatrixSpace.H:58
A templated (m x n) matrix of objects of <T>.
Definition: Matrix.H:83
~Matrix()
Destructor.
Definition: Matrix.C:316
Matrix()
Null constructor.
Definition: MatrixI.H:31
label size() const
Return the number of elements in matrix (m*n)
Definition: MatrixI.H:71
const Type * v() const
Return element vector of the constant Matrix.
Definition: MatrixI.H:118
void operator=(const mType &)
Assignment operator. Takes linear time.
Definition: Matrix.C:398
void transfer(mType &)
Transfer the contents of the argument Matrix into this Matrix.
Definition: Matrix.C:342
Form T() const
Return the transpose of the matrix.
Definition: Matrix.C:378
void setSize(const label m, const label n)
Resize the matrix preserving the elements.
Definition: Matrix.C:358
void clear()
Clear the Matrix, i.e. set sizes to zero.
Definition: Matrix.C:328
A class for managing temporary objects.
Definition: tmp.H:55
Abstract template class to provide the form resulting from.
Definition: products.H:48
A class representing the concept of 0 used to avoid unnecessary manipulations for objects that are kn...
Definition: zero.H:50
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(lagrangian::Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), lagrangian::cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
tUEqn clear()
static const coefficient B("B", dimless, 18.678)
static const coefficient A("A", dimPressure, 611.21)
static const zero Zero
Definition: zero.H:97
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
errorManip< error > abort(error &err)
Definition: errorManip.H:131
tmp< DimensionedField< Type, GeoMesh, Field > > operator/(const DimensionedField< Type, GeoMesh, PrimitiveField1 > &df1, const DimensionedField< scalar, GeoMesh, PrimitiveField2 > &df2)
tmp< DimensionedField< typename typeOfSum< Type1, Type2 >::type, GeoMesh, Field > > operator+(const DimensionedField< Type1, GeoMesh, PrimitiveField1 > &df1, const DimensionedField< Type2, GeoMesh, PrimitiveField2 > &df2)
tmp< DimensionedField< Type, GeoMesh, Field > > operator*(const DimensionedField< Type, GeoMesh, PrimitiveField1 > &df1, const DimensionedField< scalar, GeoMesh, PrimitiveField2 > &df2)
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
tmp< DimensionedField< Type, GeoMesh, Field > > operator-(const DimensionedField< Type, GeoMesh, PrimitiveField > &df1)
dimensioned< Type > min(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
error FatalError
static const char nl
Definition: Ostream.H:297
dimensioned< Type > max(const DimensionedField< Type, GeoMesh, PrimitiveField > &df)
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488
labelList f(nPoints)