iterative-solver 0.0
 
Loading...
Searching...
No Matches
util.h
1#ifndef LINEARALGEBRA_SRC_MOLPRO_LINALG_ITSOLV_SUBSPACE_UTIL_H
2#define LINEARALGEBRA_SRC_MOLPRO_LINALG_ITSOLV_SUBSPACE_UTIL_H
3#include <Eigen/Dense>
4#include <limits>
5#include <molpro/linalg/itsolv/ArrayHandlers.h>
6#include <molpro/linalg/itsolv/subspace/Matrix.h>
7#include <molpro/linalg/itsolv/wrap.h>
8#include <molpro/linalg/scalar_traits.h>
9
10#include <cmath>
11#include <vector>
12
14namespace detail {
15
17template <typename T1, typename T2, typename... Ts>
18struct is_one_of {
19 static constexpr bool value = std::is_same<T1, T2>::value || is_one_of<T1, Ts...>::value;
20};
21
22template <typename T1, typename T2>
23struct is_one_of<T1, T2> {
24 static constexpr bool value = std::is_same<T1, T2>::value;
25};
26
28 bool = std::is_same<R, Z>::value, bool = std::is_same<W, Q>::value>
29struct Overlap {};
30
31template <class R, class Q, class Z, class W>
32struct Overlap<R, Q, Z, W, true, true, true> {
35 return handler.gemm_inner(left, right);
36 }
37};
38
39template <class R, class Q, class Z, class W>
40struct Overlap<R, Q, Z, W, true, false, false> {
43 // gemm_inner(right, left)(i, j) = <right_i|left_j>, and <left_j|right_i> is its conjugate
44 auto mat = handler.gemm_inner(right, left);
45 auto m = Matrix<value_type>({left.size(), right.size()});
47 return m;
48 }
49};
50
51template <class R, class Q, class Z, class W>
53} // namespace detail
54
56template <class R, class Q, class Z, class W>
58 -> std::enable_if_t<detail::Z_and_W_are_one_of_R_and_Q<R, Q, Z, W>,
61}
62
64template <class R>
67 auto m = Matrix<typename array::ArrayHandler<R, R>::value_type>({params.size(), params.size()});
68 for (size_t i = 0; i < m.rows(); ++i)
69 for (size_t j = 0; j <= i; ++j) {
70 m(i, j) = handler.dot(params[i], params[j]);
71 m(j, i) = conjugate(m(i, j)); // the matrix is hermitian, which for a real element type is symmetric
72 }
73 return m;
74}
75
81template <typename T>
82std::vector<real_type_t<T>> solution_norms(const Matrix<T>& solutions, const Matrix<T>& overlap) {
83 using row_major_type = Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>;
84 const auto nsol = Eigen::Index(solutions.rows()), dim = Eigen::Index(solutions.cols());
85 auto norms = std::vector<real_type_t<T>>(nsol);
86 if (nsol == 0 || dim == 0)
87 return norms;
88 const auto c = Eigen::Map<const row_major_type>(solutions.data().data(), nsol, dim);
89 const auto s = Eigen::Map<const row_major_type>(overlap.data().data(), dim, dim);
90 const row_major_type cs = c.conjugate() * s;
91 using std::abs;
92 using std::sqrt;
93 for (Eigen::Index i = 0; i < nsol; ++i)
94 norms[i] = sqrt(abs(cs.row(i).dot(c.row(i).conjugate())));
95 return norms;
96}
97
105template <typename T>
107 auto scaled = solutions;
108 const auto norms = solution_norms(solutions, overlap);
109 for (size_t i = 0; i < scaled.rows(); ++i)
110 if (norms[i] > 0)
111 for (size_t j = 0; j < scaled.cols(); ++j)
112 scaled(i, j) /= T(norms[i]);
113 return scaled;
114}
115
117template <typename T>
119 assert(mat.rows() == mat.cols() && "must be a square matrix");
120 for (size_t i = 0; i < mat.rows(); ++i)
121 for (size_t j = 0; j < i; ++j) {
122 mat(i, j) = T(0.5) * (mat(i, j) + conjugate(mat(j, i)));
123 mat(j, i) = conjugate(mat(i, j));
124 }
125}
126
128template <typename T>
129typename Matrix<T>::coord_type max_element_index(const std::list<size_t>& rows, const std::list<size_t>& cols,
130 const Matrix<T>& mat) {
131 auto max_el = std::numeric_limits<T>::lowest();
132 auto ind = typename Matrix<T>::coord_type{0, 0};
133 for (auto i : rows) {
134 for (auto j : cols) {
135 if (mat(i, j) > max_el) {
136 max_el = mat(i, j);
137 ind = {i, j};
138 }
139 }
140 }
141 return ind;
142}
143
157template <typename Slice>
158std::vector<size_t> eye_order(const Slice& mat) {
159 auto dim = mat.dimensions();
160 auto rows = std::list<size_t>{};
161 auto cols = std::list<size_t>{};
162 for (size_t i = 0; i < dim.first; ++i) {
163 rows.emplace_back(i);
164 cols.emplace_back(i);
165 }
166 auto order = std::vector<size_t>(dim.first);
167 size_t i, j;
168 while (!rows.empty() && !cols.empty()) {
169 std::tie(i, j) = max_element_index(rows, cols, mat);
170 order.at(j) = i;
171 auto it_row = std::find(begin(rows), end(rows), i);
172 auto it_col = std::find(begin(cols), end(cols), j);
173 rows.erase(it_row);
174 cols.erase(it_col);
175 }
176 return order;
177}
178
179} // namespace molpro::linalg::itsolv::subspace::util
180
181#endif // LINEARALGEBRA_SRC_MOLPRO_LINALG_ITSOLV_SUBSPACE_UTIL_H
Enhances various operations between pairs of arrays and allows dynamic code injection with uniform in...
Definition ArrayHandler.h:163
virtual value_type dot(const AL &x, const AR &y)=0
The hermitian inner product <x|y>: conjugate-linear in x, linear in y.
decltype(value_type_L{} *value_type_R{}) value_type
Definition ArrayHandler.h:182
virtual Matrix< value_type > gemm_inner(const CVecRef< AL > &xx, const CVecRef< AR > &yy)=0
Matrix container that allows simple data access, slicing, copying and resizing without loosing data.
Definition Matrix.h:32
std::pair< size_t, size_t > coord_type
Definition Matrix.h:40
const std::vector< T > & data() const &
Access the underlying data buffer.
Definition Matrix.h:69
index_type rows() const
Definition Matrix.h:169
index_type cols() const
Definition Matrix.h:170
constexpr bool Z_and_W_are_one_of_R_and_Q
Definition util.h:52
Definition gram_schmidt.h:8
Matrix< T > unit_length_solutions(const Matrix< T > &solutions, const Matrix< T > &overlap)
The subspace coefficients of the solutions scaled to unit Euclidean length, so that their sizes can b...
Definition util.h:106
Matrix< T >::coord_type max_element_index(const std::list< size_t > &rows, const std::list< size_t > &cols, const Matrix< T > &mat)
Return maximum element in a matrix along specified rows and columns.
Definition util.h:129
std::vector< size_t > eye_order(const Slice &mat)
Returns order of rows in a matrix slice that brings it closest to identity.
Definition util.h:158
auto overlap(const CVecRef< R > &left, const CVecRef< Q > &right, array::ArrayHandler< Z, W > &handler) -> std::enable_if_t< detail::Z_and_W_are_one_of_R_and_Q< R, Q, Z, W >, Matrix< typename array::ArrayHandler< Z, W >::value_type > >
Calculates overlap matrix between left and right vectors.
Definition util.h:57
void matrix_symmetrize(Matrix< T > &mat)
Replaces a matrix by its hermitian part, which for a real element type is its symmetric part.
Definition util.h:118
std::vector< real_type_t< T > > solution_norms(const Matrix< T > &solutions, const Matrix< T > &overlap)
The Euclidean norms of the solutions x_i = sum_j c_ij b_j, from their subspace coefficients c (one ro...
Definition util.h:82
void conjugate_transpose_copy(ML &&ml, const MR &mr)
Copies the conjugate transpose of mr into ml.
Definition Matrix.h:299
std::unique_ptr< LinearEigensystem< R, Q, P > > create_LinearEigensystem(const LinearEigensystemOptions &options, const std::shared_ptr< ArrayHandlers< R, Q, P > > &handlers=std::make_shared< molpro::linalg::itsolv::ArrayHandlers< R, Q, P > >())
Definition SolverFactory.h:111
std::vector< std::reference_wrapper< const A > > CVecRef
Definition wrap.h:14
T conjugate(const T &x)
Complex conjugate, staying within the scalar type; the identity for a real type.
Definition scalar_traits.h:47
typename array::ArrayHandler< Z, W >::value_type value_type
Definition util.h:33
static Matrix< value_type > _(const CVecRef< R > &left, const CVecRef< Q > &right, array::ArrayHandler< Z, W > &handler)
Definition util.h:34
typename array::ArrayHandler< Z, W >::value_type value_type
Definition util.h:41
static Matrix< value_type > _(const CVecRef< R > &left, const CVecRef< Q > &right, array::ArrayHandler< Z, W > &handler)
Definition util.h:42
Checks that type T1 is same as one of T2, Ts ...
Definition util.h:18
static constexpr bool value
Definition util.h:19