-
Notifications
You must be signed in to change notification settings - Fork 134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Numerical instability of Davidson iterative eigensolver in solving LR-TDDFT excited states #5376
Comments
What does it mean to pass larger initial guess of subspace basis than the number of eigenpairs (bands or states) to be solved?
|
Try to solve the issue by yourselves @maki49 @Cstandardlib @haozhihan |
Will the same numerical instability be triggered for CG and Davidson? |
Both the two problems occur also in Davidson, but not so severe (or often). I've tried CG in #5399 , no such problems:
Here's an example of full matrix which faces problem 1 in
|
Iterative solvers are usually intended for relatively large problems and many of them use a LAPACK For example the function We can see from the code that what void DiagoIterAssist<T, Device>::diagH_subspace(const hamilt::Hamilt<T, Device>* const pHamilt, // hamiltonian operator carrier
const psi::Psi<T, Device>& psi, // [in] wavefunction
psi::Psi<T, Device>& evc, // [out] wavefunction
Real* en, // [out] eigenvalues
int n_band // [in] number of bands to be calculated, also number of rows
// of evc, if set to 0, n_band = nstart, default 0
)
{
// two case:
// 1. pw base: nstart = n_band, psi(nbands * npwx)
// 2. lcao_in_pw base: nstart >= n_band, psi(NLOCAL * npwx)
...
{ // code block to calculate hcc and scc
setmem_complex_op()(ctx, temp, 0, nstart * dmax);
T* hphi = temp;
// do hPsi for all bands
psi::Range all_bands_range(1, psi.get_current_k(), 0, nstart - 1);
hpsi_info hpsi_in(&psi, all_bands_range, hphi);
pHamilt->ops->hPsi(hpsi_in);
gemm_op<T, Device>()('C', 'N', psi.get_pointer(),hphi, hcc);
T* sphi = temp;
// do sPsi for all bands
pHamilt->sPsi(psi.get_pointer(), sphi, dmax, dmin, nstart);
gemm_op<T, Device>()('C', 'N', psi, sphi, scc);
}
// after generation of H and S matrix, diag them
DiagoIterAssist::diagH_LAPACK(nstart, n_band, hcc, scc, nstart, en, vcc);
{ // code block to calculate evc
gemm_op<T, Device>()('N', 'N', psi.get_pointer(), vcc, evc);
}
} I extract only the core operation of this function.
This technique is usually applied to a subspace to get eigenpair approximations in all kinds of block iterative methods including Davidson, |
@Cstandardlib Thanks. So can I use |
What's the difference between |
@Cstandardlib I refer to the code from here: abacus-develop/source/module_hsolver/hsolver_pw.cpp Lines 375 to 403 in e5768ec
|
@maki49 Seems that this first-round subspace diagonalization is used to improve the initial guess passed to the iterative solvers. I found changes to these two functions in #4047.
/// solve eigenvector and eigenvalue for H(k)
hsolver::DiagoIterAssist<T>::diagH_subspace_init(
pHamilt, // interface to hamilt
transform.get_pointer(), // transform matrix between lcao and pw
transform.get_nbands(),
transform.get_nbasis(),
psi, // psi in pw basis
eigenvalues.data() + ik * pes->ekb.nc // eigenvalues
#ifdef __EXX
,
add_exx_to_subspace_hamilt,
set_exxlip_lcaowfc
#endif
); and it takes much more parameters as well as supporting more devices than void DiagoIterAssist<T, Device>::diagH_subspace_init(hamilt::Hamilt<T, Device>* pHamilt,
const T* psi,
int psi_nr,
int psi_nc,
psi::Psi<T, Device>& evc,
Real* en,
const std::function<void(T*, const int)>& add_to_hcc,
const std::function<void(const T* const, const int, const int)>& export_vcc)
{
...
if (base_device::get_device_type(ctx) == base_device::GpuDevice)
... In which field do these parameters affect this process? What's the motivation to replace old |
Oh no... both |
Thanks for the help of @haozhihan @Cstandardlib. Now there seems no bug in the usage of However, the hard-coded formula here is unreasonable for LR-TDDFT and slows down the convergence, which needs further refactor: abacus-develop/source/module_hsolver/diago_dav_subspace.cpp Lines 342 to 344 in 7c46674
|
Describe the bug
Now
lr_solver=dav_subspace
has mainly two problems in solving LR-TDDFT excited states:cal_grad
(also appears inlr_solver=dav
)Both of them already exist before #5199, after which the problem 1 become worse.
To Reproduce
In tests/integrate/291_NO_KP_LR, enlarge
lr_nstates
(for example, 10), or use more k-points.Possible Solution (with Refactor)
I'm going to try the following solutions that needs some refactor:
n_bands
initial vectors are copied in.hpsi_func
to enable custom preconditioner (which is hard-coded at present), such as sTDA or rid-preconditionerThe text was updated successfully, but these errors were encountered: