Matrix.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-2017 OpenFOAM Foundation
9  Copyright (C) 2019-2025 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 "Matrix.H"
30 #include <functional>
31 
32 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
33 
34 template<class Form, class Type>
35 template<class ListType>
37 (
38  const ListType& x
39 ) const
40 {
41  const Matrix<Form, Type>& mat = *this;
42 
43  #ifdef FULLDEBUG
44  if (mat.n() != x.size())
45  {
47  << "Attempt to multiply incompatible Matrix and Vector:" << nl
48  << "Matrix : (" << mat.m() << ", " << mat.n() << ')' << nl
49  << "Matrix columns != Vector size (" << x.size() << ')' << nl
50  << abort(FatalError);
51  }
52  #endif
53 
54  auto tresult = tmp<Field<Type>>::New(mat.m(), Foam::zero{});
55  auto& result = tresult.ref();
56 
57  for (label i = 0; i < mat.m(); ++i)
58  {
59  for (label j = 0; j < mat.n(); ++j)
60  {
61  result[i] += mat(i, j)*x[j];
62  }
63  }
64 
65  return tresult;
66 }
67 
68 
69 template<class Form, class Type>
70 template<class ListType>
72 (
73  const ListType& x
74 ) const
75 {
76  const Matrix<Form, Type>& mat = *this;
77 
78  #ifdef FULLDEBUG
79  if (mat.m() != x.size())
80  {
82  << "Attempt to multiply incompatible Matrix and Vector:" << nl
83  << "Matrix : (" << mat.m() << ", " << mat.n() << ')' << nl
84  << "Matrix rows != Vector size (" << x.size() << ')' << nl
85  << abort(FatalError);
86  }
87  #endif
88 
89  auto tresult = tmp<Field<Type>>::New(mat.n(), Foam::zero{});
90  auto& result = tresult.ref();
91 
92  for (label i = 0; i < mat.m(); ++i)
93  {
94  const Type& val = x[i];
95  for (label j = 0; j < mat.n(); ++j)
96  {
97  result[j] += val*mat(i, j);
98  }
99  }
100 
101  return tresult;
102 }
103 
104 
105 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
106 
107 template<class Form, class Type>
108 Foam::Matrix<Form, Type>::Matrix(const label m, const label n)
109 :
110  mRows_(m),
111  nCols_(n),
112  v_(nullptr)
113 {
114  checkSize();
115 
116  doAlloc();
117 }
118 
119 
120 template<class Form, class Type>
121 Foam::Matrix<Form, Type>::Matrix(const label m, const label n, Foam::zero)
122 :
123  mRows_(m),
124  nCols_(n),
125  v_(nullptr)
126 {
127  checkSize();
128 
129  doAlloc();
130 
131  std::fill_n(begin(), size(), Zero);
132 }
133 
134 
135 template<class Form, class Type>
136 Foam::Matrix<Form, Type>::Matrix(const label m, const label n, const Type& val)
137 :
138  mRows_(m),
139  nCols_(n),
140  v_(nullptr)
141 {
142  checkSize();
143 
144  doAlloc();
145 
146  std::fill_n(begin(), size(), val);
147 }
148 
149 
150 template<class Form, class Type>
152 :
153  mRows_(mat.mRows_),
154  nCols_(mat.nCols_),
155  v_(nullptr)
156 {
157  if (mat.cdata())
158  {
159  doAlloc();
161  std::copy(mat.cbegin(), mat.cend(), v_);
162  }
163 }
164 
165 
166 template<class Form, class Type>
167 Foam::Matrix<Form, Type>::Matrix(Matrix<Form, Type>&& mat)
168 :
169  mRows_(mat.mRows_),
170  nCols_(mat.nCols_),
171  v_(mat.v_)
172 {
173  mat.mRows_ = 0;
174  mat.nCols_ = 0;
175  mat.v_ = nullptr;
176 }
177 
178 
179 template<class Form, class Type>
180 template<class Form2>
182 :
183  mRows_(mat.m()),
184  nCols_(mat.n()),
185  v_(nullptr)
186 {
187  if (mat.cdata())
188  {
189  doAlloc();
190 
191  std::copy(mat.cbegin(), mat.cend(), v_);
192  }
193 }
194 
195 
196 template<class Form, class Type>
197 template<class MatrixType>
199 (
200  const ConstMatrixBlock<MatrixType>& Mb
201 )
202 :
203  mRows_(Mb.m()),
204  nCols_(Mb.n()),
205  v_(nullptr)
206 {
207  doAlloc();
208 
209  for (label i = 0; i < mRows_; ++i)
210  {
211  for (label j = 0; j < nCols_; ++j)
212  {
213  (*this)(i, j) = Mb(i,j);
214  }
215  }
216 }
217 
218 
219 template<class Form, class Type>
220 template<class MatrixType>
222 (
223  const MatrixBlock<MatrixType>& Mb
224 )
225 :
226  mRows_(Mb.m()),
227  nCols_(Mb.n()),
228  v_(nullptr)
229 {
230  doAlloc();
231 
232  for (label i = 0; i < mRows_; ++i)
233  {
234  for (label j = 0; j < nCols_; ++j)
235  {
236  (*this)(i, j) = Mb(i, j);
237  }
238  }
239 }
240 
241 
242 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
243 
244 template<class Form, class Type>
246 {
247  // Accurate alignment information?
248  ListPolicy::deallocate(this->v_, (mRows_*nCols_));
249 }
250 
251 
252 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
253 
254 template<class Form, class Type>
256 {
257  // Accurate alignment information?
258  ListPolicy::deallocate(this->v_, (mRows_*nCols_));
259 
260  v_ = nullptr;
261  mRows_ = 0;
262  nCols_ = 0;
263 }
264 
265 
266 template<class Form, class Type>
268 {
269  List<Type> list;
270 
271  const label len = size();
272 
273  if (v_ && len)
274  {
275  UList<Type> storage(v_, len);
276  list.swap(storage);
277 
278  v_ = nullptr;
279  }
280  clear();
281 
282  return list;
283 }
284 
285 
286 template<class Form, class Type>
288 {
289  if (this == &mat)
290  {
291  return; // Self-swap is a no-op
292  }
293 
294  std::swap(mRows_, mat.mRows_);
295  std::swap(nCols_, mat.nCols_);
296  std::swap(v_, mat.v_);
297 }
298 
299 
300 template<class Form, class Type>
302 {
303  if (this == &mat)
304  {
305  return; // Self-assignment is a no-op
306  }
307 
308  clear();
309 
310  mRows_ = mat.mRows_;
311  nCols_ = mat.nCols_;
312  v_ = mat.v_;
313 
314  mat.mRows_ = 0;
315  mat.nCols_ = 0;
316  mat.v_ = nullptr;
317 }
318 
319 
320 template<class Form, class Type>
321 void Foam::Matrix<Form, Type>::resize(const label m, const label n)
322 {
323  if (m == mRows_ && n == nCols_)
324  {
325  return;
326  }
327 
328  Matrix<Form, Type> newMatrix(m, n, Foam::zero{});
329 
330  const label mrow = Foam::min(m, mRows_);
331  const label ncol = Foam::min(n, nCols_);
332 
333  for (label i = 0; i < mrow; ++i)
334  {
335  for (label j = 0; j < ncol; ++j)
336  {
337  newMatrix(i, j) = (*this)(i, j);
338  }
339  }
340 
341  transfer(newMatrix);
342 }
343 
344 
345 template<class Form, class Type>
346 void Foam::Matrix<Form, Type>::resize_nocopy(const label mrow, const label ncol)
347 {
348  if (mrow == mRows_ && ncol == nCols_)
349  {
350  return;
351  }
352 
353  const label oldLen = (mRows_ * nCols_);
354 
355  const label newLen = (mrow * ncol);
356 
357  if (oldLen == newLen)
358  {
359  // Shallow resize is enough
360  mRows_ = mrow;
361  nCols_ = ncol;
362  }
363  else
364  {
365  this->clear();
366 
367  mRows_ = mrow;
368  nCols_ = ncol;
370  this->doAlloc();
371  }
372 }
373 
374 
375 template<class Form, class Type>
376 void Foam::Matrix<Form, Type>::round(const scalar tol)
377 {
378  for (Type& val : *this)
379  {
380  if (mag(val) < tol)
381  {
382  val = Zero;
383  }
384  }
385 }
386 
387 
388 template<class Form, class Type>
389 Form Foam::Matrix<Form, Type>::T() const
390 {
391  Form At(labelPair{n(), m()});
392 
393  for (label i = 0; i < m(); ++i)
394  {
395  for (label j = 0; j < n(); ++j)
396  {
397  At(j, i) = Detail::conj((*this)(i, j));
398  }
399  }
400 
401  return At;
402 }
403 
404 
405 template<class Form, class Type>
407 {
408  Form At(labelPair{n(), m()});
409 
410  for (label i = 0; i < m(); ++i)
411  {
412  for (label j = 0; j < n(); ++j)
413  {
414  At(j, i) = (*this)(i, j);
415  }
416  }
417 
418  return At;
419 }
420 
421 
422 template<class Form, class Type>
424 {
425  const label len = Foam::min(mRows_, nCols_);
426 
427  List<Type> result(len);
428 
429  for (label i=0; i < len; ++i)
430  {
431  result[i] = (*this)(i, i);
432  }
433 
434  return result;
435 }
436 
437 
438 template<class Form, class Type>
439 void Foam::Matrix<Form, Type>::diag(const UList<Type>& list)
440 {
441  const label len = Foam::min(mRows_, nCols_);
442 
443  #ifdef FULLDEBUG
444  if (list.size() != len)
445  {
447  << "List size (" << list.size()
448  << ") incompatible with Matrix diagonal" << abort(FatalError);
449  }
450  #endif
451 
452  for (label i=0; i < len; ++i)
453  {
454  (*this)(i, i) = list[i];
455  }
456 }
457 
458 
459 template<class Form, class Type>
461 {
462  const label len = Foam::min(mRows_, nCols_);
463 
464  Type val = Zero;
465 
466  for (label i=0; i < len; ++i)
467  {
468  val += (*this)(i, i);
469  }
471  return val;
472 }
473 
474 
475 template<class Form, class Type>
477 (
478  const label colIndex,
479  const bool noSqrt
480 ) const
481 {
482  scalar result(0);
483 
484  for (label i=0; i < mRows_; ++i)
485  {
486  result += magSqr((*this)(i, colIndex));
487  }
488 
489  return noSqrt ? result : Foam::sqrt(result);
490 }
491 
492 
493 template<class Form, class Type>
494 Foam::scalar Foam::Matrix<Form, Type>::norm(const bool noSqrt) const
495 {
496  scalar result(0);
497 
498  for (const Type& val : *this)
499  {
500  result += magSqr(val);
501  }
502 
503  return noSqrt ? result : Foam::sqrt(result);
504 }
505 
506 
507 template<class Form, class Type>
508 std::streamsize Foam::Matrix<Form, Type>::byteSize() const
509 {
510  if constexpr (!is_contiguous_v<Type>)
511  {
513  << "Invalid for non-contiguous data types"
515  }
516  return this->size_bytes();
517 }
518 
519 
520 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
521 
522 template<class Form, class Type>
524 {
525  if (this == &mat)
526  {
527  return; // Self-assignment is a no-op
528  }
529 
530  if (mRows_ != mat.mRows_ || nCols_ != mat.nCols_)
531  {
532  clear();
533  mRows_ = mat.mRows_;
534  nCols_ = mat.nCols_;
535  doAlloc();
536  }
537 
538  if (v_)
539  {
540  std::copy(mat.cbegin(), mat.cend(), v_);
541  }
542 }
543 
544 
545 template<class Form, class Type>
546 void Foam::Matrix<Form, Type>::operator=(Matrix<Form, Type>&& mat)
547 {
548  if (this != &mat)
549  {
550  // Self-assignment is a no-op
551  this->transfer(mat);
552  }
553 }
554 
555 
556 template<class Form, class Type>
557 template<class MatrixType>
559 (
560  const ConstMatrixBlock<MatrixType>& Mb
561 )
562 {
563  for (label i = 0; i < mRows_; ++i)
564  {
565  for (label j = 0; j < nCols_; ++j)
566  {
567  (*this)(i, j) = Mb(i, j);
568  }
569  }
570 }
571 
572 
573 template<class Form, class Type>
574 template<class MatrixType>
576 (
577  const MatrixBlock<MatrixType>& Mb
578 )
579 {
580  for (label i = 0; i < mRows_; ++i)
581  {
582  for (label j = 0; j < nCols_; ++j)
583  {
584  (*this)(i, j) = Mb(i, j);
585  }
586  }
587 }
588 
589 
590 template<class Form, class Type>
592 {
593  std::fill_n(begin(), size(), val);
594 }
595 
596 
597 template<class Form, class Type>
599 {
600  std::fill_n(begin(), size(), Zero);
601 }
602 
603 
604 template<class Form, class Type>
606 {
607  #ifdef FULLDEBUG
608  if (this == &other)
609  {
611  << "Attempted addition to self"
612  << abort(FatalError);
613  }
614 
615  if (m() != other.m() || n() != other.n())
616  {
618  << "Attempt to add matrices with different sizes: ("
619  << m() << ", " << n() << ") != ("
620  << other.m() << ", " << other.n() << ')' << nl
621  << abort(FatalError);
622  }
623  #endif
624 
625  auto iter2 = other.cbegin();
626  for (Type& val : *this)
627  {
628  val += *iter2;
629  ++iter2;
630  }
631 }
632 
633 
634 template<class Form, class Type>
635 void Foam::Matrix<Form, Type>::operator-=(const Matrix<Form, Type>& other)
636 {
637  #ifdef FULLDEBUG
638  if (this == &other)
639  {
641  << "Attempted subtraction from self"
642  << abort(FatalError);
643  }
644 
645  if (m() != other.m() || n() != other.n())
646  {
648  << "Attempt to subtract matrices with different sizes: ("
649  << m() << ", " << n() << ") != ("
650  << other.m() << ", " << other.n() << ')' << nl
651  << abort(FatalError);
652  }
653  #endif
654 
655  auto iter2 = other.cbegin();
656  for (Type& val : *this)
657  {
658  val -= *iter2;
659  ++iter2;
660  }
661 }
662 
663 
664 template<class Form, class Type>
665 void Foam::Matrix<Form, Type>::operator+=(const Type& s)
666 {
667  for (Type& val : *this)
668  {
669  val += s;
670  }
671 }
672 
673 
674 template<class Form, class Type>
675 void Foam::Matrix<Form, Type>::operator-=(const Type& s)
676 {
677  for (Type& val : *this)
678  {
679  val -= s;
680  }
681 }
682 
683 
684 template<class Form, class Type>
685 void Foam::Matrix<Form, Type>::operator*=(const Type& s)
686 {
687  for (Type& val : *this)
688  {
689  val *= s;
690  }
691 }
692 
693 
694 template<class Form, class Type>
695 void Foam::Matrix<Form, Type>::operator/=(const Type& s)
696 {
697  for (Type& val : *this)
698  {
699  val /= s;
700  }
701 }
702 
703 
704 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
705 
706 namespace Foam
707 {
709 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * //
710 
711 //- Find max value in Matrix
712 template<class Form, class Type>
713 const Type& max(const Matrix<Form, Type>& mat)
714 {
715  if (mat.empty())
716  {
718  << "Matrix is empty" << abort(FatalError);
719  }
720 
721  return *(std::max_element(mat.cbegin(), mat.cend()));
722 }
723 
725 //- Find min value in Matrix
726 template<class Form, class Type>
727 const Type& min(const Matrix<Form, Type>& mat)
728 {
729  if (mat.empty())
730  {
732  << "Matrix is empty" << abort(FatalError);
733  }
734 
735  return *(std::min_element(mat.cbegin(), mat.cend()));
736 }
737 
738 
739 //- Find the min/max values of Matrix
740 template<class Form, class Type>
742 {
743  MinMax<Type> result;
744 
745  for (const Type& val : mat)
746  {
747  result += val;
748  }
749 
750  return result;
751 }
752 
753 
754 
755 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
756 
757 //- Matrix negation
758 template<class Form, class Type>
759 Form operator-(const Matrix<Form, Type>& mat)
760 {
761  Form result(mat.sizes());
762 
764  (
765  mat.cbegin(),
766  mat.cend(),
767  result.begin(),
768  std::negate<Type>()
769  );
770 
771  return result;
772 }
773 
774 
775 //- Matrix addition. Returns Matrix of the same form as the first parameter.
776 template<class Form1, class Form2, class Type>
777 Form1 operator+
778 (
779  const Matrix<Form1, Type>& A,
780  const Matrix<Form2, Type>& B
781 )
782 {
783  #ifdef FULLDEBUG
784  if (A.m() != B.m() || A.n() != B.n())
785  {
787  << "Attempt to add matrices with different sizes: ("
788  << A.m() << ", " << A.n() << ") != ("
789  << B.m() << ", " << B.n() << ')' << nl
790  << abort(FatalError);
791  }
792  #endif
793 
794  Form1 result(A.sizes());
795 
797  (
798  A.cbegin(),
799  A.cend(),
800  B.cbegin(),
801  result.begin(),
802  std::plus<Type>()
803  );
804 
805  return result;
806 }
807 
808 
809 //- Matrix subtraction. Returns Matrix of the same form as the first parameter.
810 template<class Form1, class Form2, class Type>
811 Form1 operator-
812 (
813  const Matrix<Form1, Type>& A,
814  const Matrix<Form2, Type>& B
815 )
816 {
817  #ifdef FULLDEBUG
818  if (A.m() != B.m() || A.n() != B.n())
819  {
821  << "Attempt to subtract matrices with different sizes: ("
822  << A.m() << ", " << A.n() << ") != ("
823  << B.m() << ", " << B.n() << ')' << nl
824  << abort(FatalError);
825  }
826  #endif
827 
828  Form1 result(A.sizes());
829 
831  (
832  A.cbegin(),
833  A.cend(),
834  B.cbegin(),
835  result.begin(),
836  std::minus<Type>()
837  );
838 
839  return result;
840 }
841 
842 
843 //- Scalar multiplication of Matrix
844 template<class Form, class Type>
845 Form operator*(const Type& s, const Matrix<Form, Type>& mat)
846 {
847  Form result(mat.sizes());
848 
850  (
851  mat.cbegin(),
852  mat.cend(),
853  result.begin(),
854  [&](const Type& val) { return s * val; }
855  );
856 
857  return result;
858 }
859 
860 
861 //- Scalar multiplication of Matrix
862 template<class Form, class Type>
863 Form operator*(const Matrix<Form, Type>& mat, const Type& s)
864 {
865  return s*mat;
866 }
867 
868 
869 //- Scalar addition of Matrix
870 template<class Form, class Type>
871 Form operator+(const Type& s, const Matrix<Form, Type>& mat)
872 {
873  Form result(mat.sizes());
874 
876  (
877  mat.cbegin(),
878  mat.cend(),
879  result.begin(),
880  [&](const Type& val) { return s + val; }
881  );
883  return result;
884 }
885 
886 
887 //- Scalar addition of Matrix
888 template<class Form, class Type>
889 Form operator+(const Matrix<Form, Type>& mat, const Type& s)
890 {
891  return s + mat;
892 }
893 
894 
895 //- Scalar subtraction of Matrix
896 template<class Form, class Type>
897 Form operator-(const Type& s, const Matrix<Form, Type>& mat)
898 {
899  Form result(mat.sizes());
900 
902  (
903  mat.cbegin(),
904  mat.end(),
905  result.begin(),
906  [&](const Type& val) { return s - val; }
907  );
908 
909  return result;
910 }
911 
913 //- Scalar subtraction of Matrix
914 template<class Form, class Type>
915 Form operator-(const Matrix<Form, Type>& mat, const Type& s)
916 {
917  Form result(mat.sizes());
918 
920  (
921  mat.cbegin(),
922  mat.end(),
923  result.begin(),
924  [&](const Type& val) { return val - s; }
925  );
926 
927  return result;
928 }
929 
930 
931 //- Scalar division of Matrix
932 template<class Form, class Type>
933 Form operator/(const Matrix<Form, Type>& mat, const Type& s)
934 {
935  Form result(mat.sizes());
936 
938  (
939  mat.cbegin(),
940  mat.end(),
941  result.begin(),
942  [&](const Type& val) { return val / s; }
943  );
944 
945  return result;
946 }
947 
948 
949 //- Matrix-Matrix multiplication using ikj-algorithm
950 template<class Form1, class Form2, class Type>
952 operator*
953 (
954  const Matrix<Form1, Type>& A,
955  const Matrix<Form2, Type>& B
956 )
957 {
958  #ifdef FULLDEBUG
959  if (A.n() != B.m())
960  {
962  << "Attempt to multiply incompatible matrices:" << nl
963  << "Matrix A : (" << A.m() << ", " << A.n() << ')' << nl
964  << "Matrix B : (" << B.m() << ", " << B.n() << ')' << nl
965  << "The columns of A must equal rows of B"
966  << abort(FatalError);
967  }
968  #endif
969 
971  (
972  A.m(),
973  B.n(),
975  );
976 
977  for (label i = 0; i < AB.m(); ++i)
978  {
979  for (label k = 0; k < B.m(); ++k)
980  {
981  for (label j = 0; j < AB.n(); ++j)
982  {
983  AB(i, j) += A(i, k)*B(k, j);
984  }
985  }
986  }
987 
988  return AB;
989 }
990 
991 
992 //- Implicit inner product of Matrix-Matrix, equivalent to A.T()*B
993 template<class Form1, class Form2, class Type>
995 operator&
996 (
997  const Matrix<Form1, Type>& AT,
998  const Matrix<Form2, Type>& B
999 )
1000 {
1001  #ifdef FULLDEBUG
1002  if (AT.m() != B.m())
1003  {
1005  << "Attempt to multiply incompatible matrices:" << nl
1006  << "Matrix A : (" << AT.m() << ", " << AT.n() << ')' << nl
1007  << "Matrix B : (" << B.m() << ", " << B.n() << ')' << nl
1008  << "The rows of A must equal rows of B"
1009  << abort(FatalError);
1010  }
1011  #endif
1012 
1014  (
1015  AT.n(),
1016  B.n(),
1017  Zero
1018  );
1020  for (label k = 0; k < B.m(); ++k)
1021  {
1022  for (label i = 0; i < AB.m(); ++i)
1023  {
1024  for (label j = 0; j < AB.n(); ++j)
1025  {
1026  AB(i, j) += Detail::conj(AT(k, i))*B(k, j);
1027  }
1028  }
1029  }
1030 
1031  return AB;
1032 }
1033 
1034 
1035 //- Implicit outer product of Matrix-Matrix, equivalent to A*B.T()
1036 template<class Form1, class Form2, class Type>
1038 operator^
1039 (
1040  const Matrix<Form1, Type>& A,
1041  const Matrix<Form2, Type>& BT
1042 )
1043 {
1044  #ifdef FULLDEBUG
1045  if (A.n() != BT.n())
1046  {
1048  << "Attempt to multiply incompatible matrices:" << nl
1049  << "Matrix A : (" << A.m() << ", " << A.n() << ')' << nl
1050  << "Matrix B : (" << BT.m() << ", " << BT.n() << ')' << nl
1051  << "The columns of A must equal columns of B"
1052  << abort(FatalError);
1053  }
1054  #endif
1055 
1057  (
1058  A.m(),
1059  BT.m(),
1060  Zero
1061  );
1062 
1063  for (label i = 0; i < AB.m(); ++i)
1064  {
1065  for (label j = 0; j < AB.n(); ++j)
1066  {
1067  for (label k = 0; k < BT.n(); ++k)
1068  {
1069  AB(i, j) += A(i, k)*Detail::conj(BT(j, k));
1070  }
1071  }
1072  }
1073 
1074  return AB;
1075 }
1076 
1077 
1078 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1079 
1080 } // End namespace Foam
1081 
1082 // ************************************************************************* //
void swap(UList< T > &list) noexcept
Swap content with another UList of the same type in constant time.
Definition: UListI.H:499
Abstract template class to provide the form resulting from the inner-product of two forms...
Definition: products.H:47
void resize(const label m, const label n)
Change Matrix dimensions, preserving the elements.
Definition: Matrix.C:314
type
Types of root.
Definition: Roots.H:52
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
constexpr Matrix() noexcept
Default construct (empty matrix)
Definition: MatrixI.H:43
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:600
Form T() const
Return conjugate transpose of Matrix.
Definition: Matrix.C:382
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
A min/max value pair with additional methods. In addition to conveniently storing values...
Definition: HashSet.H:72
scalar columnNorm(const label colIndex, const bool noSqrt=false) const
Return L2-Norm of chosen column.
Definition: Matrix.C:470
dimensionedScalar sqrt(const dimensionedScalar &ds)
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.
dimensionedScalar operator/(const scalar s1, const dimensionedScalar &ds2)
label k
Boltzmann constant.
std::enable_if_t<!std::is_same_v< complex, T >, const T & > conj(const T &val)
The &#39;conjugate&#39; of non-complex returns itself (pass-through) it does not return a complex! ...
Definition: complex.H:399
List< Type > release()
Release storage management of Matrix contents by transferring management to a List.
Definition: Matrix.C:260
tmp< faMatrix< Type > > operator+(const faMatrix< Type > &, const faMatrix< Type > &)
void transfer(Matrix< Form, Type > &mat)
Transfer the contents of the argument Matrix into this Matrix and annul the argument Matrix...
Definition: Matrix.C:294
bool empty() const noexcept
Return true if Matrix is empty (i.e., size() is zero)
Definition: MatrixI.H:97
void operator+=(const Matrix< Form, Type > &other)
Matrix addition.
Definition: Matrix.C:598
void operator-=(const Matrix< Form, Type > &other)
Matrix subtraction.
Definition: Matrix.C:628
MinMax< label > minMax(const labelHashSet &set)
Find the min/max values of labelHashSet.
Definition: hashSets.C:54
label n() const noexcept
The number of columns.
Definition: Matrix.H:271
labelPair sizes() const noexcept
Return row/column sizes.
Definition: MatrixI.H:90
tmp< faMatrix< Type > > operator*(const areaScalarField::Internal &, const faMatrix< Type > &)
Type trace() const
Return the trace.
Definition: Matrix.C:453
void operator*=(const Type &s)
Matrix scalar multiplication.
Definition: Matrix.C:678
List< Type > diag() const
Extract the diagonal elements. Method may change in the future.
Definition: Matrix.C:416
void deallocate(T *ptr)
Definition: ListPolicy.H:173
iterator end() noexcept
Return an iterator to end traversing a Matrix.
Definition: MatrixI.H:517
scalar norm(const bool noSqrt=false) const
Return Frobenius norm of Matrix.
Definition: Matrix.C:487
void clear()
Clear Matrix, i.e. set sizes to zero.
Definition: Matrix.C:248
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
errorManip< error > abort(error &err)
Definition: errorManip.H:139
tmp< faMatrix< Type > > operator-(const faMatrix< Type > &)
Unary negation.
const Type * cdata() const noexcept
Return const pointer to the first data element, which can also be used to address into Matrix content...
Definition: MatrixI.H:176
void swap(Matrix< Form, Type > &mat)
Swap contents.
Definition: Matrix.C:280
A templated (m x n) matrix of objects of <T>. The layout is (mRows x nCols) - row-major order: ...
refinementData transform(const tensor &, const refinementData val)
No-op rotational transform for base types.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
label m() const noexcept
The number of rows.
Definition: Matrix.H:261
std::streamsize byteSize() const
Number of contiguous bytes for the Matrix data, runtime FatalError if type is not contiguous...
Definition: Matrix.C:501
const_iterator cend() const noexcept
Return const_iterator to end traversing a constant Matrix.
Definition: MatrixI.H:533
surface1 clear()
~Matrix()
Destructor.
Definition: Matrix.C:238
Form transpose() const
Return non-conjugate transpose of Matrix.
Definition: Matrix.C:399
void operator/=(const Type &s)
Matrix scalar division.
Definition: Matrix.C:688
void round(const scalar tol=SMALL)
Round elements with magnitude smaller than tol (SMALL) to zero.
Definition: Matrix.C:369
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
label n
const_iterator cbegin() const noexcept
Return const_iterator to begin traversing a constant Matrix.
Definition: MatrixI.H:525
void resize_nocopy(const label mrow, const label ncol)
Change Matrix dimensions without preserving existing content.
Definition: Matrix.C:339
A class for managing temporary objects.
Definition: HashPtrTable.H:50
void operator=(const Matrix< Form, Type > &mat)
Copy assignment. Takes linear time.
Definition: Matrix.C:516
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)
static const Foam::dimensionedScalar B("", Foam::dimless, 18.678)
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127