33 static_assert(std::is_same_v<T, double> ||
34 std::is_same_v<T, std::complex<double>>,
35 "solve_Axeqb only available for Matrix<double> or "
36 "Matrix<complex<double>>");
43 auto x_gsl = x.as_gsl_view();
46 gsl_permutation *Am_perm =
47 gsl_permutation_alloc(std::max(Am.
rows(), Am.
cols()));
48 if constexpr (std::is_same_v<T, double>) {
49 gsl_linalg_LU_decomp(&Am_gsl.matrix, Am_perm, &sLU);
50 gsl_linalg_LU_solve(&Am_gsl.matrix, Am_perm, &b_gsl.vector, &x_gsl.vector);
51 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
52 gsl_linalg_complex_LU_decomp(&Am_gsl.matrix, Am_perm, &sLU);
53 gsl_linalg_complex_LU_solve(&Am_gsl.matrix, Am_perm, &b_gsl.vector,
56 gsl_permutation_free(Am_perm);
67 assert(A.rows() == A.cols());
70 auto eigen_vv = std::make_pair(
Vector<double>(A.rows()), std::move(A));
71 auto &[e_values, e_vectors] = eigen_vv;
73 int dim = (int)e_vectors.rows();
78 if constexpr (std::is_same_v<T, double>) {
81 int lwork = -1, liwork = -1;
82 double work_query = 0.0;
84 dsyevd_(&jobz, &uplo, &dim, e_vectors.data(), &dim, e_values.data(),
85 &work_query, &lwork, &iwork_query, &liwork, &info);
86 lwork =
static_cast<int>(work_query);
88 std::vector<double> work(std::size_t(std::max(1, lwork)));
89 std::vector<int> iwork(std::size_t(std::max(1, liwork)));
90 dsyevd_(&jobz, &uplo, &dim, e_vectors.data(), &dim, e_values.data(),
91 work.data(), &lwork, iwork.data(), &liwork, &info);
93 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
94 std::vector<T> work(3 * e_vectors.rows());
95 int workspace_size = (int)work.size();
100 std::vector<double> Rwork(3 * e_vectors.rows() - 2ul);
101 complex_double *evec_ptr =
102 reinterpret_cast<complex_double *
>(e_vectors.data());
103 complex_double *work_ptr =
reinterpret_cast<complex_double *
>(work.data());
104 zheev_(&jobz, &uplo, &dim, evec_ptr, &dim, e_values.data(), work_ptr,
105 &workspace_size, Rwork.data(), &info);
109 std::cerr <<
"\nError 91: symmhEigensystem " << info <<
" " << dim <<
" "
112 std::cerr <<
"The " << -info <<
"-th argument had an illegal value\n";
114 std::cerr <<
"The algorithm failed to converge; " << info
115 <<
" off-diagonal elements of an intermediate "
116 "tridiagonal form did not converge to zero.\n";
118 std::cerr << info <<
" " << A.size() <<
"\n";
127 assert(A.rows() == A.cols());
128 assert(number < (
int)A.rows());
129 static_assert(std::is_same_v<T, double>,
130 "This overload uses dsyevr_ (real symmetric). "
131 "For complex Hermitian use zheevr/cheevr.");
135 auto &[e_values, e_vectors] = eigen_vv;
137 int dim = (int)A.rows();
145 double abstol{1.0e-12};
149 std::vector<int> isuppz(std::size_t(2 * std::max(1, number)));
152 int lwork = -1, liwork = -1;
153 double work_query = 0.0;
155 dsyevr_(&jobz, &range, &uplo, &dim, A.data(), &dim, &vl, &vu, &il, &iu,
156 &abstol, &m, e_values.data(), e_vectors.data(), &dim, isuppz.data(),
157 &work_query, &lwork, &iwork_query, &liwork, &info);
160 std::cerr <<
"\nError: dsyevr workspace query info=" << info <<
"\n";
163 lwork =
static_cast<int>(work_query);
164 liwork = iwork_query;
165 std::vector<double> work(std::size_t(std::max(1, lwork)));
166 std::vector<int> iwork(std::size_t(std::max(1, liwork)));
168 dsyevr_(&jobz, &range, &uplo, &dim, A.data(), &dim, &vl, &vu, &il, &iu,
169 &abstol, &m, e_values.data(), e_vectors.data(), &dim, isuppz.data(),
170 work.data(), &lwork, iwork.data(), &liwork, &info);
173 std::cerr <<
"\nError: dsyevr (range=I) symmhEigensystem info=" << info
174 <<
" dim=" << dim <<
"\n";
184 static_assert(std::is_same_v<T, double>,
185 "This overload uses dsyevr (real symmetric). "
186 "For complex Hermitian use zheevr/cheevr.");
188 assert(A.rows() == A.cols());
189 int n =
static_cast<int>(A.rows());
194 auto &[num_solutions, e_values, e_vectors] = eigen_vv;
202 double vl = -std::numeric_limits<double>::max();
203 double vu = all_below;
206 double abstol{1.0e-12};
211 std::vector<int> isuppz(std::size_t(2 * std::max(1, n)));
214 int lwork{-1}, liwork{-1};
215 double work_query{0.0};
218 dsyevr_(&jobz, &range, &uplo, &n, A.data(), &n, &vl, &vu, &il, &iu, &abstol,
219 &num_solutions, e_values.data(), e_vectors.data(), &n, isuppz.data(),
220 &work_query, &lwork, &iwork_query, &liwork, &info);
223 std::cerr <<
"\nError: symmhEigensystem dsyevr(work query) info=" << info
224 <<
" n=" << n <<
"\n";
228 lwork =
static_cast<int>(work_query);
229 liwork = iwork_query;
230 std::vector<double> work(std::size_t(std::max(1, lwork)));
231 std::vector<int> iwork(std::size_t(std::max(1, liwork)));
234 dsyevr_(&jobz, &range, &uplo, &n, A.data(), &n, &vl, &vu, &il, &iu, &abstol,
235 &num_solutions, e_values.data(), e_vectors.data(), &n, isuppz.data(),
236 work.data(), &lwork, iwork.data(), &liwork, &info);
239 std::cerr <<
"\nError: symmhEigensystem dsyevr info=" << info <<
" n=" << n
240 <<
" m=" << num_solutions <<
"\n";
253 assert(A.rows() == A.cols());
254 assert(B.rows() == B.cols());
255 assert(A.rows() == B.rows());
258 auto eigen_vv = std::make_pair(
Vector<double>(A.rows()), std::move(A));
259 auto &[e_values, e_vectors] = eigen_vv;
262 int dim = (int)e_vectors.rows();
267 std::vector<T> work(3 * e_vectors.rows());
268 int workspace_size = (int)work.size();
270 if constexpr (std::is_same_v<T, double>) {
273 dsygv_(&itype, &jobz, &uplo, &dim, e_vectors.data(), &dim, B.data(), &dim,
274 e_values.data(), work.data(), &workspace_size, &info);
276 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
281 std::vector<double> Rwork(3 * e_vectors.rows() - 2ul);
282 complex_double *evec_ptr =
283 reinterpret_cast<complex_double *
>(e_vectors.data());
284 complex_double *Bmat_ptr =
reinterpret_cast<complex_double *
>(B.data());
285 complex_double *work_ptr =
reinterpret_cast<complex_double *
>(work.data());
286 zhegv_(&itype, &jobz, &uplo, &dim, evec_ptr, &dim, Bmat_ptr, &dim,
287 e_values.data(), work_ptr, &workspace_size, Rwork.data(), &info);
288 e_vectors.conj_in_place();
292 std::cerr <<
"\nError 198: symmhEigensystem " << info <<
" " << dim <<
" "
293 << B.size() << std::endl;
295 std::cerr <<
"The " << -info <<
"-th argument had an illegal value\n";
296 }
else if (info <= dim) {
297 std::cerr <<
"DSYEV failed to converge; " << info
298 <<
" off-diagonal elements of an intermediate tridiagonal form "
299 "did not converge to zero;";
301 std::cerr <<
"The leading minor of order " << info
302 <<
" of B is not positive definite. "
303 "The factorization of B could not be completed and no "
304 "eigenvalues or eigenvectors were computed.";
319 assert(A.rows() == A.cols());
320 static_assert(std::is_same_v<T, double>,
321 "genEigensystem only for Real matrix");
324 const auto dim = A.rows();
325 auto eigen_vv = std::make_pair(
Vector<std::complex<double>>(dim),
326 Matrix<std::complex<double>>(dim));
327 auto &[e_values, e_vectors] = eigen_vv;
331 auto A_gsl = A.as_gsl_view();
332 auto val_gsl = e_values.as_gsl_view();
333 auto vec_gsl = e_vectors.as_gsl_view();
334 gsl_eigen_nonsymmv_workspace *work = gsl_eigen_nonsymmv_alloc(dim);
335 gsl_eigen_nonsymmv(&A_gsl.matrix, &val_gsl.vector, &vec_gsl.matrix, work);
336 gsl_eigen_nonsymmv_free(work);
338 gsl_eigen_nonsymmv_sort(&val_gsl.vector, &vec_gsl.matrix,
339 GSL_EIGEN_SORT_ABS_ASC);
343 auto tmp = e_vectors.transpose();
344 e_vectors = std::move(tmp);
std::pair< Vector< std::complex< double > >, Matrix< std::complex< double > > > genEigensystem(Matrix< T > A, bool sort)
Solves Av = ev for all eigenvalues and right eigenvectors of a general (non-symmetric) real matrix A.
Definition Solvers.ipp:318
Vector< T > solve_Axeqb(Matrix< T > Am, const Vector< T > &b)
Solves the linear system Ax = b for x, given square matrix A and vector b.
Definition Solvers.ipp:32
std::pair< Vector< double >, Matrix< T > > symmhEigensystem(Matrix< T > A)
Solves Av = ev for all eigenvalues and eigenvectors of a real symmetric or complex Hermitian matrix A...
Definition Solvers.ipp:66