diff --git a/include/Spectra/DavidsonSymEig.h b/include/Spectra/DavidsonSymEig.h new file mode 100644 index 00000000..b346b4f9 --- /dev/null +++ b/include/Spectra/DavidsonSymEig.h @@ -0,0 +1,88 @@ +// Copyright (C) 2020 Netherlands eScience Center +// +// This Source Code Form is subject to the terms of the Mozilla +// Public License v. 2.0. If a copy of the MPL was not distributed +// with this file, You can obtain one at https://mozilla.org/MPL/2.0/. + +#ifndef SPECTRA_DAVIDSON_SYM_EIG_H +#define SPECTRA_DAVIDSON_SYM_EIG_H + +#include +#include "JDSymEigsBase.h" +#include "Util/SelectionRule.h" + +namespace Spectra { + +/// +/// \ingroup EigenSolver +/// +/// This class implement the DPR correction for the Davidson algorithms. +/// The algorithms in the Davidson family only differ in how the correction +/// vectors are computed and optionally in the initial orthogonal basis set. +/// +/// the DPR correction compute the new correction vector using the following expression: +/// \f[ correction = -(\boldsymbol{D} - \rho \boldsymbol{I})^{-1} \boldsymbol{r} \f] +/// where +/// \f$D\f$ is the diagonal of the target matrix, \f$\rho\f$ the Ritz eigenvalue, +/// \f$I\f$ the identity matrix and \f$r\f$ the residue vector. +/// + +template +class DavidsonSymEig : public JDSymEigsBase,OpType> +{ +private: + using Index = Eigen::Index; + using Scalar = typename OpType::Scalar; + using Matrix = Eigen::Matrix; + using Vector = Eigen::Matrix; + + Vector diagonal_; + +public: + DavidsonSymEig(OpType& op, Index nev) : + JDSymEigsBase,OpType>{op, nev} + { + diagonal_.resize(this->matrix_operator_.rows()); + for (Index i = 0; i < op.rows(); i++) + { + diagonal_(i) = op(i, i); + } + } + + /// Create initial search space based on the diagonal + /// and the spectrum'target (highest or lowest) + /// \param selection spectrum section to target (e.g. lowest, etc.) + /// \return Matrix with the initial orthonormal basis + Matrix SetupInitialSearchSpace(SortRule selection) const + { + std::vector indices_sorted = argsort(selection, diagonal_); + + Matrix initial_basis = Matrix::Zero(this->matrix_operator_.rows(), this->initial_search_space_size_); + + for (Index k = 0; k < this->initial_search_space_size_; k++) + { + Index row = indices_sorted[k]; + initial_basis(row, k) = 1.0; + } + return initial_basis; + } + + /// compute the corrections using the DPR method. + /// \return new correction vectors. + Matrix CalculateCorrectionVector() const + { + const Matrix& residues = this->ritz_pairs_.Residues(); + const Vector& eigvals = this->ritz_pairs_.RitzValues(); + Matrix correction = Matrix::Zero(this->matrix_operator_.rows(), this->correction_size_); + for (Index k = 0; k < this->correction_size_; k++) + { + Vector tmp = eigvals(k) - diagonal_.array(); + correction.col(k) = residues.col(k).array() / tmp.array(); + } + return correction; + } +}; + +} // namespace Spectra + +#endif // SPECTRA_DAVIDSON_SYM_EIG_H \ No newline at end of file diff --git a/include/Spectra/JDSymEigsBase.h b/include/Spectra/JDSymEigsBase.h index 62648176..d682a3bd 100644 --- a/include/Spectra/JDSymEigsBase.h +++ b/include/Spectra/JDSymEigsBase.h @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2020 Yixuan Qiu +// Copyright (C) 2020 Netherlands eScience Center // // This Source Code Form is subject to the terms of the Mozilla // Public License v. 2.0. If a copy of the MPL was not distributed @@ -39,7 +39,6 @@ class JDSymEigsBase public: JDSymEigsBase(OpType& op, Index nev) : matrix_operator_(op), - operator_dimension_(op.rows()), number_eigenvalues_(nev), max_search_space_size_(10 * number_eigenvalues_), initial_search_space_size_(2 * number_eigenvalues_), @@ -94,24 +93,24 @@ class JDSymEigsBase protected: - const OpType& matrix_operator_; // object to conduct marix operation, + const OpType& matrix_operator_; // object to conduct matrix operation, // e.g. matrix-vector product Index niter_ = 0; - const Index operator_dimension_; // dimension of matrix A const Index number_eigenvalues_; // number of eigenvalues requested Index max_search_space_size_; Index initial_search_space_size_; Index correction_size_; // how many correction vectors are added in each iteration RitzPairs ritz_pairs_; // Ritz eigen pair structure SearchSpace search_space_; // search space + Index size_update_; // size of the current correction private: CompInfo info_ = CompInfo::NotComputed; // status of the computation void check_argument() const { - if (number_eigenvalues_ < 1 || number_eigenvalues_ > operator_dimension_ - 1) + if (number_eigenvalues_ < 1 || number_eigenvalues_ > matrix_operator_.cols() - 1) throw std::invalid_argument("nev must satisfy 1 <= nev <= n - 1, n is the size of matrix"); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cdcaa047..2cfe6fa3 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -2,14 +2,18 @@ set(test_target_sources) list(APPEND test_target_sources BKLDLT.cpp + DavidsonSymEig.cpp DenseGenMatProd.cpp DenseSymMatProd.cpp Eigen.cpp GenEigs.cpp GenEigsRealShift.cpp GenEigsComplexShift.cpp + JDSymEigsBase.cpp Orthogonalization.cpp QR.cpp + RitzPairs.cpp + SearchSpace.cpp SparseGenMatProd.cpp SparseSymMatProd.cpp SVD.cpp @@ -17,10 +21,6 @@ list(APPEND test_target_sources SymEigsShift.cpp SymGEigsCholesky.cpp SymGEigsRegInv.cpp - SymGEigsShift.cpp - JDSymEigsBase.cpp - RitzPairs.cpp - SearchSpace.cpp ) foreach(TEST_SOURCE ${test_target_sources}) diff --git a/test/DavidsonSymEig.cpp b/test/DavidsonSymEig.cpp new file mode 100644 index 00000000..feebc1d7 --- /dev/null +++ b/test/DavidsonSymEig.cpp @@ -0,0 +1,20 @@ +#include +#include + +#include +#include + +using namespace Spectra; + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" + +TEMPLATE_TEST_CASE("Constructing DavidsonSymEig", "[DavidsonSymEig]", float, double) +{ + using Matrix = Eigen::Matrix; + const Matrix A = Matrix::Random(10, 10); + DenseGenMatProd op(A); + DavidsonSymEig> eigs{op, 5}; + REQUIRE(eigs.num_iterations() == 0); + REQUIRE(eigs.info() == Spectra::CompInfo::NotComputed); +} \ No newline at end of file diff --git a/test/JDSymEigsBase.cpp b/test/JDSymEigsBase.cpp index 2b7035b8..3f3b714e 100644 --- a/test/JDSymEigsBase.cpp +++ b/test/JDSymEigsBase.cpp @@ -23,13 +23,11 @@ class JDMock : public JDSymEigsBase, OpType> public: JDMock(OpType& op, Index nev) : JDSymEigsBase,OpType>(op, nev) {} - Matrix SetupInitialSearchSpace(SortRule) const final - { + Matrix SetupInitialSearchSpace(SortRule) const { return Matrix::Zero(0, 0); } - Matrix CalculateCorrectionVector() const final - { + Matrix CalculateCorrectionVector() const { return Matrix::Zero(0, 0); } };