14#include <spdlog/spdlog.h>
23#if defined(WITH_MKL) || defined(WITH_LAPACKE)
24lapack_int evr(
int matrix_layout,
char jobz,
char range,
char uplo, lapack_int n,
float *a,
25 lapack_int lda,
float vl,
float vu, lapack_int il, lapack_int iu,
float abstol,
26 lapack_int *m,
float *w,
float *z, lapack_int ldz, lapack_int *isuppz) {
27 return LAPACKE_ssyevr(matrix_layout, jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w,
31lapack_int evr(
int matrix_layout,
char jobz,
char range,
char uplo, lapack_int n,
double *a,
32 lapack_int lda,
double vl,
double vu, lapack_int il, lapack_int iu,
double abstol,
33 lapack_int *m,
double *w,
double *z, lapack_int ldz, lapack_int *isuppz) {
34 return LAPACKE_dsyevr(matrix_layout, jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w,
38lapack_int evr(
int matrix_layout,
char jobz,
char range,
char uplo, lapack_int n,
39 lapack_complex_float *a, lapack_int lda,
float vl,
float vu, lapack_int il,
40 lapack_int iu,
float abstol, lapack_int *m,
float *w, lapack_complex_float *z,
41 lapack_int ldz, lapack_int *isuppz) {
42 return LAPACKE_cheevr(matrix_layout, jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w,
46lapack_int evr(
int matrix_layout,
char jobz,
char range,
char uplo, lapack_int n,
47 lapack_complex_double *a, lapack_int lda,
double vl,
double vu, lapack_int il,
48 lapack_int iu,
double abstol, lapack_int *m,
double *w, lapack_complex_double *z,
49 lapack_int ldz, lapack_int *isuppz) {
50 return LAPACKE_zheevr(matrix_layout, jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w,
54template <
typename Scalar>
55template <
typename ScalarLim>
56EigenSystemH<Scalar> DiagonalizerLapackeEvr<Scalar>::dispatch_eigh(
57 const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix,
58 std::optional<real_t> min_eigenvalue, std::optional<real_t> max_eigenvalue,
double rtol)
const {
60 int dim = matrix.rows();
61 bool has_range = min_eigenvalue.has_value() || max_eigenvalue.has_value();
66 this->
template subtract_mean<ScalarLim>(matrix, shift, rtol);
67 real_lim_t scaling = shifted_matrix.norm();
69 if (scaling < std::numeric_limits<real_lim_t>::epsilon()) {
73 shifted_matrix /= scaling;
78 char range_char = has_range ?
'V' :
'A';
80 real_lim_t abstol = 0.1 * rtol;
83 real_lim_t vl = (min_eigenvalue.value_or(-1) - shift) / scaling;
84 real_lim_t vu = (max_eigenvalue.value_or(1) - shift) / scaling;
88 std::vector<lapack_int> isuppz(
static_cast<size_t>(2 * dim));
90 evr(LAPACK_COL_MAJOR, jobz, range_char, uplo, dim, shifted_matrix.data(), dim, vl, vu, il,
91 iu, abstol, &m, evals.data(), evecs.data(), dim, isuppz.data());
95 throw std::invalid_argument(
96 fmt::format(
"Diagonalization error: Argument {} to the "
97 "lapacke_evr routine had an illegal value (the counting of the "
98 "arguments starts with one). For a documentation of lapacke_evr, see "
99 "https://www.intel.com/content/www/us/en/docs/onemkl/"
100 "developer-reference-c/2025-1/syevr.html.",
103 throw std::runtime_error(
104 fmt::format(
"Diagonalization error: The lapacke_evr routine failed with error code {}. "
105 "Try to set a lower 'rtol'.",
110 evals.conservativeResize(m);
113 return {evecs.leftCols(m).sparseView(1, 0.5 * rtol / std::sqrt(dim)).template cast<Scalar>(),
114 this->add_mean(evals, shift)};
117template <
typename Scalar>
119 : DiagonalizerInterface<Scalar>(float_type) {}
121template <
typename Scalar>
123DiagonalizerLapackeEvr<Scalar>::eigh(
const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix,
125 return this->eigh(matrix, std::nullopt, std::nullopt, rtol);
128template <
typename Scalar>
130DiagonalizerLapackeEvr<Scalar>::eigh(
const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix,
131 std::optional<real_t> min_eigenvalue,
132 std::optional<real_t> max_eigenvalue,
double rtol)
const {
133 switch (this->float_type) {
134 case FloatType::FLOAT32:
135 return dispatch_eigh<traits::restricted_t<Scalar, FloatType::FLOAT32>>(
136 matrix, min_eigenvalue, max_eigenvalue, rtol);
137 case FloatType::FLOAT64:
138 return dispatch_eigh<traits::restricted_t<Scalar, FloatType::FLOAT64>>(
139 matrix, min_eigenvalue, max_eigenvalue, rtol);
141 throw std::invalid_argument(
"Unsupported floating point precision.");
147template <
typename Scalar>
150 throw std::runtime_error(
"The lapacke_evr routine is not available in this build. Please use a "
151 "different diagonalizer.");
154template <
typename Scalar>
156 const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> & ,
double )
const {
160template <
typename Scalar>
162 const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> & ,
163 std::optional<real_t> , std::optional<real_t> ,
EigenSystemH< Scalar > eigh(const Eigen::SparseMatrix< Scalar, Eigen::RowMajor > &matrix, double rtol) const override
DiagonalizerLapackeEvr(FloatType float_type=FloatType::FLOAT64)
Matrix< Type, Dynamic, Dynamic > MatrixX
Matrix< Type, Dynamic, 1 > VectorX