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-2022 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(), 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(), 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, const 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  delete[] v_;
248 }
249 
250 
251 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
252 
253 template<class Form, class Type>
255 {
256  if (v_)
257  {
258  delete[] v_;
259  v_ = nullptr;
260  }
262  mRows_ = 0;
263  nCols_ = 0;
264 }
265 
266 
267 template<class Form, class Type>
269 {
270  List<Type> list;
271 
272  const label len = size();
273 
274  if (v_ && len)
275  {
276  UList<Type> storage(v_, len);
277  list.swap(storage);
278 
279  v_ = nullptr;
280  }
281  clear();
282 
283  return list;
284 }
285 
286 
287 template<class Form, class Type>
289 {
290  if (this == &mat)
291  {
292  return; // Self-swap is a no-op
293  }
294 
295  std::swap(mRows_, mat.mRows_);
296  std::swap(nCols_, mat.nCols_);
297  std::swap(v_, mat.v_);
298 }
299 
300 
301 template<class Form, class Type>
303 {
304  if (this == &mat)
305  {
306  return; // Self-assignment is a no-op
307  }
308 
309  clear();
310 
311  mRows_ = mat.mRows_;
312  nCols_ = mat.nCols_;
313  v_ = mat.v_;
314 
315  mat.mRows_ = 0;
316  mat.nCols_ = 0;
317  mat.v_ = nullptr;
318 }
319 
320 
321 template<class Form, class Type>
322 void Foam::Matrix<Form, Type>::resize(const label m, const label n)
323 {
324  if (m == mRows_ && n == nCols_)
325  {
326  return;
327  }
328 
329  Matrix<Form, Type> newMatrix(m, n, Zero);
330 
331  const label mrow = min(m, mRows_);
332  const label ncol = min(n, nCols_);
333 
334  for (label i = 0; i < mrow; ++i)
335  {
336  for (label j = 0; j < ncol; ++j)
337  {
338  newMatrix(i, j) = (*this)(i, j);
339  }
340  }
341 
342  transfer(newMatrix);
343 }
344 
345 
346 template<class Form, class Type>
347 void Foam::Matrix<Form, Type>::resize_nocopy(const label mrow, const label ncol)
348 {
349  if (mrow == mRows_ && ncol == nCols_)
350  {
351  return;
352  }
353 
354  const label oldLen = (mRows_ * nCols_);
355 
356  const label newLen = (mrow * ncol);
357 
358  if (oldLen == newLen)
359  {
360  // Shallow resize is enough
361  mRows_ = mrow;
362  nCols_ = ncol;
363  }
364  else
365  {
366  this->clear();
367 
368  mRows_ = mrow;
369  nCols_ = ncol;
371  this->doAlloc();
372  }
373 }
374 
375 
376 template<class Form, class Type>
377 void Foam::Matrix<Form, Type>::round(const scalar tol)
378 {
379  for (Type& val : *this)
380  {
381  if (mag(val) < tol)
382  {
383  val = Zero;
384  }
385  }
386 }
387 
388 
389 template<class Form, class Type>
390 Form Foam::Matrix<Form, Type>::T() const
391 {
392  Form At(labelPair{n(), m()});
393 
394  for (label i = 0; i < m(); ++i)
395  {
396  for (label j = 0; j < n(); ++j)
397  {
398  At(j, i) = Detail::conj((*this)(i, j));
399  }
400  }
401 
402  return At;
403 }
404 
405 
406 template<class Form, class Type>
408 {
409  Form At(labelPair{n(), m()});
410 
411  for (label i = 0; i < m(); ++i)
412  {
413  for (label j = 0; j < n(); ++j)
414  {
415  At(j, i) = (*this)(i, j);
416  }
417  }
418 
419  return At;
420 }
421 
422 
423 template<class Form, class Type>
425 {
426  const label len = Foam::min(mRows_, nCols_);
427 
428  List<Type> result(len);
429 
430  for (label i=0; i < len; ++i)
431  {
432  result[i] = (*this)(i, i);
433  }
434 
435  return result;
436 }
437 
438 
439 template<class Form, class Type>
440 void Foam::Matrix<Form, Type>::diag(const UList<Type>& list)
441 {
442  const label len = Foam::min(mRows_, nCols_);
443 
444  #ifdef FULLDEBUG
445  if (list.size() != len)
446  {
448  << "List size (" << list.size()
449  << ") incompatible with Matrix diagonal" << abort(FatalError);
450  }
451  #endif
452 
453  for (label i=0; i < len; ++i)
454  {
455  (*this)(i, i) = list[i];
456  }
457 }
458 
459 
460 template<class Form, class Type>
462 {
463  const label len = Foam::min(mRows_, nCols_);
464 
465  Type val = Zero;
466 
467  for (label i=0; i < len; ++i)
468  {
469  val += (*this)(i, i);
470  }
472  return val;
473 }
474 
475 
476 template<class Form, class Type>
478 (
479  const label colIndex,
480  const bool noSqrt
481 ) const
482 {
483  scalar result = Zero;
484 
485  for (label i=0; i < mRows_; ++i)
486  {
487  result += magSqr((*this)(i, colIndex));
488  }
489 
490  return noSqrt ? result : Foam::sqrt(result);
491 }
492 
493 
494 template<class Form, class Type>
495 Foam::scalar Foam::Matrix<Form, Type>::norm(const bool noSqrt) const
496 {
497  scalar result = Zero;
498 
499  for (const Type& val : *this)
500  {
501  result += magSqr(val);
502  }
503 
504  return noSqrt ? result : Foam::sqrt(result);
505 }
506 
507 
508 template<class Form, class Type>
509 std::streamsize Foam::Matrix<Form, Type>::byteSize() const
510 {
511  if (!is_contiguous<Type>::value)
512  {
514  << "Invalid for non-contiguous data types"
515  << abort(FatalError);
516  }
517  return this->size_bytes();
518 }
519 
520 
521 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
522 
523 template<class Form, class Type>
525 {
526  if (this == &mat)
527  {
528  return; // Self-assignment is a no-op
529  }
530 
531  if (mRows_ != mat.mRows_ || nCols_ != mat.nCols_)
532  {
533  clear();
534  mRows_ = mat.mRows_;
535  nCols_ = mat.nCols_;
536  doAlloc();
537  }
538 
539  if (v_)
540  {
541  std::copy(mat.cbegin(), mat.cend(), v_);
542  }
543 }
544 
545 
546 template<class Form, class Type>
547 void Foam::Matrix<Form, Type>::operator=(Matrix<Form, Type>&& mat)
548 {
549  if (this != &mat)
550  {
551  // Self-assignment is a no-op
552  this->transfer(mat);
553  }
554 }
555 
556 
557 template<class Form, class Type>
558 template<class MatrixType>
560 (
561  const ConstMatrixBlock<MatrixType>& Mb
562 )
563 {
564  for (label i = 0; i < mRows_; ++i)
565  {
566  for (label j = 0; j < nCols_; ++j)
567  {
568  (*this)(i, j) = Mb(i, j);
569  }
570  }
571 }
572 
573 
574 template<class Form, class Type>
575 template<class MatrixType>
577 (
578  const MatrixBlock<MatrixType>& Mb
579 )
580 {
581  for (label i = 0; i < mRows_; ++i)
582  {
583  for (label j = 0; j < nCols_; ++j)
584  {
585  (*this)(i, j) = Mb(i, j);
586  }
587  }
588 }
589 
590 
591 template<class Form, class Type>
593 {
594  std::fill_n(begin(), size(), val);
595 }
596 
597 
598 template<class Form, class Type>
600 {
601  std::fill_n(begin(), size(), Zero);
602 }
603 
604 
605 template<class Form, class Type>
607 {
608  #ifdef FULLDEBUG
609  if (this == &other)
610  {
612  << "Attempted addition to self"
613  << abort(FatalError);
614  }
615 
616  if (m() != other.m() || n() != other.n())
617  {
619  << "Attempt to add matrices with different sizes: ("
620  << m() << ", " << n() << ") != ("
621  << other.m() << ", " << other.n() << ')' << nl
622  << abort(FatalError);
623  }
624  #endif
625 
626  auto iter2 = other.cbegin();
627  for (Type& val : *this)
628  {
629  val += *iter2;
630  ++iter2;
631  }
632 }
633 
634 
635 template<class Form, class Type>
636 void Foam::Matrix<Form, Type>::operator-=(const Matrix<Form, Type>& other)
637 {
638  #ifdef FULLDEBUG
639  if (this == &other)
640  {
642  << "Attempted subtraction from self"
643  << abort(FatalError);
644  }
645 
646  if (m() != other.m() || n() != other.n())
647  {
649  << "Attempt to subtract matrices with different sizes: ("
650  << m() << ", " << n() << ") != ("
651  << other.m() << ", " << other.n() << ')' << nl
652  << abort(FatalError);
653  }
654  #endif
655 
656  auto iter2 = other.cbegin();
657  for (Type& val : *this)
658  {
659  val -= *iter2;
660  ++iter2;
661  }
662 }
663 
664 
665 template<class Form, class Type>
666 void Foam::Matrix<Form, Type>::operator+=(const Type& s)
667 {
668  for (Type& val : *this)
669  {
670  val += s;
671  }
672 }
673 
674 
675 template<class Form, class Type>
676 void Foam::Matrix<Form, Type>::operator-=(const Type& s)
677 {
678  for (Type& val : *this)
679  {
680  val -= s;
681  }
682 }
683 
684 
685 template<class Form, class Type>
686 void Foam::Matrix<Form, Type>::operator*=(const Type& s)
687 {
688  for (Type& val : *this)
689  {
690  val *= s;
691  }
692 }
693 
694 
695 template<class Form, class Type>
696 void Foam::Matrix<Form, Type>::operator/=(const Type& s)
697 {
698  for (Type& val : *this)
699  {
700  val /= s;
701  }
702 }
703 
704 
705 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
706 
707 namespace Foam
708 {
710 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * * //
711 
712 //- Find max value in Matrix
713 template<class Form, class Type>
714 const Type& max(const Matrix<Form, Type>& mat)
715 {
716  if (mat.empty())
717  {
719  << "Matrix is empty" << abort(FatalError);
720  }
721 
722  return *(std::max_element(mat.cbegin(), mat.cend()));
723 }
724 
726 //- Find min value in Matrix
727 template<class Form, class Type>
728 const Type& min(const Matrix<Form, Type>& mat)
729 {
730  if (mat.empty())
731  {
733  << "Matrix is empty" << abort(FatalError);
734  }
735 
736  return *(std::min_element(mat.cbegin(), mat.cend()));
737 }
738 
739 
740 //- Find the min/max values of Matrix
741 template<class Form, class Type>
743 {
744  MinMax<Type> result;
745 
746  for (const Type& val : mat)
747  {
748  result += val;
749  }
750 
751  return result;
752 }
753 
754 
755 
756 // * * * * * * * * * * * * * * * Global Operators * * * * * * * * * * * * * //
757 
758 //- Matrix negation
759 template<class Form, class Type>
760 Form operator-(const Matrix<Form, Type>& mat)
761 {
762  Form result(mat.sizes());
763 
765  (
766  mat.cbegin(),
767  mat.cend(),
768  result.begin(),
769  std::negate<Type>()
770  );
771 
772  return result;
773 }
774 
775 
776 //- Matrix addition. Returns Matrix of the same form as the first parameter.
777 template<class Form1, class Form2, class Type>
778 Form1 operator+
779 (
780  const Matrix<Form1, Type>& A,
781  const Matrix<Form2, Type>& B
782 )
783 {
784  #ifdef FULLDEBUG
785  if (A.m() != B.m() || A.n() != B.n())
786  {
788  << "Attempt to add matrices with different sizes: ("
789  << A.m() << ", " << A.n() << ") != ("
790  << B.m() << ", " << B.n() << ')' << nl
791  << abort(FatalError);
792  }
793  #endif
794 
795  Form1 result(A.sizes());
796 
798  (
799  A.cbegin(),
800  A.cend(),
801  B.cbegin(),
802  result.begin(),
803  std::plus<Type>()
804  );
805 
806  return result;
807 }
808 
809 
810 //- Matrix subtraction. Returns Matrix of the same form as the first parameter.
811 template<class Form1, class Form2, class Type>
812 Form1 operator-
813 (
814  const Matrix<Form1, Type>& A,
815  const Matrix<Form2, Type>& B
816 )
817 {
818  #ifdef FULLDEBUG
819  if (A.m() != B.m() || A.n() != B.n())
820  {
822  << "Attempt to subtract matrices with different sizes: ("
823  << A.m() << ", " << A.n() << ") != ("
824  << B.m() << ", " << B.n() << ')' << nl
825  << abort(FatalError);
826  }
827  #endif
828 
829  Form1 result(A.sizes());
830 
832  (
833  A.cbegin(),
834  A.cend(),
835  B.cbegin(),
836  result.begin(),
837  std::minus<Type>()
838  );
839 
840  return result;
841 }
842 
843 
844 //- Scalar multiplication of Matrix
845 template<class Form, class Type>
846 Form operator*(const Type& s, const Matrix<Form, Type>& mat)
847 {
848  Form result(mat.sizes());
849 
851  (
852  mat.cbegin(),
853  mat.cend(),
854  result.begin(),
855  [&](const Type& val) { return s * val; }
856  );
857 
858  return result;
859 }
860 
861 
862 //- Scalar multiplication of Matrix
863 template<class Form, class Type>
864 Form operator*(const Matrix<Form, Type>& mat, const Type& s)
865 {
866  return s*mat;
867 }
868 
869 
870 //- Scalar addition of Matrix
871 template<class Form, class Type>
872 Form operator+(const Type& s, const Matrix<Form, Type>& mat)
873 {
874  Form result(mat.sizes());
875 
877  (
878  mat.cbegin(),
879  mat.cend(),
880  result.begin(),
881  [&](const Type& val) { return s + val; }
882  );
884  return result;
885 }
886 
887 
888 //- Scalar addition of Matrix
889 template<class Form, class Type>
890 Form operator+(const Matrix<Form, Type>& mat, const Type& s)
891 {
892  return s + mat;
893 }
894 
895 
896 //- Scalar subtraction of Matrix
897 template<class Form, class Type>
898 Form operator-(const Type& s, const Matrix<Form, Type>& mat)
899 {
900  Form result(mat.sizes());
901 
903  (
904  mat.cbegin(),
905  mat.end(),
906  result.begin(),
907  [&](const Type& val) { return s - val; }
908  );
909 
910  return result;
911 }
912 
914 //- Scalar subtraction of Matrix
915 template<class Form, class Type>
916 Form operator-(const Matrix<Form, Type>& mat, const Type& s)
917 {
918  Form result(mat.sizes());
919 
921  (
922  mat.cbegin(),
923  mat.end(),
924  result.begin(),
925  [&](const Type& val) { return val - s; }
926  );
927 
928  return result;
929 }
930 
931 
932 //- Scalar division of Matrix
933 template<class Form, class Type>
934 Form operator/(const Matrix<Form, Type>& mat, const Type& s)
935 {
936  Form result(mat.sizes());
937 
939  (
940  mat.cbegin(),
941  mat.end(),
942  result.begin(),
943  [&](const Type& val) { return val / s; }
944  );
945 
946  return result;
947 }
948 
949 
950 //- Matrix-Matrix multiplication using ikj-algorithm
951 template<class Form1, class Form2, class Type>
953 operator*
954 (
955  const Matrix<Form1, Type>& A,
956  const Matrix<Form2, Type>& B
957 )
958 {
959  #ifdef FULLDEBUG
960  if (A.n() != B.m())
961  {
963  << "Attempt to multiply incompatible matrices:" << nl
964  << "Matrix A : (" << A.m() << ", " << A.n() << ')' << nl
965  << "Matrix B : (" << B.m() << ", " << B.n() << ')' << nl
966  << "The columns of A must equal rows of B"
967  << abort(FatalError);
968  }
969  #endif
970 
972  (
973  A.m(),
974  B.n(),
976  );
977 
978  for (label i = 0; i < AB.m(); ++i)
979  {
980  for (label k = 0; k < B.m(); ++k)
981  {
982  for (label j = 0; j < AB.n(); ++j)
983  {
984  AB(i, j) += A(i, k)*B(k, j);
985  }
986  }
987  }
988 
989  return AB;
990 }
991 
992 
993 //- Implicit inner product of Matrix-Matrix, equivalent to A.T()*B
994 template<class Form1, class Form2, class Type>
996 operator&
997 (
998  const Matrix<Form1, Type>& AT,
999  const Matrix<Form2, Type>& B
1000 )
1001 {
1002  #ifdef FULLDEBUG
1003  if (AT.m() != B.m())
1004  {
1006  << "Attempt to multiply incompatible matrices:" << nl
1007  << "Matrix A : (" << AT.m() << ", " << AT.n() << ')' << nl
1008  << "Matrix B : (" << B.m() << ", " << B.n() << ')' << nl
1009  << "The rows of A must equal rows of B"
1010  << abort(FatalError);
1011  }
1012  #endif
1013 
1015  (
1016  AT.n(),
1017  B.n(),
1018  Zero
1019  );
1021  for (label k = 0; k < B.m(); ++k)
1022  {
1023  for (label i = 0; i < AB.m(); ++i)
1024  {
1025  for (label j = 0; j < AB.n(); ++j)
1026  {
1027  AB(i, j) += Detail::conj(AT(k, i))*B(k, j);
1028  }
1029  }
1030  }
1031 
1032  return AB;
1033 }
1034 
1035 
1036 //- Implicit outer product of Matrix-Matrix, equivalent to A*B.T()
1037 template<class Form1, class Form2, class Type>
1039 operator^
1040 (
1041  const Matrix<Form1, Type>& A,
1042  const Matrix<Form2, Type>& BT
1043 )
1044 {
1045  #ifdef FULLDEBUG
1046  if (A.n() != BT.n())
1047  {
1049  << "Attempt to multiply incompatible matrices:" << nl
1050  << "Matrix A : (" << A.m() << ", " << A.n() << ')' << nl
1051  << "Matrix B : (" << BT.m() << ", " << BT.n() << ')' << nl
1052  << "The columns of A must equal columns of B"
1053  << abort(FatalError);
1054  }
1055  #endif
1056 
1058  (
1059  A.m(),
1060  BT.m(),
1061  Zero
1062  );
1063 
1064  for (label i = 0; i < AB.m(); ++i)
1065  {
1066  for (label j = 0; j < AB.n(); ++j)
1067  {
1068  for (label k = 0; k < BT.n(); ++k)
1069  {
1070  AB(i, j) += A(i, k)*Detail::conj(BT(j, k));
1071  }
1072  }
1073  }
1074 
1075  return AB;
1076 }
1077 
1078 
1079 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1080 
1081 } // End namespace Foam
1082 
1083 // ************************************************************************* //
const Type & min(const Matrix< Form, Type > &mat)
Find min value in Matrix.
Definition: Matrix.C:725
void swap(UList< T > &list) noexcept
Swap content with another UList of the same type in constant time.
Definition: UListI.H:505
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:315
type
Types of root.
Definition: Roots.H:52
std::enable_if< !std::is_same< complex, T >::value, const T &>::type conj(const T &val)
The &#39;conjugate&#39; of non-complex returns itself (pass-through) it does not return a complex! ...
Definition: complex.H:405
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
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:598
Form T() const
Return conjugate transpose of Matrix.
Definition: Matrix.C:383
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:471
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.
List< Type > release()
Release storage management of Matrix contents by transferring management to a List.
Definition: Matrix.C:261
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:295
bool empty() const noexcept
Return true if Matrix is empty (i.e., size() is zero)
Definition: MatrixI.H:103
void operator+=(const Matrix< Form, Type > &other)
Matrix addition.
Definition: Matrix.C:599
void operator-=(const Matrix< Form, Type > &other)
Matrix subtraction.
Definition: Matrix.C:629
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:258
tmp< faMatrix< Type > > operator*(const areaScalarField::Internal &, const faMatrix< Type > &)
Type trace() const
Return the trace.
Definition: Matrix.C:454
void operator*=(const Type &s)
Matrix scalar multiplication.
Definition: Matrix.C:679
List< Type > diag() const
Extract the diagonal elements. Method may change in the future.
Definition: Matrix.C:417
labelPair sizes() const
Return row/column sizes.
Definition: MatrixI.H:96
iterator end() noexcept
Return an iterator to end traversing a Matrix.
Definition: MatrixI.H:523
scalar norm(const bool noSqrt=false) const
Return Frobenius norm of Matrix.
Definition: Matrix.C:488
patchWriters clear()
void clear()
Clear Matrix, i.e. set sizes to zero.
Definition: Matrix.C:247
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:182
void swap(Matrix< Form, Type > &mat)
Swap contents.
Definition: Matrix.C:281
A templated (m x n) matrix of objects of <T>. The layout is (mRows x nCols) - row-major order: ...
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
label m() const noexcept
The number of rows.
Definition: Matrix.H:248
std::streamsize byteSize() const
Number of contiguous bytes for the Matrix data, runtime FatalError if type is not contiguous...
Definition: Matrix.C:502
const_iterator cend() const noexcept
Return const_iterator to end traversing a constant Matrix.
Definition: MatrixI.H:539
~Matrix()
Destructor.
Definition: Matrix.C:238
Form transpose() const
Return non-conjugate transpose of Matrix.
Definition: Matrix.C:400
void operator/=(const Type &s)
Matrix scalar division.
Definition: Matrix.C:689
Matrix() noexcept
Default construct (empty matrix)
Definition: MatrixI.H:42
void round(const scalar tol=SMALL)
Round elements with magnitude smaller than tol (SMALL) to zero.
Definition: Matrix.C:370
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:531
void resize_nocopy(const label mrow, const label ncol)
Change Matrix dimensions without preserving existing content.
Definition: Matrix.C:340
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:517
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))
dimensionSet transform(const dimensionSet &ds)
Return the argument; transformations do not change the dimensions.
Definition: dimensionSet.C:521
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
constexpr auto begin(C &c) -> decltype(c.begin())
Return iterator to the beginning of the container c.
Definition: stdFoam.H:168
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