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-2025 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;
186  (
187  typename std::initializer_list<std::initializer_list<Type>>,
188  lstLst,
189  rowIter
190  )
191  {
192  if (label(rowIter->size()) != nCols_)
193  {
195  << "Number of columns in row " << rowi
196  << " is not equal to " << nCols_
197  << abort(FatalError);
198  }
199 
201  (
202  typename std::initializer_list<Type>,
203  *rowIter,
204  colIter
205  )
206  {
207  v_[i++] = *colIter;
208  }
209 
210  rowi++;
211  }
212 }
213 
214 
215 template<class Form, class Type>
217 :
218  mRows_(M.mRows_),
219  nCols_(M.nCols_),
220  v_(nullptr)
221 {
222  if (M.v_)
223  {
224  allocate();
225 
226  const label mn = size();
227  for (label i=0; i<mn; i++)
228  {
229  v_[i] = M.v_[i];
230  }
231  }
232 }
233 
234 
235 template<class Form, class Type>
236 template<class Form2>
238 :
239  mRows_(M.m()),
240  nCols_(M.n()),
241  v_(nullptr)
242 {
243  if (M.v())
244  {
245  allocate();
246 
247  const label mn = size();
248  for (label i=0; i<mn; i++)
249  {
250  v_[i] = M.v()[i];
251  }
252  }
253 }
254 
255 
256 template<class Form, class Type>
257 template<class MatrixType>
259 (
261 )
262 :
263  mRows_(Mb.m()),
264  nCols_(Mb.n())
265 {
266  allocate();
267 
268  for (label i=0; i<mRows_; i++)
269  {
270  for (label j=0; j<nCols_; j++)
271  {
272  (*this)(i,j) = Mb(i,j);
273  }
274  }
275 }
276 
277 
278 template<class Form, class Type>
279 template<class MatrixType>
281 (
282  const MatrixBlock<MatrixType>& Mb
283 )
284 :
285  mRows_(Mb.m()),
286  nCols_(Mb.n())
287 {
288  allocate();
289 
290  for (label i=0; i<mRows_; i++)
291  {
292  for (label j=0; j<nCols_; j++)
293  {
294  (*this)(i,j) = Mb(i,j);
295  }
296  }
297 }
298 
299 
300 template<class Form, class Type>
301 template<class MSForm, Foam::direction Mrows, Foam::direction Ncols>
303 (
305 )
306 :
307  mRows_(Mrows),
308  nCols_(Ncols)
309 {
310  allocate();
311 
312  for (label i=0; i<mRows_; i++)
313  {
314  for (label j=0; j<nCols_; j++)
315  {
316  (*this)(i,j) = Ms(i,j);
317  }
318  }
319 }
320 
321 
322 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
323 
324 template<class Form, class Type>
326 {
327  if (v_)
328  {
329  delete[] v_;
330  }
331 }
332 
333 
334 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
335 
336 template<class Form, class Type>
338 {
339  if (v_)
340  {
341  delete[] v_;
342  v_ = nullptr;
343  }
344 
345  mRows_ = 0;
346  nCols_ = 0;
347 }
348 
349 
350 template<class Form, class Type>
352 {
353  clear();
354 
355  mRows_ = M.mRows_;
356  M.mRows_ = 0;
357 
358  nCols_ = M.nCols_;
359  M.nCols_ = 0;
360 
361  v_ = M.v_;
362  M.v_ = nullptr;
363 }
364 
365 
366 template<class Form, class Type>
368 {
369  mType newMatrix(m, n, Zero);
370 
371  label minM = min(m, mRows_);
372  label minN = min(n, nCols_);
373 
374  for (label i=0; i<minM; i++)
375  {
376  for (label j=0; j<minN; j++)
377  {
378  newMatrix(i, j) = (*this)(i, j);
379  }
380  }
381 
382  transfer(newMatrix);
383 }
384 
385 
386 template<class Form, class Type>
388 {
389  const Matrix<Form, Type>& A = *this;
390  Form At(n(), m());
391 
392  for (label i=0; i<m(); i++)
393  {
394  for (label j=0; j<n(); j++)
395  {
396  At(j, i) = A(i, j);
397  }
398  }
399 
400  return At;
401 }
402 
403 
404 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
405 
406 template<class Form, class Type>
408 {
409  if (this == &M)
410  {
412  << "Attempted assignment to self"
413  << abort(FatalError);
414  }
415 
416  if (mRows_ != M.mRows_ || nCols_ != M.nCols_)
417  {
418  clear();
419  mRows_ = M.mRows_;
420  nCols_ = M.nCols_;
421  allocate();
422  }
423 
424  if (v_)
425  {
426  const label mn = size();
427  for (label i=0; i<mn; i++)
428  {
429  v_[i] = M.v_[i];
430  }
431  }
432 }
433 
434 
435 template<class Form, class Type>
436 template<class MatrixType>
438 (
440 )
441 {
442  for (label i=0; i<mRows_; i++)
443  {
444  for (label j=0; j<nCols_; j++)
445  {
446  (*this)(i,j) = Mb(i,j);
447  }
448  }
449 }
450 
451 
452 template<class Form, class Type>
453 template<class MatrixType>
455 (
456  const MatrixBlock<MatrixType>& Mb
457 )
458 {
459  for (label i=0; i<mRows_; i++)
460  {
461  for (label j=0; j<nCols_; j++)
462  {
463  (*this)(i,j) = Mb(i,j);
464  }
465  }
466 }
467 
468 
469 template<class Form, class Type>
471 {
472  if (v_)
473  {
474  const label mn = size();
475  for (label i=0; i<mn; i++)
476  {
477  v_[i] = s;
478  }
479  }
480 }
481 
482 
483 template<class Form, class Type>
485 {
486  if (v_)
487  {
488  const label mn = size();
489  for (label i=0; i<mn; i++)
490  {
491  v_[i] = Zero;
492  }
493  }
494 }
495 
496 
497 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
498 
499 template<class Form, class Type>
500 const Type& Foam::max(const Matrix<Form, Type>& M)
501 {
502  const label mn = M.size();
503 
504  if (mn)
505  {
506  label curMaxI = 0;
507  const Type* Mv = M.v();
508 
509  for (label i=1; i<mn; i++)
510  {
511  if (Mv[i] > Mv[curMaxI])
512  {
513  curMaxI = i;
514  }
515  }
516 
517  return Mv[curMaxI];
518  }
519  else
520  {
522  << "Matrix is empty"
523  << abort(FatalError);
524 
525  // Return in error to keep compiler happy
526  return M(0, 0);
527  }
528 }
529 
530 
531 template<class Form, class Type>
532 const Type& Foam::min(const Matrix<Form, Type>& M)
533 {
534  const label mn = M.size();
535 
536  if (mn)
537  {
538  label curMinI = 0;
539  const Type* Mv = M.v();
540 
541  for (label i=1; i<mn; i++)
542  {
543  if (Mv[i] < Mv[curMinI])
544  {
545  curMinI = i;
546  }
547  }
548 
549  return Mv[curMinI];
550  }
551  else
552  {
554  << "Matrix is empty"
555  << abort(FatalError);
556 
557  // Return in error to keep compiler happy
558  return M(0, 0);
559  }
560 }
561 
562 
563 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
564 
565 template<class Form, class Type>
567 {
568  Form nM(M.m(), M.n());
569 
570  if (M.m() && M.n())
571  {
572  Type* nMv = nM.v();
573  const Type* Mv = M.v();
574 
575  const label mn = M.size();
576  for (label i=0; i<mn; i++)
577  {
578  nMv[i] = -Mv[i];
579  }
580  }
581 
582  return nM;
583 }
584 
585 
586 template<class Form, class Type>
588 {
589  if (A.m() != B.m())
590  {
592  << "Attempt to add matrices with different numbers of rows: "
593  << A.m() << ", " << B.m()
594  << abort(FatalError);
595  }
596 
597  if (A.n() != B.n())
598  {
600  << "Attempt to add matrices with different numbers of columns: "
601  << A.n() << ", " << B.n()
602  << abort(FatalError);
603  }
604 
605  Form AB(A.m(), A.n());
606 
607  Type* ABv = AB.v();
608  const Type* Av = A.v();
609  const Type* Bv = B.v();
610 
611  const label mn = A.size();
612  for (label i=0; i<mn; i++)
613  {
614  ABv[i] = Av[i] + Bv[i];
615  }
616 
617  return AB;
618 }
619 
620 
621 template<class Form, class Type>
623 {
624  if (A.m() != B.m())
625  {
627  << "Attempt to add matrices with different numbers of rows: "
628  << A.m() << ", " << B.m()
629  << abort(FatalError);
630  }
631 
632  if (A.n() != B.n())
633  {
635  << "Attempt to add matrices with different numbers of columns: "
636  << A.n() << ", " << B.n()
637  << abort(FatalError);
638  }
639 
640  Form AB(A.m(), A.n());
641 
642  Type* ABv = AB.v();
643  const Type* Av = A.v();
644  const Type* Bv = B.v();
645 
646  const label mn = A.size();
647  for (label i=0; i<mn; i++)
648  {
649  ABv[i] = Av[i] - Bv[i];
650  }
651 
652  return AB;
653 }
654 
655 
656 template<class Form, class Type>
657 Form Foam::operator*(const scalar s, const Matrix<Form, Type>& M)
658 {
659  Form sM(M.m(), M.n());
660 
661  if (M.m() && M.n())
662  {
663  Type* sMv = sM.v();
664  const Type* Mv = M.v();
665 
666  const label mn = M.size();
667  for (label i=0; i<mn; i++)
668  {
669  sMv[i] = s*Mv[i];
670  }
671  }
672 
673  return sM;
674 }
675 
676 
677 template<class Form, class Type>
678 Form Foam::operator*(const Matrix<Form, Type>& M, const scalar s)
679 {
680  Form sM(M.m(), M.n());
681 
682  if (M.m() && M.n())
683  {
684  Type* sMv = sM.v();
685  const Type* Mv = M.v();
686 
687  const label mn = M.size();
688  for (label i=0; i<mn; i++)
689  {
690  sMv[i] = Mv[i]*s;
691  }
692  }
693 
694  return sM;
695 }
696 
697 
698 template<class Form, class Type>
699 Form Foam::operator/(const Matrix<Form, Type>& M, const scalar s)
700 {
701  Form sM(M.m(), M.n());
702 
703  if (M.m() && M.n())
704  {
705  Type* sMv = sM.v();
706  const Type* Mv = M.v();
707 
708  const label mn = M.size();
709  for (label i=0; i<mn; i++)
710  {
711  sMv[i] = Mv[i]/s;
712  }
713  }
714 
715  return sM;
716 }
717 
718 
719 template<class Form1, class Form2, class Type>
721 Foam::operator*
722 (
723  const Matrix<Form1, Type>& A,
724  const Matrix<Form2, Type>& B
725 )
726 {
727  if (A.n() != B.m())
728  {
730  << "Attempt to multiply incompatible matrices:" << nl
731  << "Matrix A : " << A.m() << " x " << A.n() << nl
732  << "Matrix B : " << B.m() << " x " << B.n() << nl
733  << "In order to multiply matrices, columns of A must equal "
734  << "rows of B"
735  << abort(FatalError);
736  }
737 
739  (
740  A.m(),
741  B.n(),
742  Zero
743  );
744 
745  for (label i=0; i<AB.m(); i++)
746  {
747  for (label j=0; j<AB.n(); j++)
748  {
749  for (label k=0; k<B.m(); k++)
750  {
751  AB(i, j) += A(i, k)*B(k, j);
752  }
753  }
754  }
755 
756  return AB;
757 }
758 
759 
760 template<class Form, class Type>
761 inline Foam::tmp<Foam::Field<Type>> Foam::operator*
762 (
763  const Matrix<Form, Type>& M,
764  const Field<Type>& f
765 )
766 {
767  if (M.n() != f.size())
768  {
770  << "Attempt to multiply incompatible matrix and field:" << nl
771  << "Matrix : " << M.m() << " x " << M.n() << nl
772  << "Field : " << f.size() << " rows" << nl
773  << "In order to multiply a matrix M and field f, "
774  "columns of M must equal rows of f"
775  << abort(FatalError);
776  }
777 
778  tmp<Field<Type>> tMf(new Field<Type>(M.m(), Zero));
779  Field<Type>& Mf = tMf.ref();
780 
781  for (label i=0; i<M.m(); i++)
782  {
783  for (label j=0; j<M.n(); j++)
784  {
785  Mf[i] += M(i, j)*f[j];
786  }
787  }
788 
789  return tMf;
790 }
791 
792 
793 // * * * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * //
794 
795 #include "MatrixIO.C"
796 
797 // ************************************************************************* //
label k
#define M(I)
label n
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:476
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
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:325
Matrix()
Null constructor.
Definition: MatrixI.H:31
label size() const
Return the number of elements in matrix (m*n)
Definition: MatrixI.H:71
void operator=(const mType &)
Assignment operator. Takes linear time.
Definition: Matrix.C:407
void transfer(mType &)
Transfer the contents of the argument Matrix into this Matrix.
Definition: Matrix.C:351
Form T() const
Return the transpose of the matrix.
Definition: Matrix.C:387
void setSize(const label m, const label n)
Resize the matrix preserving the elements.
Definition: Matrix.C:367
void clear()
Clear the Matrix, i.e. set sizes to zero.
Definition: Matrix.C:337
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
labelList first(const UList< labelPair > &p)
Definition: patchToPatch.C:39
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
tmp< fvMatrix< Type > > operator*(const volScalarField::Internal &, const fvMatrix< Type > &)
error FatalError
tmp< fvMatrix< Type > > operator+(const fvMatrix< Type > &, const fvMatrix< Type > &)
tmp< fvMatrix< Type > > operator-(const fvMatrix< Type > &)
static const char nl
Definition: Ostream.H:267
tmp< fvMatrix< Type > > operator/(const fvMatrix< Type > &, const volScalarField::Internal &)
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)