Spectra 1.1.0
Header-only C++ Library for Large Scale Eigenvalue Problems
Loading...
Searching...
No Matches
JDSymEigsBase.h
1// Copyright (C) 2020 Netherlands eScience Center <J.Wehner@esciencecenter.nl>
2//
3// This Source Code Form is subject to the terms of the Mozilla
4// Public License v. 2.0. If a copy of the MPL was not distributed
5// with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7#ifndef SPECTRA_JD_SYM_EIGS_BASE_H
8#define SPECTRA_JD_SYM_EIGS_BASE_H
9
10#include <Eigen/Core>
11#include <vector> // std::vector
12#include <cmath> // std::abs, std::pow
13#include <algorithm> // std::min
14#include <stdexcept> // std::invalid_argument
15#include <iostream>
16
17#include "Util/SelectionRule.h"
18#include "Util/CompInfo.h"
19#include "LinAlg/SearchSpace.h"
20#include "LinAlg/RitzPairs.h"
21
22namespace Spectra {
23
33template <typename Derived, typename OpType>
34class JDSymEigsBase
35{
36protected:
37 using Index = Eigen::Index;
38 using Scalar = typename OpType::Scalar;
39 using Matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
40 using Vector = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;
41
42 const OpType& m_matrix_operator; // object to conduct matrix operation,
43 // e.g. matrix-vector product
44 Index niter_ = 0;
45 const Index m_number_eigenvalues; // number of eigenvalues requested
46 Index m_max_search_space_size;
47 Index m_initial_search_space_size;
48 Index m_correction_size; // how many correction vectors are added in each iteration
49 RitzPairs<Scalar> m_ritz_pairs; // Ritz eigen pair structure
50 SearchSpace<Scalar> m_search_space; // search space
51
52private:
53 CompInfo m_info = CompInfo::NotComputed; // status of the computation
54
55 void check_argument() const
56 {
57 if (m_number_eigenvalues < 1 || m_number_eigenvalues > m_matrix_operator.cols() - 1)
58 throw std::invalid_argument("nev must satisfy 1 <= nev <= n - 1, n is the size of matrix");
59 }
60
61 void initialize()
62 {
63 // TODO better input validation and checks
64 if (m_matrix_operator.cols() < m_max_search_space_size)
65 {
66 m_max_search_space_size = m_matrix_operator.cols();
67 }
68 if (m_matrix_operator.cols() < m_initial_search_space_size + m_correction_size)
69 {
70 m_initial_search_space_size = m_matrix_operator.cols() / 3;
71 m_correction_size = m_matrix_operator.cols() / 3;
72 }
73 }
74
75public:
76 JDSymEigsBase(OpType& op, Index nev, Index nvec_init, Index nvec_max) :
77 m_matrix_operator(op),
78 m_number_eigenvalues(nev),
79 m_max_search_space_size(nvec_max < op.rows() ? nvec_max : 10 * m_number_eigenvalues),
80 m_initial_search_space_size(nvec_init < op.rows() ? nvec_init : 2 * m_number_eigenvalues),
81 m_correction_size(m_number_eigenvalues)
82 {
83 check_argument();
84 initialize();
85 }
86
87 JDSymEigsBase(OpType& op, Index nev) :
88 JDSymEigsBase(op, nev, 2 * nev, 10 * nev) {}
89
93 void set_max_search_space_size(Index max_search_space_size)
94 {
95 m_max_search_space_size = max_search_space_size;
96 }
97
100 void set_correction_size(Index correction_size)
101 {
102 m_correction_size = correction_size;
103 }
104
108 void set_initial_search_space_size(Index initial_search_space_size)
109 {
110 m_initial_search_space_size = initial_search_space_size;
111 }
112
116 virtual ~JDSymEigsBase() {}
117
122 CompInfo info() const { return m_info; }
123
127 Index num_iterations() const { return niter_; }
128
129 Vector eigenvalues() const { return m_ritz_pairs.ritz_values().head(m_number_eigenvalues); }
130
131 Matrix eigenvectors() const { return m_ritz_pairs.ritz_vectors().leftCols(m_number_eigenvalues); }
132
133 Index compute(SortRule selection = SortRule::LargestMagn, Index maxit = 100,
134 Scalar tol = 100 * Eigen::NumTraits<Scalar>::dummy_precision())
135 {
136 Derived& derived = static_cast<Derived&>(*this);
137 Matrix intial_space = derived.setup_initial_search_space(selection);
138 return compute_with_guess(intial_space, selection, maxit, tol);
139 }
140
141 Index compute_with_guess(const Eigen::Ref<const Matrix>& initial_space,
143 Index maxit = 100,
144 Scalar tol = 100 * Eigen::NumTraits<Scalar>::dummy_precision())
145
146 {
147 m_search_space.initialize_search_space(initial_space);
148 niter_ = 0;
149 for (niter_ = 0; niter_ < maxit; niter_++)
150 {
151 bool do_restart = (m_search_space.size() > m_max_search_space_size);
152
153 if (do_restart)
154 {
155 m_search_space.restart(m_ritz_pairs, m_initial_search_space_size);
156 }
157
158 m_search_space.update_operator_basis_product(m_matrix_operator);
159
160 Eigen::ComputationInfo small_problem_info = m_ritz_pairs.compute_eigen_pairs(m_search_space);
161 if (small_problem_info != Eigen::ComputationInfo::Success)
162 {
164 break;
165 }
166 m_ritz_pairs.sort(selection);
167
168 bool converged = m_ritz_pairs.check_convergence(tol, m_number_eigenvalues);
169 if (converged)
170 {
171 m_info = CompInfo::Successful;
172 break;
173 }
174 else if (niter_ == maxit - 1)
175 {
177 break;
178 }
179 Derived& derived = static_cast<Derived&>(*this);
180 Matrix corr_vect = derived.calculate_correction_vector();
181
182 m_search_space.extend_basis(corr_vect);
183 }
184 return (m_ritz_pairs.converged_eigenvalues()).template cast<Index>().head(m_number_eigenvalues).sum();
185 }
186};
187
188} // namespace Spectra
189
190#endif // SPECTRA_JD_SYM_EIGS_BASE_H
CompInfo info() const
void set_correction_size(Index correction_size)
Index num_iterations() const
void set_initial_search_space_size(Index initial_search_space_size)
void set_max_search_space_size(Index max_search_space_size)
@ Successful
Computation was successful.
Definition CompInfo.h:19