sisi4s
Loading...
Searching...
No Matches
LapackGeneralEigenSystem.hpp
Go to the documentation of this file.
1#ifndef LAPACK_GENERAL_EIGEN_SYSTEM_DEFINED
2#define LAPACK_GENERAL_EIGEN_SYSTEM_DEFINED
3
4#include <math/Complex.hpp>
6#include <util/Exception.hpp>
7#include <extern/Lapack.hpp>
8#include <util/Log.hpp>
9
10#include <vector>
11
12namespace sisi4s {
13// base template
14template <typename F = double>
16
17template <>
19public:
20 class EigenValueComparator {
21 public:
22 bool operator()(const std::pair<int, double> &a,
23 const std::pair<int, double> &b) {
24 double diff(b.second - a.second);
25 double magnitude(std::abs(a.second) + std::abs(b.second));
26 if (std::real(diff) > +1E-13 * magnitude) return true;
27 if (std::real(diff) < -1E-13 * magnitude) return false;
28 return a.first < b.first;
29 }
30 };
31};
32
33/*
34 // specialization for double
35 template <>
36 class LapackGeneralEigenSystem<double> {
37 public:
38 LapackGeneralEigenSystem(
39 const LapackMatrix<double> &A_
40 ):
41 R(A_.getRows(), A_.getColumns()),
42 L(A_.getRows(), A_.getColumns()),
43 lambdas(A_.getRows())
44 {
45 if (A_.getRows() != A_.getColumns()) {
46 throw EXCEPTION("EigenSystem requries a square matrix");
47 }
48 // copy A since it will be modified
49 LapackMatrix<double> A(A_);
50 int rows(A_.getRows());
51 std::vector<double> lambdaReals(rows), lambdaImags(rows);
52 double optimalWork;
53 int workCount(-1);
54 int info;
55 dgeev_(
56 "V", "V",
57 &rows,
58 A.getValues(), &rows,
59 lambdaReals.data(), lambdaImags.data(),
60 L.getValues(), &rows,
61 R.getValues(), &rows,
62 &optimalWork, &workCount,
63 &info
64 );
65 // TODO: check info
66 workCount = static_cast<int>(optimalWork+0.5);
67 std::vector<double> work(workCount);
68
69 dgeev_(
70 "V", "V",
71 &rows,
72 A.getValues(), &rows,
73 lambdaReals.data(), lambdaImags.data(),
74 L.getValues(), &rows,
75 R.getValues(), &rows,
76 work.data(), &workCount,
77 &info
78 );
79 // TODO: check info
80
81 for (int i(0); i < rows; ++i) {
82 lambdas[i] = complex(lambdaReals[i], lambdaImags[i]);
83 if (std::abs(lambdaImags[i]) > 1e-8*std::abs(lambdaReals[i])) {
84 // TODO: decode eigenvectors to complex eigenvalues
85 }
86 }
87 }
88
89 ~LapackGeneralEigenSystem() {
90 }
91
92 const std::vector<complex> &getEigenValues() const {
93 return lambda;
94 }
95
96 const LapackMatrix<complex> &getRightEigenVectors() const {
97 return R;
98 }
99
100 const LapackMatrix<complex> &getLeftEigenVectors() const {
101 return L;
102 }
103
104 protected:
105 LapackMatrix<complex> R, L;
106 std::vector<complex> lambdas;
107 };
108*/
109
110// specialization for complex
111template <>
113public:
115 bool computeRightEigenvectors = true,
116 bool computeLeftEigenvectors = false)
117 : R(computeRightEigenvectors
118 ? NEW(LapackMatrix<complex>, A_.getRows(), A_.getColumns())
119 : nullptr)
120 , L(computeLeftEigenvectors
121 ? NEW(LapackMatrix<complex>, A_.getRows(), A_.getColumns())
122 : nullptr)
123 , lambdas(A_.getRows()) {
124 if (A_.getRows() != A_.getColumns()) {
125 throw EXCEPTION("EigenSystem requries a square matrix");
126 }
127 // copy A since it will be modified
129 int rows(A_.getRows());
130 std::vector<double> realWork(2 * rows);
131 complex optimalWork;
132 int workCount(-1);
133 int info;
134 zgeev_(computeLeftEigenvectors ? "V" : "N",
135 computeRightEigenvectors ? "V" : "N",
136 &rows,
137 A.getValues(),
138 &rows,
139 lambdas.data(),
140 computeLeftEigenvectors ? L->getValues() : nullptr,
141 &rows,
142 computeRightEigenvectors ? R->getValues() : nullptr,
143 &rows,
144 &optimalWork,
145 &workCount,
146 realWork.data(),
147 &info);
148 // TODO: check info
149 workCount = static_cast<int>(std::real(optimalWork) + 0.5);
150 std::vector<complex> work(workCount);
151
152 zgeev_(computeLeftEigenvectors ? "V" : "N",
153 computeRightEigenvectors ? "V" : "N",
154 &rows,
155 A.getValues(),
156 &rows,
157 lambdas.data(),
158 computeLeftEigenvectors ? L->getValues() : nullptr,
159 &rows,
160 computeRightEigenvectors ? R->getValues() : nullptr,
161 &rows,
162 work.data(),
163 &workCount,
164 realWork.data(),
165 &info);
166 // TODO: check info
167
168 // sort eigenvalues
169 std::vector<std::pair<int, complex>> sortedEigenValues(rows);
170 for (int i(0); i < rows; ++i) {
171 sortedEigenValues[i] = std::pair<int, complex>(i, lambdas[i]);
172 }
173 std::sort(sortedEigenValues.begin(),
174 sortedEigenValues.end(),
175 EigenValueComparator());
176 // order eigenvectors and returned eigenvalues in the same way
177 if (computeRightEigenvectors) { orderEigenVectors(sortedEigenValues, *R); }
178 if (computeLeftEigenvectors) { orderEigenVectors(sortedEigenValues, *L); }
179 for (int i(0); i < rows; ++i) { lambdas[i] = sortedEigenValues[i].second; }
180 }
181
183
184 const std::vector<complex> &getEigenValues() const { return lambdas; }
185
187 if (!R) {
188 throw new EXCEPTION(
189 "Right eigenvectors were not computed in constructor.");
190 }
191 return *R;
192 }
193
195 if (!L) {
196 throw new EXCEPTION(
197 "Left eigenvectors were not computed in constructor.");
198 }
199 return *L;
200 }
201
203 double error(0);
204 for (int i(0); i < A.getRows(); ++i) {
205 for (int k(0); k < A.getRows(); ++k) {
206 complex element(0);
207 for (int j(0); j < A.getRows(); ++j) {
208 element += A(i, j) * (*R)(j, k);
209 }
210 element -= lambdas[k] * (*R)(i, k);
211 error += std::real(element * std::conj(element));
212 }
213 }
214 return error;
215 }
217 double error(0);
218 for (int j(0); j < A.getRows(); ++j) {
219 for (int k(0); k < A.getRows(); ++k) {
220 complex element(0);
221 for (int i(0); i < A.getRows(); ++i) {
222 element += std::conj((*L)(i, k)) * A(i, j);
223 }
224 element -= std::conj((*L)(j, k)) * lambdas[k];
225 error += std::real(element * std::conj(element));
226 }
227 }
228 return error;
229 }
230
232 double error(0);
233 for (int i(0); i < R->getRows(); ++i) {
234 for (int j(0); j < R->getRows(); ++j) {
235 complex element(0);
236 for (int k(0); k < R->getRows(); ++k) {
237 element += std::conj((*R)(i, k)) * (*R)(j, k);
238 }
239 element -= i == j ? 1.0 : 0.0;
240 error += i == j ? 0.0 : std::real(element * std::conj(element));
241 }
242 }
243 return error;
244 }
245
246 class EigenValueComparator {
247 public:
248 bool operator()(const std::pair<int, complex> &a,
249 const std::pair<int, complex> &b) {
250 // FIXME: Move the inf code into particular implementations
251 double inf = std::numeric_limits<double>::infinity();
252 double A(std::abs(a.second) < 1E-4 ? inf : std::real(a.second));
253 double B(std::abs(b.second) < 1E-4 ? inf : std::real(b.second));
254 double diff(B - A);
255 double magnitude(std::abs(a.second) + std::abs(b.second));
256 if (std::real(diff) > +1E-13 * magnitude) return true;
257 else return false;
258 // if (std::real(diff) < -1E-13*magnitude) return false;
259 // if (std::imag(diff) > +1E-13*magnitude) return false;
260 // if (std::imag(diff) < -1E-13*magnitude) return true;
261 return a.first < b.first;
262 }
263 };
264
265protected:
267 std::vector<complex> lambdas;
268
270 const std::vector<std::pair<int, complex>> &sortedEigenValues,
272 LapackMatrix<complex> unsortedU(U);
273 for (int j(0); j < U.getRows(); ++j) {
274 int unsortedJ(sortedEigenValues[j].first);
275 for (int i(0); i < U.getRows(); ++i) {
276 U(i, j) = unsortedU(i, unsortedJ);
277 }
278 }
279 }
280};
281} // namespace sisi4s
282
283#endif
#define EXCEPTION(message)
Definition Exception.hpp:8
void zgeev_(const char *jobvLeft, const char *jobvRight, const int *n, const sisi4s::Complex64 *a, const int *lda, sisi4s::Complex64 *w, sisi4s::Complex64 *vLeft, const int *ldvLeft, sisi4s::Complex64 *vRight, const int *ldvRight, sisi4s::Complex64 *work, const int *workSize, sisi4s::Float64 *rwork, int *info)
#define NEW(TYPE,...)
Definition SharedPointer.hpp:10
#define PTR(TYPE)
Definition SharedPointer.hpp:8
bool operator()(const std::pair< int, complex > &a, const std::pair< int, complex > &b)
Definition LapackGeneralEigenSystem.hpp:248
void orderEigenVectors(const std::vector< std::pair< int, complex > > &sortedEigenValues, LapackMatrix< complex > &U)
Definition LapackGeneralEigenSystem.hpp:269
const LapackMatrix< complex > & getRightEigenVectors() const
Definition LapackGeneralEigenSystem.hpp:186
std::vector< complex > lambdas
Definition LapackGeneralEigenSystem.hpp:267
L
Definition LapackGeneralEigenSystem.hpp:266
const LapackMatrix< complex > & getLeftEigenVectors() const
Definition LapackGeneralEigenSystem.hpp:194
double leftEigenError(const LapackMatrix< complex > &A)
Definition LapackGeneralEigenSystem.hpp:216
~LapackGeneralEigenSystem()
Definition LapackGeneralEigenSystem.hpp:182
LapackGeneralEigenSystem(const LapackMatrix< complex > &A_, bool computeRightEigenvectors=true, bool computeLeftEigenvectors=false)
Definition LapackGeneralEigenSystem.hpp:114
const std::vector< complex > & getEigenValues() const
Definition LapackGeneralEigenSystem.hpp:184
double rightEigenError(const LapackMatrix< complex > &A)
Definition LapackGeneralEigenSystem.hpp:202
double biorthogonalError()
Definition LapackGeneralEigenSystem.hpp:231
bool operator()(const std::pair< int, double > &a, const std::pair< int, double > &b)
Definition LapackGeneralEigenSystem.hpp:22
Definition LapackGeneralEigenSystem.hpp:15
Definition LapackMatrix.hpp:11
const F * getValues() const
Returns the pointer to the column major data.
Definition LapackMatrix.hpp:69
int getColumns() const
Definition LapackMatrix.hpp:64
int getRows() const
Definition LapackMatrix.hpp:63
Definition Algorithm.hpp:10
Complex< real > complex
Definition Complex.hpp:17