forked from deepmodeling/abacus-develop
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathi_diagonalizer.hpp
More file actions
199 lines (172 loc) · 5.68 KB
/
i_diagonalizer.hpp
File metadata and controls
199 lines (172 loc) · 5.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/**
* @file i_diagonalizer.hpp
* @brief Abstract interface for eigenvalue solver (diagonalizer)
*
* Defines the interface for diagonalizing Hamiltonian matrices
* to obtain eigenvalues and eigenvectors.
*/
#ifndef PYABACUS_ESOLVER_I_DIAGONALIZER_HPP
#define PYABACUS_ESOLVER_I_DIAGONALIZER_HPP
#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <pybind11/functional.h>
#include <complex>
#include <functional>
#include <string>
#include <vector>
namespace py = pybind11;
namespace pyabacus {
namespace esolver {
/**
* @brief Diagonalization method types
*/
enum class DiagMethod
{
Davidson, ///< Davidson iterative method
DavSubspace, ///< Davidson with subspace rotation
CG, ///< Conjugate gradient
LAPACK, ///< Direct LAPACK diagonalization
ScaLAPACK, ///< Parallel ScaLAPACK
ELPA ///< ELPA eigensolver
};
/**
* @brief Result of diagonalization
*/
template <typename TK>
struct DiagResult
{
py::array_t<TK> psi; ///< Eigenvectors
py::array_t<double> eigenvalues; ///< Eigenvalues
int iterations = 0; ///< Number of iterations (for iterative methods)
bool converged = false; ///< Whether converged
double residual = 0.0; ///< Final residual
};
/**
* @brief Configuration for diagonalization
*/
struct DiagConfig
{
DiagMethod method = DiagMethod::Davidson;
double tolerance = 1e-6; ///< Convergence tolerance
int max_iterations = 100; ///< Maximum iterations
int dav_ndim = 4; ///< Davidson subspace dimension multiplier
int nproc_in_pool = 1; ///< Number of processes in pool
};
/**
* @brief Abstract interface for diagonalizer
*
* This interface defines the contract for eigenvalue solvers,
* supporting both direct and iterative methods.
*
* @tparam TK Type for k-space quantities (double or complex<double>)
*/
template <typename TK>
class IDiagonalizer
{
public:
virtual ~IDiagonalizer() = default;
// ==================== Direct Diagonalization ====================
/**
* @brief Diagonalize H(k) and S(k) matrices directly
* @param ik K-point index
* @param Hk Hamiltonian matrix
* @param Sk Overlap matrix
* @param psi_init Initial guess for eigenvectors (optional)
* @return Diagonalization result
*/
virtual DiagResult<TK> diagonalize(int ik,
const py::array_t<TK>& Hk,
const py::array_t<TK>& Sk,
const py::array_t<TK>& psi_init) = 0;
// ==================== Iterative Diagonalization ====================
/**
* @brief Diagonalize using matrix-vector product functions
*
* For iterative methods that don't need explicit matrices.
*
* @param ik K-point index
* @param hpsi_func Function computing H|psi>
* @param spsi_func Function computing S|psi>
* @param psi_init Initial guess for eigenvectors
* @param precond Preconditioner (diagonal approximation to H)
* @return Diagonalization result
*/
virtual DiagResult<TK> diagonalize_iterative(
int ik,
std::function<py::array_t<TK>(const py::array_t<TK>&)> hpsi_func,
std::function<py::array_t<TK>(const py::array_t<TK>&)> spsi_func,
const py::array_t<TK>& psi_init,
const py::array_t<double>& precond) = 0;
// ==================== Configuration ====================
/**
* @brief Set diagonalization configuration
* @param config Configuration
*/
virtual void set_config(const DiagConfig& config) = 0;
/**
* @brief Get current configuration
* @return Current configuration
*/
virtual DiagConfig get_config() const = 0;
/**
* @brief Set convergence tolerance
* @param tol Tolerance
*/
virtual void set_tolerance(double tol) = 0;
/**
* @brief Set maximum iterations
* @param max_iter Maximum iterations
*/
virtual void set_max_iterations(int max_iter) = 0;
// ==================== Dimension Queries ====================
/**
* @brief Get number of basis functions
* @return Number of basis functions
*/
virtual int get_nbasis() const = 0;
/**
* @brief Get number of bands to compute
* @return Number of bands
*/
virtual int get_nbands() const = 0;
/**
* @brief Set number of bands to compute
* @param nbands Number of bands
*/
virtual void set_nbands(int nbands) = 0;
};
// Type aliases for common use cases
using IDiagonalizerGamma = IDiagonalizer<double>;
using IDiagonalizerMultiK = IDiagonalizer<std::complex<double>>;
/**
* @brief Convert DiagMethod enum to string
*/
inline std::string diag_method_to_string(DiagMethod method)
{
switch (method)
{
case DiagMethod::Davidson: return "davidson";
case DiagMethod::DavSubspace: return "dav_subspace";
case DiagMethod::CG: return "cg";
case DiagMethod::LAPACK: return "lapack";
case DiagMethod::ScaLAPACK: return "scalapack";
case DiagMethod::ELPA: return "elpa";
default: return "unknown";
}
}
/**
* @brief Convert string to DiagMethod enum
*/
inline DiagMethod string_to_diag_method(const std::string& str)
{
if (str == "davidson") return DiagMethod::Davidson;
if (str == "dav_subspace") return DiagMethod::DavSubspace;
if (str == "cg") return DiagMethod::CG;
if (str == "lapack") return DiagMethod::LAPACK;
if (str == "scalapack") return DiagMethod::ScaLAPACK;
if (str == "elpa") return DiagMethod::ELPA;
return DiagMethod::Davidson; // default
}
} // namespace esolver
} // namespace pyabacus
#endif // PYABACUS_ESOLVER_I_DIAGONALIZER_HPP