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