TRIQS/nda 1.3.0
Multi-dimensional array library for C++
Loading...
Searching...
No Matches
eigenelements.hpp
Go to the documentation of this file.
1// Copyright (c) 2019-2023 Simons Foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0.txt
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14//
15// Authors: Olivier Parcollet, Nils Wentzell
16
17/**
18 * @file
19 * @brief Provides eigenvalues and eigenvectors of a symmetric or hermitian matrix.
20 */
21
22#pragma once
23
24#include "./det_and_inverse.hpp"
25#include "../basic_array.hpp"
26#include "../declarations.hpp"
27#include "../exceptions.hpp"
28#include "../lapack/interface/cxx_interface.hpp"
29#include "../layout/policies.hpp"
30#include "../macros.hpp"
31#include "../traits.hpp"
32
33#include <type_traits>
34#include <utility>
35
36namespace nda::linalg {
37
38 namespace detail {
39
40 // Dispatch the call to the appropriate LAPACK routine based on the value type of the matrix.
41 template <typename M>
42 auto _eigen_element_impl(M &&m, char compz) { // NOLINT (temporary views are allowed here)
43 using value_type = typename std::decay_t<M>::value_type;
44
45 // runtime checks
46 EXPECTS((not m.empty()));
47 EXPECTS(is_matrix_square(m, true));
48 EXPECTS(m.indexmap().is_contiguous());
49
50 // set up the workspace
51 int dim = m.extent(0);
52 int lwork = 64 * dim;
53 array<double, 1> ev(dim);
54 array<value_type, 1> work(lwork);
55 array<double, 1> work2(is_complex_v<value_type> ? lwork : 0);
56
57#if defined(__has_feature)
58#if __has_feature(memory_sanitizer)
59 work2 = 0;
60 work = 0;
61 ev = 0;
62#endif
63#endif
64
65 // call the correct LAPACK routine
66 int info = 0;
67 if constexpr (not is_complex_v<value_type>) {
68 lapack::f77::syev(compz, 'U', dim, m.data(), dim, ev.data(), work.data(), lwork, info);
69 } else {
70 lapack::f77::heev(compz, 'U', dim, m.data(), dim, ev.data(), work.data(), lwork, work2.data(), info);
71 }
72 if (info) NDA_RUNTIME_ERROR << "Error in nda::linalg::detail::_eigen_element_impl: Diagonalization error";
73 return ev;
74 }
75
76 } // namespace detail
77
78 /**
79 * @addtogroup linalg_tools
80 * @{
81 */
82
83 /**
84 * @brief Find the eigenvalues and eigenvectors of a symmetric (real) or hermitian (complex) matrix/view.
85 *
86 * @details For a real symmetric matrix/view, it calls the LAPACK routine `syev`. For a complex hermitian matrix/view,
87 * it calls the LAPACK routine `heev`.
88 *
89 * The given matrix/view is copied and the original is not modified.
90 *
91 * @tparam M Type of the matrix/view.
92 * @param m Matrix/View to diagonalize.
93 * @return std::pair consisting of the array of eigenvalues in ascending order and the matrix containing the
94 * eigenvectors in its columns.
95 */
96 template <typename M>
97 auto eigenelements(M const &m) {
98 auto m_copy = matrix<typename M::value_type, F_layout>(m);
99 auto ev = detail::_eigen_element_impl(m_copy, 'V');
100 return std::pair<array<double, 1>, typename M::regular_type>{ev, m_copy};
101 }
102
103 /**
104 * @brief Find the eigenvalues of a symmetric (real) or hermitian (complex) matrix/view.
105 *
106 * @details For a real symmetric matrix/view, it calls the LAPACK routine `syev`. For a complex hermitian matrix/view,
107 * it calls the LAPACK routine `heev`.
108 *
109 * The given matrix/view is copied and the original is not modified.
110 *
111 * @tparam M Type of the matrix/view.
112 * @param m Matrix/View to diagonalize.
113 * @return An nda::array of rank 1 containing the eigenvalues in ascending order.
114 */
115 template <typename M>
116 auto eigenvalues(M const &m) {
117 auto m_copy = matrix<typename M::value_type, F_layout>(m);
118 return detail::_eigen_element_impl(m_copy, 'N');
119 }
120
121 /**
122 * @brief Find the eigenvalues of a symmetric (real) or hermitian (complex) matrix/view.
123 *
124 * @details For a real symmetric matrix/view, it calls the LAPACK routine `syev`. For a complex hermitian matrix/view,
125 * it calls the LAPACK routine `heev`.
126 *
127 * The given matrix/view will be modified by the diagonalization process.
128 *
129 * @tparam M Type of the matrix/view.
130 * @param m Matrix/View to diagonalize.
131 * @return An nda::array of rank 1 containing the eigenvalues in ascending order.
132 */
133 template <typename M>
135 return detail::_eigen_element_impl(m, 'N');
136 }
137
138 /** @} */
139
140} // namespace nda::linalg
ValueType * data() noexcept
Get a pointer to the actual data (in general this is not the beginning of thr memory block for a view...
#define NDA_RUNTIME_ERROR
auto eigenvalues(M const &m)
Find the eigenvalues of a symmetric (real) or hermitian (complex) matrix/view.
auto eigenelements(M const &m)
Find the eigenvalues and eigenvectors of a symmetric (real) or hermitian (complex) matrix/view.
auto eigenvalues_in_place(M &m)
Find the eigenvalues of a symmetric (real) or hermitian (complex) matrix/view.
#define EXPECTS(X)
Definition macros.hpp:59
Contiguous layout policy with Fortran-order (column-major order).
Definition policies.hpp:63