1#ifndef LINEARALGEBRA_SRC_MOLPRO_LINALG_ITERATIVESOLVER_HELPER_DISPATCH_H_
2#define LINEARALGEBRA_SRC_MOLPRO_LINALG_ITERATIVESOLVER_HELPER_DISPATCH_H_
21#include <molpro/lapacke.h>
22#include <molpro/linalg/itsolv/helper.h>
35extern "C" int dsyev_c(
char,
char,
int,
double*,
int,
double*);
49#if defined(HAVE_LAPACKE) || defined(MOLPRO)
55struct has_lapack_kernel<float> : std::true_type {};
57struct has_lapack_kernel<std::complex<float>> : std::true_type {};
59struct has_lapack_kernel<std::complex<double>> : std::true_type {};
74inline lapack_int heev(
int matrix_layout,
char jobz,
char uplo, lapack_int n,
float* a, lapack_int lda,
float* w) {
75 return LAPACKE_ssyev(matrix_layout, jobz, uplo, n, a, lda, w);
77inline lapack_int heev(
int matrix_layout,
char jobz,
char uplo, lapack_int n,
double* a, lapack_int lda,
double* w) {
78 return LAPACKE_dsyev(matrix_layout, jobz, uplo, n, a, lda, w);
80inline lapack_int heev(
int matrix_layout,
char jobz,
char uplo, lapack_int n, std::complex<float>* a, lapack_int lda,
82 return LAPACKE_cheev(matrix_layout, jobz, uplo, n,
reinterpret_cast<lapack_complex_float*
>(a), lda, w);
84inline lapack_int heev(
int matrix_layout,
char jobz,
char uplo, lapack_int n, std::complex<double>* a, lapack_int lda,
86 return LAPACKE_zheev(matrix_layout, jobz, uplo, n,
reinterpret_cast<lapack_complex_double*
>(a), lda, w);
90inline lapack_int gesdd(
int matrix_layout,
char jobz, lapack_int m, lapack_int n,
float* a, lapack_int lda,
float* s,
91 float* u, lapack_int ldu,
float* vt, lapack_int ldvt) {
92 return LAPACKE_sgesdd(matrix_layout, jobz, m, n, a, lda, s, u, ldu, vt, ldvt);
94inline lapack_int gesdd(
int matrix_layout,
char jobz, lapack_int m, lapack_int n,
double* a, lapack_int lda,
double* s,
95 double* u, lapack_int ldu,
double* vt, lapack_int ldvt) {
96 return LAPACKE_dgesdd(matrix_layout, jobz, m, n, a, lda, s, u, ldu, vt, ldvt);
98inline lapack_int gesdd(
int matrix_layout,
char jobz, lapack_int m, lapack_int n, std::complex<float>* a,
99 lapack_int lda,
float* s, std::complex<float>* u, lapack_int ldu, std::complex<float>* vt,
101 return LAPACKE_cgesdd(matrix_layout, jobz, m, n,
reinterpret_cast<lapack_complex_float*
>(a), lda, s,
102 reinterpret_cast<lapack_complex_float*
>(u), ldu,
reinterpret_cast<lapack_complex_float*
>(vt),
105inline lapack_int gesdd(
int matrix_layout,
char jobz, lapack_int m, lapack_int n, std::complex<double>* a,
106 lapack_int lda,
double* s, std::complex<double>* u, lapack_int ldu, std::complex<double>* vt,
108 return LAPACKE_zgesdd(matrix_layout, jobz, m, n,
reinterpret_cast<lapack_complex_double*
>(a), lda, s,
109 reinterpret_cast<lapack_complex_double*
>(u), ldu,
reinterpret_cast<lapack_complex_double*
>(vt),
114inline lapack_int gesvd(
int matrix_layout,
char jobu,
char jobvt, lapack_int m, lapack_int n,
float* a, lapack_int lda,
115 float* s,
float* u, lapack_int ldu,
float* vt, lapack_int ldvt,
float* superb) {
116 return LAPACKE_sgesvd(matrix_layout, jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, superb);
118inline lapack_int gesvd(
int matrix_layout,
char jobu,
char jobvt, lapack_int m, lapack_int n,
double* a, lapack_int lda,
119 double* s,
double* u, lapack_int ldu,
double* vt, lapack_int ldvt,
double* superb) {
120 return LAPACKE_dgesvd(matrix_layout, jobu, jobvt, m, n, a, lda, s, u, ldu, vt, ldvt, superb);
122inline lapack_int gesvd(
int matrix_layout,
char jobu,
char jobvt, lapack_int m, lapack_int n, std::complex<float>* a,
123 lapack_int lda,
float* s, std::complex<float>* u, lapack_int ldu, std::complex<float>* vt,
124 lapack_int ldvt,
float* superb) {
125 return LAPACKE_cgesvd(matrix_layout, jobu, jobvt, m, n,
reinterpret_cast<lapack_complex_float*
>(a), lda, s,
126 reinterpret_cast<lapack_complex_float*
>(u), ldu,
reinterpret_cast<lapack_complex_float*
>(vt),
129inline lapack_int gesvd(
int matrix_layout,
char jobu,
char jobvt, lapack_int m, lapack_int n, std::complex<double>* a,
130 lapack_int lda,
double* s, std::complex<double>* u, lapack_int ldu, std::complex<double>* vt,
131 lapack_int ldvt,
double* superb) {
132 return LAPACKE_zgesvd(matrix_layout, jobu, jobvt, m, n,
reinterpret_cast<lapack_complex_double*
>(a), lda, s,
133 reinterpret_cast<lapack_complex_double*
>(u), ldu,
reinterpret_cast<lapack_complex_double*
>(vt),
151template <
typename value_type>
153 std::span<real_type_t<value_type>> w,
size_t dimension) {
154 using matrix_type = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
155 using real_vector_type = Eigen::Vector<real_type_t<value_type>, Eigen::Dynamic>;
156 Eigen::Map<matrix_type> A(a.data(), dimension, dimension);
158 Eigen::SelfAdjointEigenSolver<matrix_type> solver(A, Eigen::ComputeEigenvectors);
159 if (solver.info() != Eigen::Success)
161 Eigen::Map<real_vector_type>(w.data(), dimension) = solver.eigenvalues();
162 A = solver.eigenvectors();
166#if defined(HAVE_LAPACKE) || defined(MOLPRO)
168template <
typename value_type>
170 std::span<real_type_t<value_type>> w,
size_t dimension) {
171 constexpr char compute_eigenvalues_eigenvectors =
'V';
172 constexpr char store_lower_triangle =
'L';
174 if constexpr (std::is_same_v<value_type, double>) {
175 return dsyev_c(compute_eigenvalues_eigenvectors, store_lower_triangle,
int(dimension), a.data(),
int(dimension),
180 return int(lapack::heev(LAPACK_COL_MAJOR, compute_eigenvalues_eigenvectors, store_lower_triangle,
181 lapack_int(dimension), a.data(), lapack_int(dimension), w.data()));
183 throw std::logic_error(
"no LAPACK kernel available for this scalar type");
205template <
typename value_type>
207 std::span<real_type_t<value_type>> eigenvalues,
const size_t dimension) {
209 if (eigenvectors.size() != matrix.size()) {
210 throw std::runtime_error(
"Matrix of eigenvectors and input matrix are not the same size! (" +
211 std::to_string(eigenvectors.size()) +
" vs. " + std::to_string(matrix.size()) +
")");
214 if (eigenvectors.size() != dimension * dimension || eigenvalues.size() != dimension) {
215 throw std::runtime_error(
"Size of eigenvectors/eigenvalues do not match dimension!");
219 std::copy(matrix.begin(), matrix.end(), eigenvectors.begin());
236template <
typename value_type>
238 using real_t = real_type_t<value_type>;
239 std::vector<value_type> eigvecs(dimension * dimension);
240 std::vector<real_t> eigvals(dimension);
242 const int success = eigensolver_hermitian<value_type>(matrix, eigvecs, eigvals, dimension);
244 throw std::invalid_argument(
"Invalid argument of eigensolver_hermitian: " + std::to_string(-success));
247 throw std::runtime_error(
"Hermitian eigensolver failed to converge. "
248 " elements of an intermediate tridiagonal form did not converge to zero.");
251 auto eigensystem = std::list<SVD<value_type>>{};
254 for (
int i =
int(dimension) - 1; i >= 0;
257 temp_eigenproblem.
value = eigvals[i];
258 for (
size_t j = 0; j < dimension; j++) {
259 temp_eigenproblem.v.emplace_back(eigvecs[j + (dimension * i)]);
261 eigensystem.emplace_back(temp_eigenproblem);
int eigensolver_hermitian_kernel(std::false_type, std::span< value_type > a, std::span< real_type_t< value_type > > w, size_t dimension)
Eigen implementation of the hermitian eigenproblem, used for every scalar type LAPACK does not cover.
Definition: helper-dispatch.h:152
4-parameter interpolation of a 1-dimensional function given two points for which function values and ...
Definition: helper.h:14
int eigensolver_hermitian(std::span< const value_type > matrix, std::span< value_type > eigenvectors, std::span< real_type_t< value_type > > eigenvalues, const size_t dimension)
Eigen-decomposition of a real symmetric / complex hermitian matrix.
Definition: helper-dispatch.h:206
constexpr bool has_lapack_kernel_v
Definition: helper-dispatch.h:62
Stores a singular value and corresponding left and right singular vectors.
Definition: helper.h:24
value_type value
Definition: helper.h:26
Whether the dense kernels of this library dispatch T to LAPACK rather than to Eigen.
Definition: helper-dispatch.h:48