pairinteraction
A Rydberg Interaction Calculator
DiagonalizerLapackeEvd.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2024 Pairinteraction Developers
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
5
9
10#include <Eigen/Dense>
11#include <cmath>
12#include <fmt/core.h>
13#include <spdlog/spdlog.h>
14
15#ifdef WITH_MKL
16#include <mkl.h>
17#elif WITH_LAPACKE
18#include <lapacke.h>
19#endif
20
21namespace pairinteraction {
22#if defined(WITH_MKL) || defined(WITH_LAPACKE)
23lapack_int evd(int matrix_layout, char jobz, char uplo, lapack_int n, float *a, lapack_int lda,
24 float *w) {
25 return LAPACKE_ssyevd(matrix_layout, jobz, uplo, n, a, lda, w);
26};
27
28lapack_int evd(int matrix_layout, char jobz, char uplo, lapack_int n, double *a, lapack_int lda,
29 double *w) {
30 return LAPACKE_dsyevd(matrix_layout, jobz, uplo, n, a, lda, w);
31};
32
33lapack_int evd(int matrix_layout, char jobz, char uplo, lapack_int n, lapack_complex_float *a,
34 lapack_int lda, float *w) {
35 return LAPACKE_cheevd(matrix_layout, jobz, uplo, n, a, lda, w);
36};
37
38lapack_int evd(int matrix_layout, char jobz, char uplo, lapack_int n, lapack_complex_double *a,
39 lapack_int lda, double *w) {
40 return LAPACKE_zheevd(matrix_layout, jobz, uplo, n, a, lda, w);
41};
42
43template <typename Scalar>
44template <typename ScalarLim>
45EigenSystemH<Scalar> DiagonalizerLapackeEvd<Scalar>::dispatch_eigh(
46 const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix, double rtol) const {
47 using real_lim_t = typename traits::NumTraits<ScalarLim>::real_t;
48 int dim = matrix.rows();
49
50 // Subtract the mean of the diagonal elements from the diagonal
51 real_t shift{};
52 Eigen::MatrixX<ScalarLim> evecs = this->template subtract_mean<ScalarLim>(matrix, shift, rtol);
53
54 // Diagonalize the shifted matrix
55 char jobz = 'V'; // eigenvalues and eigenvectors are computed
56 char uplo = 'U'; // full matrix is stored, upper is used
57
59 lapack_int info = evd(LAPACK_COL_MAJOR, jobz, uplo, dim, evecs.data(), dim, evals.data());
60
61 if (info != 0) {
62 if (info < 0) {
63 throw std::invalid_argument(
64 fmt::format("Diagonalization error: Argument {} to the "
65 "lapacke_evd routine had an illegal value (the counting of the "
66 "arguments starts with one). For a documentation of lapacke_evd, see "
67 "https://www.intel.com/content/www/us/en/docs/onemkl/"
68 "developer-reference-c/2025-1/syevd.html.",
69 -info));
70 }
71 throw std::runtime_error(fmt::format(
72 "Diagonalization error: The lapacke_evd routine failed with error code {}.", info));
73 }
74
75 return {evecs.sparseView(1, 0.5 * rtol / std::sqrt(dim)).template cast<Scalar>(),
76 this->add_mean(evals, shift)};
77}
78
79template <typename Scalar>
81 : DiagonalizerInterface<Scalar>(float_type) {}
82
83template <typename Scalar>
84EigenSystemH<Scalar>
85DiagonalizerLapackeEvd<Scalar>::eigh(const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix,
86 double rtol) const {
87 switch (this->float_type) {
88 case FloatType::FLOAT32:
89 return dispatch_eigh<traits::restricted_t<Scalar, FloatType::FLOAT32>>(matrix, rtol);
90 case FloatType::FLOAT64:
91 return dispatch_eigh<traits::restricted_t<Scalar, FloatType::FLOAT64>>(matrix, rtol);
92 default:
93 throw std::invalid_argument("Unsupported floating point precision.");
94 }
95}
96
97#else
98
99template <typename Scalar>
101 : DiagonalizerInterface<Scalar>(float_type) {
102 throw std::runtime_error("The lapacke_evd routine is not available in this build. Please use a "
103 "different diagonalizer.");
104}
105
106template <typename Scalar>
108 const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> & /*matrix*/, double /*rtol*/) const {
109 std::abort(); // can't happen because the constructor throws
110}
111
112#endif // WITH_MKL || WITH_LAPACKE
113
114// Explicit instantiations
115template class DiagonalizerLapackeEvd<double>;
117} // namespace pairinteraction
EigenSystemH< Scalar > eigh(const Eigen::SparseMatrix< Scalar, Eigen::RowMajor > &matrix, double rtol) const override
DiagonalizerLapackeEvd(FloatType float_type=FloatType::FLOAT64)
Matrix< Type, Dynamic, Dynamic > MatrixX
Matrix< Type, Dynamic, 1 > VectorX