Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement DPR #21

Merged
merged 22 commits into from
Jul 2, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions include/Spectra/DavidsonSymEig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (C) 2020 Netherlands eScience Center <[email protected]>
//
// 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 <Eigen/Dense>
#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 <typename OpType>
class DavidsonSymEig : public JDSymEigsBase<DavidsonSymEig<OpType>,OpType>
{
private:
using Index = Eigen::Index;
using Scalar = typename OpType::Scalar;
using Matrix = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;
using Vector = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;

Vector diagonal_;

public:
DavidsonSymEig(OpType& op, Index nev) :
JDSymEigsBase<DavidsonSymEig<OpType>,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<Eigen::Index> 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
9 changes: 4 additions & 5 deletions include/Spectra/JDSymEigsBase.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (C) 2016-2020 Yixuan Qiu <[email protected]>
// Copyright (C) 2020 Netherlands eScience Center <[email protected]>
//
// 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
Expand Down Expand Up @@ -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_),
Expand Down Expand Up @@ -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<Scalar> ritz_pairs_; // Ritz eigen pair structure
SearchSpace<Scalar> 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");
}

Expand Down
8 changes: 4 additions & 4 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@ 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
SymEigs.cpp
SymEigsShift.cpp
SymGEigsCholesky.cpp
SymGEigsRegInv.cpp
SymGEigsShift.cpp
JDSymEigsBase.cpp
RitzPairs.cpp
SearchSpace.cpp
)

foreach(TEST_SOURCE ${test_target_sources})
Expand Down
20 changes: 20 additions & 0 deletions test/DavidsonSymEig.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <Eigen/Core>
#include <Eigen/SparseCore>

#include <Spectra/DavidsonSymEig.h>
#include <Spectra/MatOp/DenseGenMatProd.h>

using namespace Spectra;

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

TEMPLATE_TEST_CASE("Constructing DavidsonSymEig", "[DavidsonSymEig]", float, double)
{
using Matrix = Eigen::Matrix<TestType, Eigen::Dynamic, Eigen::Dynamic>;
const Matrix A = Matrix::Random(10, 10);
DenseGenMatProd<TestType> op(A);
DavidsonSymEig<DenseGenMatProd<TestType>> eigs{op, 5};
REQUIRE(eigs.num_iterations() == 0);
REQUIRE(eigs.info() == Spectra::CompInfo::NotComputed);
}
6 changes: 2 additions & 4 deletions test/JDSymEigsBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ class JDMock : public JDSymEigsBase<JDMock<OpType>, OpType>
public:
JDMock(OpType& op, Index nev) :
JDSymEigsBase<JDMock<OpType>,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);
}
};
Expand Down