40 static_assert(std::is_same_v<T, double> ||
41 std::is_same_v<T, std::complex<double>>,
42 "solve_Axeqb only available for Matrix<double> or "
43 "Matrix<complex<double>>");
49 int dim = int(Am.
rows());
52 std::vector<int> ipiv(
static_cast<std::size_t
>(dim));
58 if constexpr (std::is_same_v<T, double>) {
59 dgetrf_(&dim, &dim, Am.
data(), &dim, ipiv.data(), &info);
60 dgetrs_(&trans, &dim, &nrhs, Am.
data(), &dim, ipiv.data(), x.data(), &dim,
62 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
63 complex_double *Am_ptr =
reinterpret_cast<complex_double *
>(Am.
data());
64 complex_double *x_ptr =
reinterpret_cast<complex_double *
>(x.data());
65 zgetrf_(&dim, &dim, Am_ptr, &dim, ipiv.data(), &info);
66 zgetrs_(&trans, &dim, &nrhs, Am_ptr, &dim, ipiv.data(), x_ptr, &dim, &info);
78 assert(A.rows() == A.cols());
81 auto eigen_vv = std::make_pair(
Vector<double>(A.rows()), std::move(A));
82 auto &[e_values, e_vectors] = eigen_vv;
84 int dim = (int)e_vectors.rows();
89 if constexpr (std::is_same_v<T, double>) {
92 int lwork = -1, liwork = -1;
93 double work_query = 0.0;
95 dsyevd_(&jobz, &uplo, &dim, e_vectors.data(), &dim, e_values.data(),
96 &work_query, &lwork, &iwork_query, &liwork, &info);
97 lwork =
static_cast<int>(work_query);
99 std::vector<double> work(std::size_t(std::max(1, lwork)));
100 std::vector<int> iwork(std::size_t(std::max(1, liwork)));
101 dsyevd_(&jobz, &uplo, &dim, e_vectors.data(), &dim, e_values.data(),
102 work.data(), &lwork, iwork.data(), &liwork, &info);
104 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
105 std::vector<T> work(3 * e_vectors.rows());
106 int workspace_size = (int)work.size();
111 std::vector<double> Rwork(3 * e_vectors.rows() - 2ul);
112 complex_double *evec_ptr =
113 reinterpret_cast<complex_double *
>(e_vectors.data());
114 complex_double *work_ptr =
reinterpret_cast<complex_double *
>(work.data());
115 zheev_(&jobz, &uplo, &dim, evec_ptr, &dim, e_values.data(), work_ptr,
116 &workspace_size, Rwork.data(), &info);
120 std::cerr <<
"\nError 91: symmhEigensystem " << info <<
" " << dim <<
" "
123 std::cerr <<
"The " << -info <<
"-th argument had an illegal value\n";
125 std::cerr <<
"The algorithm failed to converge; " << info
126 <<
" off-diagonal elements of an intermediate "
127 "tridiagonal form did not converge to zero.\n";
129 std::cerr << info <<
" " << A.size() <<
"\n";
138 assert(A.rows() == A.cols());
139 assert(number < (
int)A.rows());
140 static_assert(std::is_same_v<T, double>,
141 "This overload uses dsyevr_ (real symmetric). "
142 "For complex Hermitian use zheevr/cheevr.");
146 auto &[e_values, e_vectors] = eigen_vv;
148 int dim = (int)A.rows();
156 double abstol{1.0e-12};
160 std::vector<int> isuppz(std::size_t(2 * std::max(1, number)));
163 int lwork = -1, liwork = -1;
164 double work_query = 0.0;
166 dsyevr_(&jobz, &range, &uplo, &dim, A.data(), &dim, &vl, &vu, &il, &iu,
167 &abstol, &m, e_values.data(), e_vectors.data(), &dim, isuppz.data(),
168 &work_query, &lwork, &iwork_query, &liwork, &info);
171 std::cerr <<
"\nError: dsyevr workspace query info=" << info <<
"\n";
174 lwork =
static_cast<int>(work_query);
175 liwork = iwork_query;
176 std::vector<double> work(std::size_t(std::max(1, lwork)));
177 std::vector<int> iwork(std::size_t(std::max(1, liwork)));
179 dsyevr_(&jobz, &range, &uplo, &dim, A.data(), &dim, &vl, &vu, &il, &iu,
180 &abstol, &m, e_values.data(), e_vectors.data(), &dim, isuppz.data(),
181 work.data(), &lwork, iwork.data(), &liwork, &info);
184 std::cerr <<
"\nError: dsyevr (range=I) symmhEigensystem info=" << info
185 <<
" dim=" << dim <<
"\n";
195 static_assert(std::is_same_v<T, double>,
196 "This overload uses dsyevr (real symmetric). "
197 "For complex Hermitian use zheevr/cheevr.");
199 assert(A.rows() == A.cols());
200 int n =
static_cast<int>(A.rows());
205 auto &[num_solutions, e_values, e_vectors] = eigen_vv;
213 double vl = -std::numeric_limits<double>::max();
214 double vu = all_below;
217 double abstol{1.0e-12};
222 std::vector<int> isuppz(std::size_t(2 * std::max(1, n)));
225 int lwork{-1}, liwork{-1};
226 double work_query{0.0};
229 dsyevr_(&jobz, &range, &uplo, &n, A.data(), &n, &vl, &vu, &il, &iu, &abstol,
230 &num_solutions, e_values.data(), e_vectors.data(), &n, isuppz.data(),
231 &work_query, &lwork, &iwork_query, &liwork, &info);
234 std::cerr <<
"\nError: symmhEigensystem dsyevr(work query) info=" << info
235 <<
" n=" << n <<
"\n";
239 lwork =
static_cast<int>(work_query);
240 liwork = iwork_query;
241 std::vector<double> work(std::size_t(std::max(1, lwork)));
242 std::vector<int> iwork(std::size_t(std::max(1, liwork)));
245 dsyevr_(&jobz, &range, &uplo, &n, A.data(), &n, &vl, &vu, &il, &iu, &abstol,
246 &num_solutions, e_values.data(), e_vectors.data(), &n, isuppz.data(),
247 work.data(), &lwork, iwork.data(), &liwork, &info);
250 std::cerr <<
"\nError: symmhEigensystem dsyevr info=" << info <<
" n=" << n
251 <<
" m=" << num_solutions <<
"\n";
264 assert(A.rows() == A.cols());
265 assert(B.rows() == B.cols());
266 assert(A.rows() == B.rows());
269 auto eigen_vv = std::make_pair(
Vector<double>(A.rows()), std::move(A));
270 auto &[e_values, e_vectors] = eigen_vv;
273 int dim = (int)e_vectors.rows();
278 std::vector<T> work(3 * e_vectors.rows());
279 int workspace_size = (int)work.size();
281 if constexpr (std::is_same_v<T, double>) {
284 dsygv_(&itype, &jobz, &uplo, &dim, e_vectors.data(), &dim, B.data(), &dim,
285 e_values.data(), work.data(), &workspace_size, &info);
287 }
else if constexpr (std::is_same_v<T, std::complex<double>>) {
292 std::vector<double> Rwork(3 * e_vectors.rows() - 2ul);
293 complex_double *evec_ptr =
294 reinterpret_cast<complex_double *
>(e_vectors.data());
295 complex_double *Bmat_ptr =
reinterpret_cast<complex_double *
>(B.data());
296 complex_double *work_ptr =
reinterpret_cast<complex_double *
>(work.data());
297 zhegv_(&itype, &jobz, &uplo, &dim, evec_ptr, &dim, Bmat_ptr, &dim,
298 e_values.data(), work_ptr, &workspace_size, Rwork.data(), &info);
299 e_vectors.conj_in_place();
303 std::cerr <<
"\nError 198: symmhEigensystem " << info <<
" " << dim <<
" "
304 << B.size() << std::endl;
306 std::cerr <<
"The " << -info <<
"-th argument had an illegal value\n";
307 }
else if (info <= dim) {
308 std::cerr <<
"DSYEV failed to converge; " << info
309 <<
" off-diagonal elements of an intermediate tridiagonal form "
310 "did not converge to zero;";
312 std::cerr <<
"The leading minor of order " << info
313 <<
" of B is not positive definite. "
314 "The factorization of B could not be completed and no "
315 "eigenvalues or eigenvectors were computed.";
330 assert(A.rows() == A.cols());
331 static_assert(std::is_same_v<T, double>,
332 "genEigensystem only for Real matrix");
335 const auto dim = A.rows();
336 auto eigen_vv = std::make_pair(
Vector<std::complex<double>>(dim),
337 Matrix<std::complex<double>>(dim));
338 auto &[e_values, e_vectors] = eigen_vv;
342 auto A_gsl = A.as_gsl_view();
343 auto val_gsl = e_values.as_gsl_view();
344 auto vec_gsl = e_vectors.as_gsl_view();
345 gsl_eigen_nonsymmv_workspace *work = gsl_eigen_nonsymmv_alloc(dim);
346 gsl_eigen_nonsymmv(&A_gsl.matrix, &val_gsl.vector, &vec_gsl.matrix, work);
347 gsl_eigen_nonsymmv_free(work);
349 gsl_eigen_nonsymmv_sort(&val_gsl.vector, &vec_gsl.matrix,
350 GSL_EIGEN_SORT_ABS_ASC);
354 auto tmp = e_vectors.transpose();
355 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:329
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:39
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:77