13#include <spdlog/spdlog.h>
22void feast(
const char *uplo,
const MKL_INT *n,
const float *a,
const MKL_INT *lda, MKL_INT *fpm,
23 float *epsout, MKL_INT *loop,
const float *emin,
const float *emax, MKL_INT *m0,
24 float *e,
float *x, MKL_INT *m,
float *res, MKL_INT *info) {
25 sfeast_syev(uplo, n, a, lda, fpm, epsout, loop, emin, emax, m0, e, x, m, res, info);
28void feast(
const char *uplo,
const MKL_INT *n,
const double *a,
const MKL_INT *lda, MKL_INT *fpm,
29 double *epsout, MKL_INT *loop,
const double *emin,
const double *emax, MKL_INT *m0,
30 double *e,
double *x, MKL_INT *m,
double *res, MKL_INT *info) {
31 dfeast_syev(uplo, n, a, lda, fpm, epsout, loop, emin, emax, m0, e, x, m, res, info);
34void feast(
const char *uplo,
const MKL_INT *n,
const MKL_Complex8 *a,
const MKL_INT *lda,
35 MKL_INT *fpm,
float *epsout, MKL_INT *loop,
const float *emin,
const float *emax,
36 MKL_INT *m0,
float *e, MKL_Complex8 *x, MKL_INT *m,
float *res, MKL_INT *info) {
37 cfeast_heev(uplo, n, a, lda, fpm, epsout, loop, emin, emax, m0, e, x, m, res, info);
40void feast(
const char *uplo,
const MKL_INT *n,
const MKL_Complex16 *a,
const MKL_INT *lda,
41 MKL_INT *fpm,
double *epsout, MKL_INT *loop,
const double *emin,
const double *emax,
42 MKL_INT *m0,
double *e, MKL_Complex16 *x, MKL_INT *m,
double *res, MKL_INT *info) {
43 zfeast_heev(uplo, n, a, lda, fpm, epsout, loop, emin, emax, m0, e, x, m, res, info);
46template <
typename Scalar>
47template <
typename ScalarLim>
49DiagonalizerFeast<Scalar>::dispatch_eigh(
const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix,
53 int dim = matrix.rows();
58 this->
template subtract_mean<ScalarLim>(matrix, shift, rtol);
61 int m0 = std::min(dim, this->m0);
66 double targeted_trace_relative_error = rtol;
67 int precision_feast =
static_cast<int>(std::ceil(-std::log10(targeted_trace_relative_error)));
69 std::vector<MKL_INT> fpm(128);
70 feastinit(fpm.data());
75 fpm[2] = precision_feast;
76 fpm[6] = precision_feast;
78 std::vector<real_lim_t> e(m0);
83 std::vector<real_lim_t> res(m0);
84 real_lim_t min_eigenvalue_lim = min_eigenvalue - shift;
85 real_lim_t max_eigenvalue_lim = max_eigenvalue - shift;
87 feast(&uplo, &dim, hamiltonian.data(), &dim, fpm.data(), &epsout, &loop, &min_eigenvalue_lim,
88 &max_eigenvalue_lim, &m0, evals.data(), evecs.data(), &m, res.data(), &info);
93 throw std::invalid_argument(
94 "Diagonalization error: Problem with size of the system n (n≤0).");
97 throw std::invalid_argument(
98 "Diagonalization error: Problem with size of initial subspace m0 (m0≤0 or m0>n).");
101 throw std::invalid_argument(
102 "Diagonalization error: Problem with emin,emax (emin≥emax).");
105 throw std::invalid_argument(
106 "Diagonalization error: Size of the subspace m0 is too small (m0<m).");
109 throw std::runtime_error(
110 "Diagonalization error: No convergence (number of iteration loops >fpm[3]).");
113 throw std::runtime_error(
114 "Diagonalization error: No eigenvalue found in the search interval.");
117 throw std::runtime_error(
118 "Diagonalization error: Internal error for allocation memory.");
121 throw std::runtime_error(
122 "Diagonalization error: Internal error of the inner system solver. Possible "
123 "reasons: not enough memory for inner linear system solver or inconsistent input.");
126 throw std::runtime_error(
127 "Diagonalization error: Internal error of the reduced eigenvalue solver. Possible "
128 "cause: matrix may not be positive definite.");
131 throw std::invalid_argument(
"Diagonalization error: Matrix is not positive definite.");
134 throw std::invalid_argument(
135 fmt::format(
"Diagonalization error: Argument {} to the FEAST *interface* "
136 "had an illegal value (the counting of the arguments starts with one). "
137 "For a documentation of the feast interface, see "
138 "https://www.intel.com/content/www/us/en/docs/onemkl/"
139 "developer-reference-c/2025-1/feast-syev-feast-heev.html.",
143 throw std::invalid_argument(fmt::format(
144 "Diagonalization error: Argument {} to the FEAST "
145 "*initialization* had an illegal value (the counting of the arguments starts with "
146 "one). For a documentation of the feast initialization, see "
147 "https://www.intel.com/content/www/us/en/docs/onemkl/developer-reference-c/2025-1/"
148 "extended-eigensolver-input-parameters.html.",
151 throw std::runtime_error(fmt::format(
152 "Diagonalization error: The FEAST routine failed with error code {}.", info));
156 evecs.conservativeResize(dim, m);
157 evals.conservativeResize(m);
159 return {evecs.sparseView(1, 0.5 * rtol / std::sqrt(dim)).template cast<Scalar>(),
160 this->add_mean(evals, shift)};
163template <
typename Scalar>
165 : DiagonalizerInterface<Scalar>(float_type), m0(m0) {
167 throw std::invalid_argument(
"The size of the initial subspace m0 (i.e., the number of "
168 "maximally obtainable eigenvalues) must be positive.");
172template <
typename Scalar>
174DiagonalizerFeast<Scalar>::eigh(
const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> & ,
176 throw std::invalid_argument(
"The FEAST routine requires a search interval.");
179template <
typename Scalar>
181DiagonalizerFeast<Scalar>::eigh(
const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix,
182 std::optional<real_t> min_eigenvalue,
183 std::optional<real_t> max_eigenvalue,
double rtol)
const {
184 if (!min_eigenvalue.has_value() || !max_eigenvalue.has_value()) {
185 throw std::invalid_argument(
"The FEAST routine requires a search interval.");
187 switch (this->float_type) {
188 case FloatType::FLOAT32:
189 return dispatch_eigh<traits::restricted_t<Scalar, FloatType::FLOAT32>>(
190 matrix, min_eigenvalue.value(), max_eigenvalue.value(), rtol);
191 case FloatType::FLOAT64:
192 return dispatch_eigh<traits::restricted_t<Scalar, FloatType::FLOAT64>>(
193 matrix, min_eigenvalue.value(), max_eigenvalue.value(), rtol);
195 throw std::invalid_argument(
"Unsupported floating point precision.");
201template <
typename Scalar>
204 throw std::runtime_error(
205 "The FEAST routine is not available in this build. Please use a different diagonalizer.");
208template <
typename Scalar>
215template <
typename Scalar>
218 std::optional<real_t> ,
219 std::optional<real_t> ,
double )
const {
EigenSystemH< Scalar > eigh(const Eigen::SparseMatrix< Scalar, Eigen::RowMajor > &matrix, double rtol) const override
DiagonalizerFeast(int m0, FloatType float_type=FloatType::FLOAT64)
Matrix< Type, Dynamic, Dynamic > MatrixX
Matrix< Type, Dynamic, 1 > VectorX