ABACUS develop
Atomic-orbital Based Ab-initio Computation at UStc
Loading...
Searching...
No Matches
hsolver_lrtd.hpp
Go to the documentation of this file.
1#pragma once
11
12namespace LR
13{
14 template<typename T> using Real = typename GetTypeReal<T>::type;
15
16 namespace HSolver
17 {
18 template<typename T>
19 inline void print_eigs(const std::vector<T>& eigs, const std::string& label = "", const double factor = 1.0)
20 {
21 std::cout << label << std::endl;
22 for (auto& e : eigs) { std::cout << e * factor << " "; }
23 std::cout << std::endl;
24 }
25
27 template<typename T, typename THamilt>
28 void solve(const THamilt& hm,
29 T* psi,
30 const int& dim,
31 const int& nband,
32 double* eig,
33 const std::string method,
34 const Real<T>& diag_ethr,
35 const std::vector<Real<T>>& precondition,
36 const bool hermitian = true)
37 {
38 ModuleBase::TITLE("HSolverLR", "solve");
39 const std::vector<std::string> spin_types = { "singlet", "triplet" };
40 // note: if not TDA, the eigenvalues will be complex
41 // then we will need a new constructor of DiagoDavid
42
43 // 1. allocate eigenvalue
44 std::vector<Real<T>> eigenvalue(nband); //nstates
45 // 2. select the method
46#ifdef __MPI
48#else
50#endif
51
52 if (method == "lapack")
53 {
54 std::vector<T> Amat_full = hm.matrix();
55 const int gdim = std::sqrt(Amat_full.size());
56 eigenvalue.resize(gdim);
57 if (hermitian) { LR_Util::diag_lapack(gdim, Amat_full.data(), eigenvalue.data()); }
58 else
59 {
60 std::vector<std::complex<double>> eig_complex(gdim);
61 LR_Util::diag_lapack_nh(gdim, Amat_full.data(), eig_complex.data());
62 print_eigs(eig_complex, "Right eigenvalues: of the non-Hermitian matrix: (Ry)");
63 for (int i = 0; i < gdim; i++) { eigenvalue[i] = eig_complex[i].real(); }
64 }
65 // copy eigenvectors
66 hm.global2local(psi, Amat_full.data(), nband);
67 }
68 else
69 {
70 // 3. set maxiter and funcs
72
73 auto hpsi_func = [&hm](T* psi_in, T* hpsi, const int ld_psi, const int nvec) {hm.hPsi(psi_in, hpsi, ld_psi, nvec);};
74 auto spsi_func = [&hm](const T* psi_in, T* spsi, const int ld_psi, const int nvec)
75 { std::memcpy(spsi, psi_in, sizeof(T) * ld_psi * nvec); };
76
77 if (method == "dav")
78 {
79 // Allow 5 tries at most. If ntry > ntry_max = 5, exit diag loop.
80 const int ntry_max = 5;
81 // In non-self consistent calculation, do until totally converged. Else allow 5 eigenvecs to be NOT
82 // converged.
83 const int notconv_max = ("nscf" == PARAM.inp.calculation) ? 0 : 5;
84 // do diag and add davidson iteration counts up to avg_iter
85 hsolver::DiagoDavid<T> david(precondition.data(),
86 nband,
87 dim,
89 false,
90 comm_info);
91 std::vector<double> ethr_band(nband, diag_ethr);
92 hsolver::DiagoIterAssist<T>::avg_iter += static_cast<double>(david.diag(hpsi_func, spsi_func,
93 dim, psi, eigenvalue.data(), ethr_band, maxiter, ntry_max, 0));
94 }
95 else if (method == "dav_subspace") //need refactor
96 {
97 hsolver::Diago_DavSubspace<T> dav_subspace(precondition,
98 nband,
99 dim,
101 diag_ethr,
102 maxiter,
103 false, //always do the subspace diag (check the implementation)
104 comm_info,
106 PARAM.inp.nb2d);
107 std::vector<double> ethr_band(nband, diag_ethr);
108 hsolver::DiagoIterAssist<T>::avg_iter += static_cast<double>(
109 dav_subspace.diag(hpsi_func, spsi_func, psi, dim, eigenvalue.data(), ethr_band, false /*scf*/));
110 }
111 else if (method == "cg")
112 {
116
117 // auto subspace_func = [&hm](const ct::Tensor& psi_in, ct::Tensor& psi_out) {
118 // const auto ndim = psi_in.shape().ndim();
119 // REQUIRES_OK(ndim == 2, "dims of psi_in should be less than or equal to 2");
120 // // Convert a Tensor object to a psi::Psi object
121 // auto psi_in_wrapper = psi::Psi<T>(psi_in.data<T>(),
122 // 1,
123 // psi_in.shape().dim_size(0),
124 // psi_in.shape().dim_size(1));
125 // auto psi_out_wrapper = psi::Psi<T>(psi_out.data<T>(),
126 // 1,
127 // psi_out.shape().dim_size(0),
128 // psi_out.shape().dim_size(1));
129 // auto eigen = ct::Tensor(ct::DataTypeToEnum<Real<T>>::value,
130 // ct::DeviceType::CpuDevice,
131 // ct::TensorShape({ psi_in.shape().dim_size(0) }));
132 // hsolver::DiagoIterAssist<T>::diagH_subspace(hm, psi_in_wrapper, psi_out_wrapper, eigen.data<Real<T>>());
133 // };
134
136 // hsolver::DiagoCG<T> cg("lcao", "nscf", true, subspace_func, diag_ethr, maxiter, GlobalV::NPROC_IN_POOL);
137
138 auto subspace_func = [](const ct::Tensor& psi_in, ct::Tensor& psi_out) {};
139 hsolver::DiagoCG<T> cg("lcao", "nscf", false, subspace_func, diag_ethr, maxiter, GlobalV::NPROC_IN_POOL);
140
141 auto psi_tensor = ct::TensorMap(psi, ct::DataTypeToEnum<T>::value, ct::DeviceType::CpuDevice, ct::TensorShape({ nband, dim }));
142 auto eigen_tensor = ct::TensorMap(eigenvalue.data(), ct::DataTypeToEnum<Real<T>>::value, ct::DeviceType::CpuDevice, ct::TensorShape({ nband }));
143 std::vector<Real<T>> precondition_(precondition); //since TensorMap does not support const pointer
144 auto precon_tensor = ct::TensorMap(precondition_.data(), ct::DataTypeToEnum<Real<T>>::value, ct::DeviceType::CpuDevice, ct::TensorShape({ dim }));
145 auto hpsi_func = [&hm](const ct::Tensor& psi_in, ct::Tensor& hpsi) {hm.hPsi(psi_in.data<T>(), hpsi.data<T>(), psi_in.shape().dim_size(0) /*nbasis_local*/, 1/*band-by-band*/);};
146 auto spsi_func = [&hm](const ct::Tensor& psi_in, ct::Tensor& spsi) {
147 std::memcpy(spsi.data<T>(), psi_in.data<T>(), sizeof(T) * psi_in.NumElements());
148 };
149
150 std::vector<double> ethr_band(nband, diag_ethr);
151 cg.diag(hpsi_func, spsi_func, psi_tensor, eigen_tensor, ethr_band, precon_tensor);
152 }
153 else { throw std::runtime_error("HSolverLR::solve: method not implemented"); }
154 }
155
156 // 5. copy eigenvalues
157 for (int ist = 0;ist < nband;++ist) { eig[ist] = eigenvalue[ist]; }
158
159 // 6. output eigenvalues and eigenvectors
160 print_eigs(eigenvalue, "eigenvalues: (Ry)");
161 print_eigs(eigenvalue, "eigenvalues: (eV)", ModuleBase::Ry_to_eV);
162
163 // normalization is already satisfied
164 // std::cout << "check normalization of eigenvectors:" << std::endl;
165 // for (int ist = 0;ist < nband;++ist)
166 // {
167 // double norm2 = 0;
168 // for (int ik = 0;ik < psi.get_nk();++ik)
169 // {
170 // for (int ib = 0;ib < psi.get_nbasis();++ib)
171 // {
172 // norm2 += std::norm(psi(ist, ik, ib));
173 // // std::cout << "norm2_now=" << norm2 << std::endl;
174 // }
175 // }
176 // std::cout << "state " << ist << ", norm2=" << norm2 << std::endl;
177 // }
178
179 // output iters
180 std::cout << " Average iterative diagonalization steps: " << hsolver::DiagoIterAssist<T>::avg_iter
181 << "; current threshold: " << hsolver::DiagoIterAssist<T>::PW_DIAG_THR << std::endl;
182 }
183 }
184}
const Input_para & inp
Definition parameter.h:26
A multi-dimensional reference array of elements of a single data type.
Definition tensor_map.h:19
A class for representing the shape of a tensor.
Definition tensor_shape.h:13
int64_t dim_size(int dim) const
Get the size of a dimension in the tensor.
Definition tensor_shape.cpp:31
A multi-dimensional array of elements of a single data type.
Definition tensor.h:32
void * data() const
Get a pointer to the data buffer of the tensor.
Definition tensor.cpp:73
int64_t NumElements() const
Get the total number of elements in the tensor.
Definition tensor.cpp:70
const TensorShape & shape() const
Get the shape of the tensor.
Definition tensor.cpp:67
Definition diago_cg.h:16
void diag(const Func &hpsi_func, const Func &spsi_func, ct::Tensor &psi, ct::Tensor &eigen, const std::vector< double > &ethr_band, const ct::Tensor &prec={})
Definition diago_cg.cpp:578
A class that implements the block-Davidson algorithm for solving generalized eigenvalue problems.
Definition diago_david.h:27
int diag(const HPsiFunc &hpsi_func, const SPsiFunc &spsi_func, const int ld_psi, T *psi_in, Real *eigenvalue_in, const std::vector< double > &ethr_band, const int david_maxiter, const int ntry_max=5, const int notconv_max=0)
Performs iterative diagonalization using the David algorithm.
Definition diago_david.cpp:967
Definition diago_iter_assist.h:14
Definition diago_dav_subspace.h:19
int diag(const HPsiFunc &hpsi_func, const HPsiFunc &spsi_func, T *psi_in, const int psi_in_dmax, Real *eigenvalue_in, const std::vector< double > &ethr_band, const bool &scf_type)
Definition diago_dav_subspace.cpp:824
#define T
Definition exp.cpp:237
int NPROC_IN_POOL
local number of process in a pool
Definition global_variable.cpp:24
int RANK_IN_POOL
global index of pool (count in process), my_rank in each pool
Definition global_variable.cpp:26
void print_eigs(const std::vector< T > &eigs, const std::string &label="", const double factor=1.0)
Definition hsolver_lrtd.hpp:19
void solve(const THamilt &hm, T *psi, const int &dim, const int &nband, double *eig, const std::string method, const Real< T > &diag_ethr, const std::vector< Real< T > > &precondition, const bool hermitian=true)
eigensolver for common Hamilt
Definition hsolver_lrtd.hpp:28
void diag_lapack(const int &n, double *mat, double *eig)
diagonalize a hermitian matrix
Definition lr_util.cpp:118
void diag_lapack_nh(const int &n, double *mat, std::complex< double > *eig)
diagonalize a general matrix
Definition lr_util.cpp:147
Definition esolver_ks_lcao.h:37
typename GetTypeReal< T >::type Real
Definition hsolver_lrtd.hpp:14
const double Ry_to_eV
Definition constants.h:81
void TITLE(const std::string &class_name, const std::string &function_name, const bool disable)
Definition tool_title.cpp:18
Definition exx_lip.h:23
MPI_Comm POOL_WORLD
Definition parallel_comm.cpp:6
Parameter PARAM
Definition parameter.cpp:3
T type
Definition macros.h:8
std::string calculation
Definition input_parameter.h:19
int diag_subspace
Definition input_parameter.h:90
int pw_diag_ndim
dimension of workspace for Davidson diagonalization
Definition input_parameter.h:88
int nb2d
matrix 2d division.
Definition input_parameter.h:129
Template struct for mapping a DataType to its corresponding enum value.
Definition tensor_types.h:194
Definition diag_comm_info.h:12