sisi4s
Loading...
Searching...
No Matches
EigenSystemDavidson.hpp
Go to the documentation of this file.
1#ifndef EIGEN_SYSTEM_DAVIDSON_DEFINED
2# define EIGEN_SYSTEM_DAVIDSON_DEFINED
3
4# include <util/LapackMatrix.hpp>
7# include <math/Complex.hpp>
8
9# include <vector>
10# include <iomanip>
11# include <utility>
12# include <algorithm>
13# include <memory>
14
15namespace sisi4s {
16template <typename H, typename P, typename V>
18public:
19 typedef typename V::FieldType F;
20
54 const int eigenVectorsCount_,
55 P *p_,
56 const double toleranceVectors,
57 const double toleranceEnergy,
58 const unsigned int maxBasisSize_,
59 const unsigned int maxIterations_,
60 const unsigned int minIterations_)
61 : h(h_)
62 , eigenVectorsCount(eigenVectorsCount_)
63 , p(p_)
64 , tolerance({toleranceEnergy, toleranceVectors})
65 , maxBasisSize(maxBasisSize_)
66 , maxIterations(maxIterations_)
67 , minIterations(minIterations_)
68 , eigenValues(eigenVectorsCount_) {}
69
70 virtual void run() = 0;
71
72 const std::vector<complex> &getEigenValues() const { return eigenValues; }
73
74 const std::vector<V> &getRightEigenVectors() const {
75 return rightEigenVectors;
76 }
77
78 const std::vector<V> &getLeftEigenVectors() const { return leftEigenVectors; }
79
85 void refreshOnMaxBasisSize(const bool value) {
87 }
88
94
95protected:
96 H *h;
98 P *p;
99 const struct {
100 double energy;
101 double vectors;
103 unsigned int maxBasisSize = 1000;
104 unsigned int maxIterations = 1000;
105 unsigned int minIterations = 1;
106 std::vector<int> refreshIterations = std::vector<int>{{}};
108 std::vector<complex> eigenValues;
109 std::vector<V> rightEigenVectors;
110 std::vector<V> leftEigenVectors;
111};
112
113template <typename H, typename P, typename V>
115public:
116 typedef typename V::FieldType F;
117
119 const int eigenVectorsCount_,
120 P *p_,
121 const double toleranceVectors,
122 const double toleranceEnergy,
123 const unsigned int maxBasisSize_,
124 const unsigned int maxIterations_,
125 const unsigned int minIterations_)
126 : EigenSystemDavidson<H, P, V>(h_,
127 eigenVectorsCount_,
128 p_,
129 toleranceVectors,
130 toleranceEnergy,
131 maxBasisSize_,
132 maxIterations_,
133 minIterations_) {}
134
135 void run() {
136 LOG(1, "Davidson")
137 .flags(std::ios::right | std::ios::scientific | std::ios::showpos);
138 // get inital estimates for rEV = initial B matrix
139 LOG(1, "Davidson") << "Initial basis retrieving" << std::endl;
140 {
141 std::vector<typename P::V> initialBasis(
142 this->p->getInitialBasis(this->eigenVectorsCount));
143 this->rightEigenVectors.assign(initialBasis.begin(), initialBasis.end());
144 }
145 LOG(1, "Davidson") << "Initial basis retrieved" << std::endl;
146 std::vector<V> rightBasis(this->rightEigenVectors);
147 std::vector<V> leftEigenVectors(this->rightEigenVectors);
148 std::vector<complex> previousReducedMatrixElements;
149
150 // begin convergence loop
151 double rms;
152 double energyDifference;
153 unsigned int iterationCount(0);
154 do {
155 LOG(1, "Davidson") << "iteration=" << (iterationCount + 1) << std::endl;
156 LOG(0, "Davidson") << "It."
157 << " "
158 << "St."
159 << " "
160 << "#basis"
161 << " "
162 << "R(energy)"
163 << " "
164 << "I(energy)"
165 << " " <<
166 //"norm" << " " <<
167 "rms"
168 << " "
169 << "Delta E"
170 << " " << std::endl;
171
172 auto previousEigenvalues(this->eigenValues);
173
174# ifdef DEBUGG
175 LOG(1, "Davidson") << "Writing out overlap matrix" << std::endl;
176 std::string overlapFile("overlap-matrix-");
177 overlapFile += std::to_string(iterationCount);
178 for (unsigned int i(0); i < rightBasis.size(); i++) {
179 for (unsigned int j(0); j < rightBasis.size(); j++) {
180 complex overlap(rightBasis[i].dot(rightBasis[j]));
181 FILE(overlapFile) << overlap << " ";
182 }
183 FILE(overlapFile) << std::endl;
184 }
185# endif
186
187 // Check if a refreshment should be done
188 if (std::find(this->refreshIterations.begin(),
189 this->refreshIterations.end(),
190 iterationCount + 1)
191 != this->refreshIterations.end()
192 || (this->refreshOnMaxBasisSize()
193 && rightBasis.size() >= this->maxBasisSize)) {
194 LOG(1, "Davidson") << "Refreshing current basis!" << std::endl;
195 rightBasis.resize(this->eigenVectorsCount);
196 this->eigenValues.resize(this->eigenVectorsCount);
197 for (unsigned int i(0); i < rightBasis.size(); i++) {
198 rightBasis[i] *= F(0);
199 rightBasis[i] += this->rightEigenVectors[i];
200 }
201
202 LOG(1, "Davidson") << "Orthonormalizing the refreshed basis"
203 << std::endl;
204 for (unsigned int i(0); i < rightBasis.size(); i++) {
205 for (unsigned int j(0); j < i; j++) {
206 rightBasis[i] -= rightBasis[j] * rightBasis[j].dot(rightBasis[i]);
207 }
208 F refreshedVectorNorm(std::sqrt(rightBasis[i].dot(rightBasis[i])));
209 // TODO: Check if refreshedVectorNorm is 0
210 rightBasis[i] *= 1.0 / refreshedVectorNorm;
211 }
212
213 // handling the caching of the reduced matrix
214 previousReducedMatrixElements.resize(0);
215
216# ifdef DEBUGG
217 LOG(1, "Davidson") << "Writing out overlap matrix" << std::endl;
218 std::string refreshOverlapFile("refreshed-overlap-matrix-");
219 refreshOverlapFile += std::to_string(iterationCount);
220 for (unsigned int i(0); i < rightBasis.size(); i++) {
221 for (unsigned int j(0); j < rightBasis.size(); j++) {
222 complex roverlap(rightBasis[i].dot(rightBasis[j]));
223 FILE(refreshOverlapFile) << roverlap << " ";
224 }
225 FILE(refreshOverlapFile) << std::endl;
226 }
227# endif
228 }
229
230 unsigned int previousBasisSize(
231 std::sqrt(previousReducedMatrixElements.size()));
232 // compute reduced H by projection onto subspace spanned by rightBasis
233 LapackMatrix<complex> reducedH(rightBasis.size(), rightBasis.size());
234
235 for (unsigned int j(0); j < previousBasisSize; ++j) {
236 for (unsigned int i(0); i < previousBasisSize; ++i) {
237 reducedH(i, j) =
238 previousReducedMatrixElements[i + previousBasisSize * j];
239 }
240 }
241
242 auto previousReducedMatrixElementsCopy(previousReducedMatrixElements);
243 previousReducedMatrixElements.resize(rightBasis.size()
244 * rightBasis.size());
245
246 for (unsigned int j(0); j < previousReducedMatrixElements.size(); ++j) {
247 previousReducedMatrixElements[j] = complex(0);
248 }
249
250 for (unsigned int j(0); j < previousBasisSize; ++j) {
251 for (unsigned int i(0); i < previousBasisSize; ++i) {
252 previousReducedMatrixElements[i + rightBasis.size() * j] =
253 previousReducedMatrixElementsCopy[i + previousBasisSize * j];
254 }
255 }
256
257 // LOG(1,"Davidson") << "Computing <basis|H|new>" << std::endl;
258 for (unsigned int j(0); j < rightBasis.size(); ++j) {
259 // LOG(1,"Davidson") << "Computing " << j << std::endl;
260 V HBj(this->h->right_apply(rightBasis[j]));
261 for (unsigned int i(previousBasisSize); i < rightBasis.size(); ++i) {
262 // LOG(1,"Davidson") << i << "," << j << std::endl;
263 reducedH(i, j) = rightBasis[i].dot(HBj);
264 previousReducedMatrixElements[i + rightBasis.size() * j] =
265 reducedH(i, j);
266 }
267 }
268
269 if (previousBasisSize > 0) {
270 // LOG(1,"Davidson") << "Computing <new|H|basis>" << std::endl;
271 for (unsigned int j(previousBasisSize); j < rightBasis.size(); ++j) {
272 V HBj(this->h->right_apply(rightBasis[j]));
273 for (unsigned int i(0); i < rightBasis.size(); ++i) {
274 // LOG(1,"Davidson") << "Creating " << i << "," << j << std::endl;
275 reducedH(i, j) = rightBasis[i].dot(HBj);
276 previousReducedMatrixElements[i + rightBasis.size() * j] =
277 reducedH(i, j);
278 }
279 }
280 }
281
282 // compute K lowest reduced eigenvalues and vectors of reduced H
283 LapackMatrix<complex> reducedEigenVectors(rightBasis.size(),
284 rightBasis.size());
285 LapackGeneralEigenSystem<complex> reducedEigenSystem(reducedH,
286 true,
287 true);
288
289# ifdef DEBUGG
290 LOG(1, "Davidson") << "Writing out reduced overlap matrix" << std::endl;
291 std::string reducedOverlapFile("reduced-overlap-matrix-");
292 reducedOverlapFile += std::to_string(iterationCount);
293 for (unsigned int i(0); i < rightBasis.size(); i++) {
294 for (unsigned int j(0); j < rightBasis.size(); j++) {
295 complex redoverlap(0);
296 for (int c(0); c < reducedH.getColumns(); ++c) {
297 redoverlap +=
298 std::conj(reducedEigenSystem.getLeftEigenVectors()(c, i))
299 * reducedEigenSystem.getRightEigenVectors()(c, j);
300 }
301 FILE(reducedOverlapFile) << redoverlap << " ";
302 }
303 FILE(reducedOverlapFile) << std::endl;
304 }
305
306 LOG(1, "Davidson") << "Writing out reducedRR overlap matrix" << std::endl;
307 std::string reducedRROverlapFile("reduced-rr-overlap-matrix-");
308 reducedRROverlapFile += std::to_string(iterationCount);
309 for (unsigned int i(0); i < rightBasis.size(); i++) {
310 for (unsigned int j(0); j < rightBasis.size(); j++) {
311 complex redRROverlap(0);
312 for (int c(0); c < reducedH.getColumns(); ++c) {
313 redRROverlap +=
314 std::conj(reducedEigenSystem.getRightEigenVectors()(c, i))
315 * reducedEigenSystem.getRightEigenVectors()(c, j);
316 }
317 FILE(reducedRROverlapFile) << redRROverlap << " ";
318 }
319 FILE(reducedRROverlapFile) << std::endl;
320 }
321# endif
322
323 // begin rightBasis extension loop for each k
324 rms = 0.0;
325 energyDifference = 0.0;
326 for (unsigned int k(0); k < this->eigenValues.size(); ++k) {
327 // get estimated eigenvalue
328 this->eigenValues[k] = reducedEigenSystem.getEigenValues()[k];
329
330 // compute estimated eigenvector by expansion in rightBasis
331 this->rightEigenVectors[k] *= F(0);
332 for (int b(0); b < reducedH.getColumns(); ++b) {
333 // complex c(
334 // reducedEigenSystem.getRightEigenVectors()(b,k)
335 //);
336 // this->rightEigenVectors[k] += c * rightBasis[b];
337 this->rightEigenVectors[k] +=
338 rightBasis[b]
340 reducedEigenSystem.getRightEigenVectors()(b, k));
341 }
342
343 leftEigenVectors[k] *= F(0);
344 for (int b(0); b < reducedH.getColumns(); ++b) {
345 leftEigenVectors[k] +=
346 rightBasis[b]
348 reducedEigenSystem.getLeftEigenVectors()(b, k));
349 }
350
351# ifdef DEBUGG
352 complex lapackNorm(0);
353 complex lapackNormConjLR(0);
354 complex lapackNormConjRR(0);
355 for (int c(0); c < reducedH.getColumns(); ++c) {
356 lapackNormConjRR +=
357 std::conj(reducedEigenSystem.getRightEigenVectors()(c, k))
358 * reducedEigenSystem.getRightEigenVectors()(c, k);
359 lapackNormConjLR +=
360 std::conj(reducedEigenSystem.getLeftEigenVectors()(c, k))
361 * reducedEigenSystem.getRightEigenVectors()(c, k);
362 lapackNorm += reducedEigenSystem.getLeftEigenVectors()(c, k)
363 * reducedEigenSystem.getRightEigenVectors()(c, k);
364 }
365# endif
366
367 const F rightNorm(std::sqrt(
368 this->rightEigenVectors[k].dot(this->rightEigenVectors[k])));
369
370 const F leftRightNorm(
371 std::sqrt(leftEigenVectors[k].dot(this->rightEigenVectors[k])));
372
373 // compute residuum
374 V residuum(this->h->right_apply(this->rightEigenVectors[k]));
375 const double kNorm = std::real(
376 this->rightEigenVectors[k].dot(this->rightEigenVectors[k]));
377 residuum -= this->rightEigenVectors[k]
379 rms += std::real(residuum.dot(residuum)) / kNorm;
380
381 // compute correction using preconditioner
382 V correction(this->p->getCorrection(this->eigenValues[k], residuum));
383
384 // orthonormalize and append to rightBasis
385 for (unsigned int b(0); b < rightBasis.size(); ++b) {
386 correction -= rightBasis[b] * rightBasis[b].dot(correction);
387 }
388 const F correction_norm(std::sqrt(correction.dot(correction)));
389 energyDifference +=
390 std::abs(previousEigenvalues[k] - this->eigenValues[k]);
391
392 LOG(0, "DavidsonIt")
393 << iterationCount + 1 << " " << k + 1 << " " << rightBasis.size()
394 << " " << std::setprecision(15) << std::setw(23)
395 << this->eigenValues[k].real() << " " << this->eigenValues[k].imag()
396 << " " <<
397 // rightNorm << " " <<
398 rms << " " << energyDifference / this->eigenVectorsCount << " "
399 << std::endl;
400
401# ifdef DEBUGG
402 OUT() << " " << rightNorm << " " << leftRightNorm
403 << " " << lapackNorm << " " << lapackNormConjLR << " "
404 << lapackNormConjRR << " " << std::endl;
405# endif
406
407 if (std::abs(correction_norm) < 1E-6) continue;
408 correction *= 1.0 / correction_norm;
409 rightBasis.push_back(correction);
410 }
411
412 ++iterationCount;
413
414 // end rightBasis extension loop
415 } while ((iterationCount + 1 <= this->minIterations)
416 || ((rms >= this->eigenVectorsCount * this->tolerance.vectors
417 && (this->refreshOnMaxBasisSize()
418 ? true
419 : (rightBasis.size() <= this->maxBasisSize))
420 && iterationCount + 1 <= this->maxIterations)
421 && (energyDifference / this->eigenVectorsCount
422 >= this->tolerance.energy
423 && (this->refreshOnMaxBasisSize()
424 ? true
425 : (rightBasis.size() <= this->maxBasisSize))
426 && iterationCount + 1 <= this->maxIterations)));
427 // end convergence loop
428 }
429};
430
431} // namespace sisi4s
432
433#endif
434
435/*
436 MySimpleVector v;
437 MySimpleMatrix m;
438 MySimplePreconditioner<MySimpleMatrix> p
439 EigenSystemDavidson<MyVectorType> eigenSystem(m, 4, p);
440 eigenSystem.getEigenValues()[0];
441 eigenSystem.getRightEigenVectors()[0];
442*/
#define LOG(...)
Definition Log.hpp:119
#define OUT()
Provides an output stream for writing a log message of the log level specified by the argument....
Definition Log.hpp:107
#define FILE(NAME)
Definition Log.hpp:116
Definition Complex.hpp:48
Definition EigenSystemDavidson.hpp:114
EigenSystemDavidsonMono(H *h_, const int eigenVectorsCount_, P *p_, const double toleranceVectors, const double toleranceEnergy, const unsigned int maxBasisSize_, const unsigned int maxIterations_, const unsigned int minIterations_)
Definition EigenSystemDavidson.hpp:118
V::FieldType F
Definition EigenSystemDavidson.hpp:116
void run()
Definition EigenSystemDavidson.hpp:135
Definition EigenSystemDavidson.hpp:17
P * p
Definition EigenSystemDavidson.hpp:98
unsigned int maxBasisSize
Definition EigenSystemDavidson.hpp:103
const std::vector< V > & getRightEigenVectors() const
Definition EigenSystemDavidson.hpp:74
V::FieldType F
Definition EigenSystemDavidson.hpp:19
EigenSystemDavidson(H *h_, const int eigenVectorsCount_, P *p_, const double toleranceVectors, const double toleranceEnergy, const unsigned int maxBasisSize_, const unsigned int maxIterations_, const unsigned int minIterations_)
...
Definition EigenSystemDavidson.hpp:53
void refreshOnMaxBasisSize(const bool value)
Controls if the Davidson algorithm should make a refreshment of the basis whenever the maximal basis ...
Definition EigenSystemDavidson.hpp:85
unsigned int maxIterations
Definition EigenSystemDavidson.hpp:104
std::vector< V > leftEigenVectors
Definition EigenSystemDavidson.hpp:110
const struct sisi4s::EigenSystemDavidson::@0 tolerance
bool refreshOnMaxBasisSizeValue
Definition EigenSystemDavidson.hpp:107
unsigned int minIterations
Definition EigenSystemDavidson.hpp:105
int eigenVectorsCount
Definition EigenSystemDavidson.hpp:97
const std::vector< complex > & getEigenValues() const
Definition EigenSystemDavidson.hpp:72
const std::vector< V > & getLeftEigenVectors() const
Definition EigenSystemDavidson.hpp:78
double vectors
Definition EigenSystemDavidson.hpp:101
bool refreshOnMaxBasisSize()
Check wether or not the basis should be refreshed whenever the maximal basis size has been reached.
Definition EigenSystemDavidson.hpp:93
std::vector< V > rightEigenVectors
Definition EigenSystemDavidson.hpp:109
H * h
Definition EigenSystemDavidson.hpp:96
double energy
Definition EigenSystemDavidson.hpp:100
std::vector< complex > eigenValues
Definition EigenSystemDavidson.hpp:108
std::vector< int > refreshIterations
Definition EigenSystemDavidson.hpp:106
Definition LapackGeneralEigenSystem.hpp:15
Definition LapackMatrix.hpp:11
int getColumns() const
Definition LapackMatrix.hpp:64
Definition Algorithm.hpp:10
F dot(F const x, F const y)
Definition MathFunctions.hpp:45
Complex< real > complex
Definition Complex.hpp:17