1#ifndef LINEARALGEBRA_SRC_MOLPRO_LINALG_ITERATIVESOLVER_HELPER_IMPLEMENTATION_H_
2#define LINEARALGEBRA_SRC_MOLPRO_LINALG_ITERATIVESOLVER_HELPER_IMPLEMENTATION_H_
5#include <molpro/Profiler.h>
6#include <molpro/lapacke.h>
7#include <molpro/linalg/itsolv/helper-dispatch.h>
8#include <molpro/linalg/itsolv/helper.h>
11#include "subspace/Matrix.h"
26template <
typename value_type>
28 real_type_t<value_type> threshold) {
29 auto mat = Eigen::Map<const Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>>(m.
data(), nrows, ncols);
30#if EIGEN_VERSION_AT_LEAST(3, 4, 90)
33 auto svd = Eigen::JacobiSVD<Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>>(
34 mat,
static_cast<unsigned int>(Eigen::ComputeThinV) |
35 static_cast<unsigned int>(Eigen::NoQRPreconditioner));
37 auto svd = Eigen::JacobiSVD<Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>, Eigen::NoQRPreconditioner>(
38 mat, Eigen::ComputeThinV);
40 auto svd_system = std::list<SVD<value_type>>{};
41 auto sv = svd.singularValues();
42 for (
int i =
int(ncols) - 1; i >= 0; --i) {
43 if (std::abs(sv(i)) < threshold) {
47 for (
size_t j = 0; j < ncols; ++j) {
48 t.v.emplace_back(svd.matrixV()(j, i));
56template <
typename value_type>
58 real_type_t<value_type> threshold) {
59 auto mat = Eigen::Map<const Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>>(m.
data(), nrows, ncols);
60 auto svd = Eigen::BDCSVD<Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>>(mat, Eigen::ComputeThinV);
61 auto svd_system = std::list<SVD<value_type>>{};
62 auto sv = svd.singularValues();
63 for (
int i =
int(ncols) - 1; i >= 0; --i) {
64 if (std::abs(sv(i)) < threshold) {
68 for (
size_t j = 0; j < ncols; ++j) {
69 t.v.emplace_back(svd.matrixV()(j, i));
84template <
typename value_type>
87 static_assert(has_lapack_kernel_v<value_type>,
"LAPACK has no ?gesdd kernel for this scalar type");
88 const size_t sdim = std::min(nrows, ncols);
90 std::vector<value_type> a(mat.
begin(), mat.
end());
91 std::vector<real_type_t<value_type>> sv(sdim);
92 std::vector<value_type> u(nrows * nrows), v(ncols * ncols);
94 lapack::gesdd(LAPACK_ROW_MAJOR,
'A', lapack_int(nrows), lapack_int(ncols), a.data(), lapack_int(ncols), sv.data(),
95 u.data(), lapack_int(nrows), v.data(), lapack_int(ncols));
97 throw std::runtime_error(
"?gesdd (singular value decomposition) failed with info = " + std::to_string(info));
98 auto svd_system = std::list<SVD<value_type>>{};
99 for (
int i =
int(ncols) - 1; i >= 0; --i) {
100 if (std::abs(sv[i]) < threshold) {
101 auto t = SVD<value_type>{};
104 for (
size_t j = 0; j < ncols; ++j) {
105 t.v.emplace_back(v[i * ncols + j]);
114template <
typename value_type>
115std::list<SVD<value_type>> svd_lapacke_gesvd(
size_t nrows,
size_t ncols,
const array::Span<value_type>& mat,
116 real_type_t<value_type> threshold) {
117 static_assert(has_lapack_kernel_v<value_type>,
"LAPACK has no ?gesvd kernel for this scalar type");
118 const size_t sdim = std::min(nrows, ncols);
120 std::vector<value_type> a(mat.begin(), mat.end());
121 std::vector<real_type_t<value_type>> sv(sdim);
122 std::vector<value_type> u(nrows * nrows), v(ncols * ncols);
123 std::vector<real_type_t<value_type>> superb(sdim > 0 ? sdim - 1 : 0);
124 const auto info = lapack::gesvd(LAPACK_ROW_MAJOR,
'N',
'A', lapack_int(nrows), lapack_int(ncols), a.data(),
125 lapack_int(ncols), sv.data(), u.data(), lapack_int(nrows), v.data(),
126 lapack_int(ncols), superb.data());
128 throw std::runtime_error(
"?gesvd (singular value decomposition) failed with info = " + std::to_string(info));
129 auto svd_system = std::list<SVD<value_type>>{};
130 for (
int i =
int(ncols) - 1; i >= 0; --i) {
131 if (std::abs(sv[i]) < threshold) {
132 auto t = SVD<value_type>{};
135 for (
size_t j = 0; j < ncols; ++j) {
136 t.v.emplace_back(v[i * ncols + j]);
154 std::span<double> eigenvalues,
const size_t dimension) {
155 return eigensolver_hermitian<double>(matrix, eigenvectors, eigenvalues, dimension);
160 return eigensolver_hermitian<double>(dimension, matrix);
170template <
typename value_type>
171size_t get_rank(std::span<const value_type> eigenvalues, value_type threshold) {
172 if (eigenvalues.size() == 0) {
175 value_type max = *max_element(eigenvalues.begin(), eigenvalues.end());
176 value_type threshold_scaled = threshold * max;
178 std::count_if(eigenvalues.begin(), eigenvalues.end(), [&](
auto const& val) { return val >= threshold_scaled; });
189template <
typename value_type>
192 value_type max_value = 0;
193 typename std::list<SVD<value_type>>::iterator it;
195 if (it->value > max_value) {
196 max_value = it->value;
200 value_type threshold_scaled = threshold * max_value;
205 if (it->value > threshold_scaled) {
212template <
typename value_type,
typename std::enable_if_t<!is_complex<value_type>{}, std::
nullptr_t>>
214 real_type_t<value_type> threshold,
bool hermitian,
bool reduce_to_rank) {
215 std::list<SVD<value_type>> svds;
216 assert(m.
size() == nrows * ncols);
220 assert(nrows == ncols);
222 svds = eigensolver_hermitian<value_type>(nrows, std::span<const value_type>{m.
data(), m.
size()});
223 for (
auto s = svds.begin(); s != svds.end();)
224 if (s->value > threshold)
232 svds = svd_eigen_jacobi<value_type>(nrows, ncols, m, threshold);
237 if (reduce_to_rank) {
238 int rank =
get_rank(svds, threshold);
239 for (
int i = ncols; i > rank; i--) {
246template <
typename value_type,
typename std::enable_if_t<is_complex<value_type>{},
int>>
253template <
typename value_type>
254void printMatrix(
const std::vector<value_type>& m,
size_t rows,
size_t cols, std::string title, std::ostream& s) {
256 << Eigen::Map<const Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>>(m.data(), rows, cols) << std::endl;
259template <
typename value_type,
typename std::enable_if_t<is_complex<value_type>{},
int>>
260void eigenproblem(std::vector<value_type>& eigenvectors, std::vector<value_type>& eigenvalues,
261 const std::vector<value_type>& matrix,
const std::vector<value_type>& metric,
size_t dimension,
262 bool hermitian, real_type_t<value_type> svdThreshold,
int verbosity) {
266template <
typename value_type,
typename std::enable_if_t<!is_complex<value_type>{}, std::
nullptr_t>>
267void eigenproblem(std::vector<value_type>& eigenvectors, std::vector<value_type>& eigenvalues,
268 const std::vector<value_type>& matrix,
const std::vector<value_type>& metric,
size_t dimension,
269 bool hermitian, real_type_t<value_type> svdThreshold,
int verbosity,
270 std::vector<std::pair<std::size_t, value_type>>* imag_eval_parts) {
275 const value_type zero_tol = precision_scaled<value_type>(1e-10);
276 const value_type null_eigenvalue_tol = precision_scaled<value_type>(1e-12);
277 const value_type null_metric_eigenvalue_tol = precision_scaled<value_type>(1e-14);
278 using MatrixT = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
279 using ComplexMatrixT = Eigen::Matrix<std::complex<value_type>, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>;
280 using MatrixRowMajT = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
281 using VectorT = Eigen::Vector<value_type, Eigen::Dynamic>;
282 using ComplexVectorT = Eigen::Vector<std::complex<value_type>, Eigen::Dynamic>;
285 prof->start(
"itsolv::eigenproblem");
286 Eigen::Map<const MatrixRowMajT> HrowMajor(
287 matrix.data(), dimension, dimension);
288 MatrixT H(dimension, dimension);
290 Eigen::Map<const MatrixT> S(metric.data(), dimension, dimension);
291 ComplexMatrixT subspaceEigenvectors;
292 ComplexVectorT subspaceEigenvalues;
295 VectorT metricEvals(dimension);
296 MatrixT metricEvecs(dimension, dimension);
302 int success = eigensolver_hermitian<value_type>(std::span<const value_type>{metric.data(), metric.size()},
303 {metricEvecs.data(), dimension * dimension},
304 {metricEvals.data(), dimension}, dimension);
306 throw std::runtime_error(
"Eigensolver did not converge");
308 rank =
get_rank<value_type>(std::span<const value_type>{metricEvals.data(), dimension}, svdThreshold);
310 if (verbosity > 1 && rank < S.cols())
311 molpro::cout <<
"SVD rank " << rank <<
" in subspace of dimension " << S.cols() << std::endl;
312 if (verbosity > 2 && rank < S.cols())
313 molpro::cout <<
"singular values " << metricEvals.transpose() << std::endl;
319 auto svmh = metricEvals.tail(rank);
320 for (
auto k = 0; k < rank; k++) {
321 assert(abs(svmh(k)) <= svdThreshold || svmh(k) >= 0);
322 svmh(k) = svmh(k) > null_metric_eigenvalue_tol ? 1 / sqrt(svmh(k)) : 0;
325 svmh.asDiagonal() * metricEvecs.rightCols(rank).adjoint() * H * metricEvecs.rightCols(rank) * svmh.asDiagonal();
328 Eigen::EigenSolver<MatrixT> s(Hbar);
329 subspaceEigenvalues = s.eigenvalues();
330 if (s.eigenvalues().imag().norm() < zero_tol) {
332 subspaceEigenvalues = subspaceEigenvalues.real();
333 subspaceEigenvectors = s.eigenvectors();
336 for (
int i = 0; i < subspaceEigenvectors.cols() - 1; i++) {
337 if (subspaceEigenvectors.col(i).imag().norm() <= zero_tol) {
342 if (abs(subspaceEigenvalues(i) - subspaceEigenvalues(j)) >= zero_tol or
343 subspaceEigenvectors.col(j).imag().norm() <= zero_tol) {
351 subspaceEigenvectors.col(j) = subspaceEigenvectors.col(i).imag() / subspaceEigenvectors.col(i).imag().norm();
352 subspaceEigenvectors.col(i) = subspaceEigenvectors.col(i).real() / subspaceEigenvectors.col(i).real().norm();
356 subspaceEigenvectors = metricEvecs.rightCols(rank) * svmh.asDiagonal() * subspaceEigenvectors;
359#ifdef __INTEL_COMPILER
360 molpro::cout <<
"Hbar\n" << Hbar << std::endl;
361 molpro::cout <<
"Eigenvalues\n" << s.eigenvalues() << std::endl;
362 molpro::cout <<
"Eigenvectors\n" << s.eigenvectors() << std::endl;
363 throw std::runtime_error(
"Intel compiler does not support working with complex eigen3 entities properly");
367 subspaceEigenvectors = metricEvecs.rightCols(rank) * svmh.asDiagonal() * s.eigenvectors();
372 Eigen::PermutationMatrix<Eigen::Dynamic, Eigen::Dynamic> perm(subspaceEigenvalues.size());
376 [](
const std::complex<value_type>& lhs,
const std::complex<value_type>& rhs) {
377 if (lhs.real() != rhs.real()) {
378 return lhs.real() < rhs.real();
381 if (abs(lhs.imag()) != abs(rhs.imag())) {
383 return abs(lhs.imag()) < abs(rhs.imag());
387 return lhs.imag() < rhs.imag();
389 [&subspaceEigenvalues](
auto idx) {
return subspaceEigenvalues[idx]; });
392 subspaceEigenvectors = subspaceEigenvectors * perm;
393 subspaceEigenvalues = perm.transpose() * subspaceEigenvalues;
400 for (
auto repeat = 0; repeat < 1; ++repeat)
401 for (Eigen::Index k = 0; k < subspaceEigenvectors.cols(); k++) {
402 if (abs(subspaceEigenvalues(k)) < null_eigenvalue_tol) {
404 subspaceEigenvectors.col(k).real() += value_type(0.3256897) * subspaceEigenvectors.col(k).imag();
405 subspaceEigenvectors.col(k).imag().setZero();
408 auto ovl = subspaceEigenvectors.col(k).dot(S * subspaceEigenvectors.col(k));
410 assert(abs(ovl.imag()) < zero_tol);
411 assert(ovl.real() > 0);
412 subspaceEigenvectors.col(k) /= sqrt(ovl.real());
417 for (std::size_t i = 0; i < subspaceEigenvectors.cols(); ++i) {
418 const auto &col = subspaceEigenvectors.col(i);
419 auto it = std::ranges::max_element(col, std::less<>{}, [](
auto val) {
return abs(val); });
420 auto idx = std::distance(col.begin(), it);
421 if (subspaceEigenvectors.col(i)[idx].real() < 0) {
422 subspaceEigenvectors.col(i) *= -1;
426 if (imag_eval_parts) {
429 imag_eval_parts->clear();
431 for (Eigen::Index root = 0; root < Hbar.cols(); ++root) {
432 if (subspaceEigenvalues(root).imag() == 0) {
437 assert(root + 1 < subspaceEigenvalues.size());
438 assert(abs(std::conj(subspaceEigenvalues(root)) - subspaceEigenvalues(root + 1)) < zero_tol);
440 imag_eval_parts->emplace_back(root, subspaceEigenvalues(root).imag());
441 imag_eval_parts->emplace_back(root + 1, -subspaceEigenvalues(root).imag());
444 subspaceEigenvalues(root) = subspaceEigenvalues(root + 1) = subspaceEigenvalues(root).real();
452 subspaceEigenvectors.col(root + 1) = subspaceEigenvectors.col(root).imag();
453 subspaceEigenvectors.col(root) = subspaceEigenvectors.col(root).real();
460 if ((subspaceEigenvectors - subspaceEigenvectors.real()).norm() > zero_tol or
461 (subspaceEigenvalues - subspaceEigenvalues.real()).norm() > zero_tol) {
462 throw std::runtime_error(
"unexpected complex solution found");
465 eigenvectors.resize(dimension * Hbar.cols());
466 eigenvalues.resize(Hbar.cols());
468 Eigen::Map<MatrixT>(eigenvectors.data(), dimension, Hbar.cols()) =
469 subspaceEigenvectors.real();
470 Eigen::Map<VectorT> ev(eigenvalues.data(), Hbar.cols());
471 ev = subspaceEigenvalues.real();
476template <
typename value_type,
typename std::enable_if_t<is_complex<value_type>{},
int>>
478 const std::vector<value_type>& matrix,
const std::vector<value_type>& metric,
479 const std::vector<value_type>& rhs,
const size_t dimension,
size_t nroot,
480 real_type_t<value_type> augmented_hessian, real_type_t<value_type> svdThreshold,
485template <
typename value_type,
typename std::enable_if_t<!is_complex<value_type>{}, std::
nullptr_t>>
486void solve_LinearEquations(std::vector<value_type>& solution, std::vector<value_type>& eigenvalues,
487 const std::vector<value_type>& matrix,
const std::vector<value_type>& metric,
488 const std::vector<value_type>& rhs,
const size_t dimension,
size_t nroot,
491 const Eigen::Index nX = dimension;
492 solution.resize(nX * nroot);
494 if (augmented_hessian > 0) {
495 Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> subspaceMatrix;
496 Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> subspaceOverlap;
497 subspaceMatrix.conservativeResize(nX + 1, nX + 1);
498 subspaceOverlap.conservativeResize(nX + 1, nX + 1);
501 using row_major_type = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
502 subspaceMatrix.block(0, 0, nX, nX) = Eigen::Map<const row_major_type>(matrix.data(), nX, nX);
503 subspaceOverlap.block(0, 0, nX, nX) = Eigen::Map<const row_major_type>(metric.data(), nX, nX);
504 eigenvalues.resize(nroot);
505 for (
size_t root = 0; root < nroot; root++) {
506 for (Eigen::Index i = 0; i < nX; i++) {
507 subspaceMatrix(i, nX) = subspaceMatrix(nX, i) = -augmented_hessian * rhs[i * nroot + root];
508 subspaceOverlap(i, nX) = subspaceOverlap(nX, i) = 0;
510 subspaceMatrix(nX, nX) = 0;
511 subspaceOverlap(nX, nX) = 1;
515 Eigen::GeneralizedEigenSolver<Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>> s(subspaceMatrix,
517 auto eval = s.eigenvalues();
518 auto evec = s.eigenvectors();
519 Eigen::Index imax = 0;
520 for (Eigen::Index i = 0; i < nX + 1; i++)
521 if (eval(i).real() < eval(imax).real())
523 eigenvalues[root] = eval(imax).real();
524 auto Solution = evec.col(imax).real().head(nX) / (augmented_hessian * evec.real()(nX, imax));
525 for (
auto k = 0; k < nX; k++)
526 solution[k + nX * root] = Solution(k);
530 Eigen::Map<const Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> subspaceMatrixR(
531 matrix.data(), nX, nX);
532 Eigen::Map<const Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>> RHS_R(rhs.data(), nX,
534 Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> subspaceMatrix = subspaceMatrixR;
535 Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> RHS = RHS_R;
536 Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic> Solution;
545 Solution = subspaceMatrix.householderQr().solve(RHS);
547 for (
size_t root = 0; root < nroot; root++)
548 for (
auto k = 0; k < nX; k++)
549 solution[k + nX * root] = Solution(k, root);
553template <
typename value_type,
typename std::enable_if_t<!is_complex<value_type>{}, std::
nullptr_t>>
554void solve_DIIS(std::vector<value_type>& solution,
const std::vector<value_type>& matrix,
const size_t dimension,
555 real_type_t<value_type> svdThreshold,
int verbosity) {
559 using VectorT = Eigen::Vector<value_type, Eigen::Dynamic>;
560 using MatrixT = Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>;
561 auto nAug = dimension + 1;
563 solution.resize(dimension);
565 VectorT Rhs(nAug), Coeffs(nAug);
566 MatrixT BAug(nAug, nAug);
570 Eigen::Map<const Eigen::Matrix<value_type, Eigen::Dynamic, Eigen::Dynamic>> subspaceMatrix(matrix.data(), dimension,
572 BAug.block(0, 0, dimension, dimension) = subspaceMatrix;
573 for (
size_t i = 0; i < dimension; ++i) {
574 BAug(dimension, i) = BAug(i, dimension) = -1;
577 BAug(dimension, dimension) = 0;
584 Eigen::JacobiSVD<MatrixT> svd(BAug, Eigen::ComputeThinU | Eigen::ComputeThinV);
588 svd.setThreshold(svdThreshold * svd.singularValues().maxCoeff() * 0);
593 Coeffs = svd.solve(Rhs).head(dimension);
597 molpro::cout <<
"Combination of iteration vectors: " << Coeffs.transpose() << std::endl;
598 for (
size_t k = 0; k < (size_t)Coeffs.rows(); k++) {
599 if (isnan(abs(Coeffs(k)))) {
600 molpro::cout <<
"B:" << std::endl << BAug << std::endl;
601 molpro::cout <<
"Rhs:" << std::endl << Rhs << std::endl;
602 molpro::cout <<
"Combination of iteration vectors: " << Coeffs.transpose() << std::endl;
603 throw std::overflow_error(
"NaN detected in DIIS submatrix solution");
605 solution[k] = Coeffs(k);
626template <
typename value_type,
typename value_type_abs>
628 const value_type_abs svd_thresh,
Logger& logger) {
630 prof->start(
"itsolv::svd_system");
631 logger.
trace(
"redundant_parameters()");
632 auto redundant_params = std::vector<int>{};
633 auto rspace_indices = std::vector<int>(nR);
634 std::iota(std::begin(rspace_indices), std::end(rspace_indices), 0);
635 auto svd =
svd_system(overlap.rows(), overlap.cols(),
636 array::Span(
const_cast<value_type*
>(overlap.data().data()), overlap.size()), svd_thresh,
true);
638 prof->start(
"find redundant parameters");
639 for (
const auto& singular_system : svd) {
640 if (!rspace_indices.empty()) {
641 auto rspace_contribution = std::vector<value_type_abs>{};
642 for (
auto i : rspace_indices)
643 rspace_contribution.push_back(std::abs(singular_system.v.at(oR + i)));
644 auto it_min = std::max_element(std::begin(rspace_contribution), std::end(rspace_contribution));
645 auto imin = std::distance(std::begin(rspace_contribution), it_min);
646 redundant_params.push_back(rspace_indices[imin]);
647 rspace_indices.erase(std::begin(rspace_indices) + imin);
648 std::stringstream ss;
649 ss << std::setprecision(3) <<
"redundant parameter found, i = " << redundant_params.back()
650 <<
", svd.value = " << singular_system.value
651 <<
", svd.v[i] = " << singular_system.v[oR + redundant_params.back()];
652 logger.
info(ss.str());
656 return redundant_params;
Non-owning container taking a pointer to the data buffer and its size and exposing routines for itera...
Definition: Span.h:31
bool empty() const
Definition: Span.h:79
iterator begin()
Definition: Span.h:69
size_type size() const
Definition: Span.h:77
iterator end()
Definition: Span.h:73
iterator data()
Definition: Span.h:66
void info(std::string_view message, Ts &&...args) const
Definition: Logger.h:505
void trace(std::string_view message, Ts &&...args) const
Definition: Logger.h:495
static std::shared_ptr< Profiler > single()
Definition: helper-dispatch.h:140
auto redundant_parameters(const subspace::Matrix< value_type > &overlap, const size_t oR, const size_t nR, const value_type_abs svd_thresh, Logger &logger)
Deduces a set of parameters that are redundant due to linear dependencies.
Definition: helper-implementation.h:627
4-parameter interpolation of a 1-dimensional function given two points for which function values and ...
Definition: helper.h:14
std::list< SVD< value_type > > svd_eigen_bdcsvd(size_t nrows, size_t ncols, const array::Span< value_type > &m, real_type_t< value_type > threshold)
Definition: helper-implementation.h:57
void solve_LinearEquations(std::vector< value_type > &solution, std::vector< value_type > &eigenvalues, const std::vector< value_type > &matrix, const std::vector< value_type > &metric, const std::vector< value_type > &rhs, size_t dimension, size_t nroot, real_type_t< value_type > augmented_hessian, real_type_t< value_type > svdThreshold, int verbosity)
Definition: helper-implementation.h:477
void eigenproblem(std::vector< value_type > &eigenvectors, std::vector< value_type > &eigenvalues, const std::vector< value_type > &matrix, const std::vector< value_type > &metric, size_t dimension, bool hermitian, real_type_t< value_type > svdThreshold, int verbosity)
Definition: helper-implementation.h:260
int eigensolver_lapacke_dsyev(std::span< const double > matrix, std::span< double > eigenvectors, std::span< double > eigenvalues, const size_t dimension)
Eigen-decomposition of a real symmetric matrix in double precision.
Definition: helper-implementation.h:153
template size_t get_rank< value_type >(std::span< const value_type > eigenvalues, value_type threshold)
void solve_DIIS(std::vector< value_type > &solution, const std::vector< value_type > &matrix, size_t dimension, real_type_t< value_type > svdThreshold, int verbosity=0)
Definition: helper-implementation.h:554
std::list< SVD< value_type > > svd_eigen_jacobi(size_t nrows, size_t ncols, const array::Span< value_type > &m, real_type_t< value_type > threshold)
Definition: helper-implementation.h:27
std::list< SVD< value_type > > svd_system(size_t nrows, size_t ncols, const array::Span< value_type > &m, real_type_t< value_type > threshold, bool hermitian=false, bool reduce_to_rank=false)
Performs singular value decomposition and returns SVD objects for singular values less than threshold...
Definition: helper-implementation.h:213
size_t get_rank(std::span< const value_type > eigenvalues, value_type threshold)
Definition: helper-implementation.h:171
void printMatrix(const std::vector< value_type > &, size_t rows, size_t cols, std::string title="", std::ostream &s=molpro::cout)
Definition: helper-implementation.h:254
typename real_type< T >::type real_type_t
The real type underlying T, i.e. T itself for a real type and U for std::complex<U>.
Definition: scalar_traits.h:43
Stores a singular value and corresponding left and right singular vectors.
Definition: helper.h:24
value_type value
Definition: helper.h:26