EigenMatrix.H
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  Code created 2014-2018 by Alberto Passalacqua
9  Contributed 2018-07-31 to the OpenFOAM Foundation
10  Copyright (C) 2018 OpenFOAM Foundation
11  Copyright (C) 2019-2020 Alberto Passalacqua
12  Copyright (C) 2020 OpenCFD Ltd.
13 -------------------------------------------------------------------------------
14 License
15  This file is part of OpenFOAM.
16 
17  OpenFOAM is free software: you can redistribute it and/or modify it
18  under the terms of the GNU General Public License as published by
19  the Free Software Foundation, either version 3 of the License, or
20  (at your option) any later version.
21 
22  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
23  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
25  for more details.
26 
27  You should have received a copy of the GNU General Public License
28  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
29 
30 Class
31  Foam::EigenMatrix
32 
33 Description
34  EigenMatrix (i.e. eigendecomposition or spectral decomposition) decomposes
35  a diagonalisable nonsymmetric real square matrix into its canonical form,
36  whereby the matrix is represented in terms of its eigenvalues and
37  eigenvectors.
38 
39  The eigenvalue equation (i.e. eigenvalue problem) is:
40 
41  \f[
42  A v = \lambda v
43  \f]
44 
45  where
46  \vartable
47  A | a diagonalisable square matrix of dimension m-by-m
48  v | a (non-zero) vector of dimension m (right eigenvector)
49  \lambda | a scalar corresponding to v (eigenvalue)
50  \endvartable
51 
52 
53  If \c A is symmetric, the following relation is satisfied:
54 
55  \f[
56  A = v*D*v^T
57  \f]
58 
59  where
60  \vartable
61  D | diagonal real eigenvalue matrix
62  v | orthogonal eigenvector matrix
63  \endvartable
64 
65  If \c A is not symmetric, \c D becomes a block diagonal matrix wherein
66  the real eigenvalues are present on the diagonal within 1-by-1 blocks, and
67  complex eigenvalues within 2-by-2 blocks, i.e. \f$\lambda + i \mu\f$ with
68  \f$[\lambda, \mu; -\mu, \lambda]\f$.
69 
70  The columns of \c v represent eigenvectors corresponding to eigenvalues,
71  satisfying the eigenvalue equation. Even though eigenvalues of a matrix
72  are unique, eigenvectors of the matrix are not. For the same eigenvalue,
73  the corresponding eigenvector can be real or complex with non-unique
74  entries. In addition, the validity of the equation \f$A = v*D*v^T\f$
75  depends on the condition number of \c v, which can be ill-conditioned,
76  or singular for invalidated equations.
77 
78  References:
79  \verbatim
80  OpenFOAM-compatible implementation:
81  Passalacqua, A., Heylmun, J., Icardi, M.,
82  Madadi, E., Bachant, P., & Hu, X. (2019).
83  OpenQBMM 5.0.1 for OpenFOAM 7, Zenodo.
84  DOI:10.5281/zenodo.3471804
85 
86  Implementations for the functions:
87  'tridiagonaliseSymmMatrix', 'symmTridiagonalQL',
88  'Hessenberg' and 'realSchur' (based on ALGOL-procedure:tred2):
89  Wilkinson, J. H., & Reinsch, C. (1971).
90  In Bauer, F. L. & Householder A. S. (Eds.),
91  Handbook for Automatic Computation: Volume II: Linear Algebra.
92  (Vol. 186), Springer-Verlag Berlin Heidelberg.
93  DOI: 10.1007/978-3-642-86940-2
94 
95  Explanations on how real eigenvectors
96  can be unpacked into complex domain:
97  Moler, C. (1998).
98  Re: Eigenvectors.
99  Retrieved from https://bit.ly/3ao4Wat
100 
101  TNT/JAMA implementation:
102  Pozo, R. (1997).
103  Template Numerical Toolkit for linear algebra:
104  High performance programming with C++
105  and the Standard Template Library.
106  The International Journal of Supercomputer Applications
107  and High Performance Computing, 11(3), 251-263.
108  DOI:10.1177/109434209701100307
109 
110  (No particular order) Hicklin, J., Moler, C., Webb, P.,
111  Boisvert, R. F., Miller, B., Pozo, R., & Remington, K. (2012).
112  JAMA: A Java Matrix Package 1.0.3.
113  Retrived from https://math.nist.gov/javanumerics/jama/
114  \endverbatim
115 
116 Note
117  - This implementation is an integration of the \c OpenQBMM \c eigenSolver
118  class (2019) without any changes to its internal mechanisms. Therefore, no
119  differences between EigenMatrix and \c eigenSolver (2019) classes should be
120  expected in terms of input-process-output operations.
121  - The \c OpenQBMM \c eigenSolver class derives almost completely from the
122  \c TNT/JAMA implementation, a public-domain library developed by \c NIST
123  and \c MathWorks from 1998 to 2012, available at
124  http://math.nist.gov/tnt/index.html (Retrieved June 6, 2020). Their
125  implementation was based upon \c EISPACK.
126  - The \c tridiagonaliseSymmMatrix, \c symmTridiagonalQL, \c Hessenberg and
127  \c realSchur methods are based on the \c Algol procedures \c tred2 by
128  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for Auto. Comp.,
129  Vol. II-Linear Algebra, and the corresponding \c FORTRAN subroutine
130  in \c EISPACK.
131 
132 See also
133  Test-EigenMatrix.C
134 
135 SourceFiles
136  EigenMatrix.C
137 
138 \*---------------------------------------------------------------------------*/
139 
140 #ifndef Foam_EigenMatrix_H
141 #define Foam_EigenMatrix_H
142 
143 #include "scalarMatrices.H"
144 #include "DiagonalMatrix.H"
145 #include "SquareMatrix.H"
146 #include "complex.H"
147 
148 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
149 
150 namespace Foam
151 {
152 
153 /*---------------------------------------------------------------------------*\
154  Class EigenMatrix Declaration
155 \*---------------------------------------------------------------------------*/
156 
157 template<class cmptType>
158 class EigenMatrix
159 {
160  static_assert
161  (
162  std::is_floating_point<cmptType>::value,
163  "EigenMatrix operates only with scalar base type."
164  );
165 
166  // Private Data
167 
168  //- Number of rows and columns in input matrix
169  const label n_;
170 
171  //- Real eigenvalues or real part of complex eigenvalues
172  DiagonalMatrix<cmptType> EValsRe_;
174  //- Zero-matrix for real eigenvalues
175  //- or imaginary part of complex eigenvalues
176  DiagonalMatrix<cmptType> EValsIm_;
177 
178  //- Right eigenvectors matrix where each column is
179  //- a right eigenvector that corresponds to an eigenvalue
180  SquareMatrix<cmptType> EVecs_;
181 
182  //- Copy of nonsymmetric input matrix evolving to eigenvectors matrix
184 
185 
186  // Private Member Functions
187 
188  //- Householder transform of a symmetric matrix to tri-diagonal form
189  void tridiagonaliseSymmMatrix();
190 
191  //- Symmetric tri-diagonal QL algorithm
192  void symmTridiagonalQL();
193 
194  //- Reduce non-symmetric matrix to upper-Hessenberg form
195  void Hessenberg();
196 
197  //- Reduce matrix from Hessenberg to real Schur form
198  void realSchur();
199 
200 
201 public:
202 
203  // Generated Methods
204 
205  //- No default construct
206  EigenMatrix() = delete;
207 
208  //- No copy construct
209  EigenMatrix(const EigenMatrix&) = delete;
210 
211  //- No copy assignment
212  EigenMatrix& operator=(const EigenMatrix&) = delete;
213 
214 
215  // Constructors
216 
217  //- Construct from a SquareMatrix<cmptType>
218  explicit EigenMatrix(const SquareMatrix<cmptType>& A);
219 
220  //- Construct from a SquareMatrix<cmptType> and symmetry flag
221  // Does not perform symmetric check
222  EigenMatrix(const SquareMatrix<cmptType>& A, bool symmetric);
223 
224 
225  // Access
226 
227  //- Return real eigenvalues or real part of complex eigenvalues
228  const DiagonalMatrix<cmptType>& EValsRe() const
229  {
230  return EValsRe_;
231  }
232 
233  //- Return zero-matrix for real eigenvalues
234  //- or imaginary part of complex eigenvalues
235  const DiagonalMatrix<cmptType>& EValsIm() const
236  {
237  return EValsIm_;
238  }
239 
240  //- Return right eigenvectors matrix where each column is
241  //- a right eigenvector that corresponds to an eigenvalue
242  const SquareMatrix<cmptType>& EVecs() const
243  {
244  return EVecs_;
245  }
246 
247  //- Return right eigenvectors in unpacked form
248  const SquareMatrix<complex> complexEVecs() const;
249 
250 };
251 
252 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
253 
254 } // End namespace Foam
255 
256 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
257 
258 #ifdef NoRepository
259  #include "EigenMatrix.C"
260 #endif
261 
262 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
263 
264 #endif
265 
266 // ************************************************************************* //
EigenMatrix()=delete
No default construct.
const DiagonalMatrix< cmptType > & EValsRe() const
Return real eigenvalues or real part of complex eigenvalues.
Definition: EigenMatrix.H:274
EigenMatrix & operator=(const EigenMatrix &)=delete
No copy assignment.
const DiagonalMatrix< cmptType > & EValsIm() const
Return zero-matrix for real eigenvalues or imaginary part of complex eigenvalues. ...
Definition: EigenMatrix.H:283
const SquareMatrix< cmptType > & EVecs() const
Return right eigenvectors matrix where each column is a right eigenvector that corresponds to an eige...
Definition: EigenMatrix.H:292
const SquareMatrix< complex > complexEVecs() const
Return right eigenvectors in unpacked form.
Definition: EigenMatrix.C:1065
static const Foam::dimensionedScalar A("", Foam::dimPressure, 611.21)
EigenMatrix (i.e. eigendecomposition or spectral decomposition) decomposes a diagonalisable nonsymmet...
Definition: EigenMatrix.H:173
Namespace for OpenFOAM.