Skip to content

Adaptive Convergence Optimization for Eigenvalue Iterative Solvers (CG & David)#7523

Open
tanrt123-tech wants to merge 3 commits into
deepmodeling:developfrom
tanrt123-tech:opt
Open

Adaptive Convergence Optimization for Eigenvalue Iterative Solvers (CG & David)#7523
tanrt123-tech wants to merge 3 commits into
deepmodeling:developfrom
tanrt123-tech:opt

Conversation

@tanrt123-tech

Copy link
Copy Markdown

Summary

This PR improves the convergence robustness and preconditioning behavior of the iterative eigensolvers in source/source_hsolver, mainly targeting DiagoCG and DiagoDavid.

The main changes are:

  • Add adaptive PR+ direction protection to DiagoCG.
  • Add selectable preconditioner types to DiagoDavid.
  • Implement a shifted diagonal Davidson preconditioner.
  • Add adaptive Davidson subspace refresh logic.
  • Extend Davidson unit tests to cover both the new and legacy preconditioner paths.

Motivation

The existing CG and Davidson eigensolvers can be sensitive to poor initial guesses, near-degenerate eigenvalues, or less effective preconditioning.

In DiagoCG, the Polak-Ribiere coefficient may become negative or excessively large, which can produce unstable search directions and slow convergence.

In DiagoDavid, the previous preconditioner used a fixed diagonal denominator and did not account for the current Ritz value. This limits its ability to adapt to different spectral regions.

Implementation Details

For DiagoCG, this PR adds adaptive CG controls:

void set_adaptive_cg(const bool use_pr_plus,
                     const Real max_gamma = static_cast<Real>(5.0));

The CG update now applies PR+ protection:

gamma = std::max(static_cast<Real>(0.0), gamma);
gamma = std::min(gamma, this->max_cg_gamma_);

For DiagoDavid, this PR introduces:

enum class DiagoPreconditioner
{
    Diagonal,
    ShiftedDiagonal
};

The default preconditioner is now ShiftedDiagonal, using the current Ritz value to build a safer and more adaptive denominator:

0.5 * (1.0 + x + sqrt(1.0 + (x - 1.0) * (x - 1.0)))

where:

x = abs(diagonal - eigenvalue)

This PR also adds adaptive Davidson refresh logic. When the subspace is close to full and many bands are still unconverged, the solver refreshes the subspace earlier to avoid unnecessary growth of the projected eigenproblem.

Tests

Configured and built with MPI:

cmake -S . -B /tmp/abacus-diago-mpi-build \
  -DCMAKE_CXX_COMPILER=mpicxx \
  -DBUILD_TESTING=ON \
  -DENABLE_MPI=ON \
  -DENABLE_LCAO=OFF \
  -DUSE_ELPA=OFF \
  -DGIT_SUBMODULE=OFF

Built relevant test targets:

cmake --build /tmp/abacus-diago-mpi-build \
  --target MODULE_HSOLVER_cg MODULE_HSOLVER_dav \
           MODULE_HSOLVER_cg_float MODULE_HSOLVER_dav_float \
  -j2

Ran single-process tests:

ctest --test-dir /tmp/abacus-diago-mpi-build \
  -R "^MODULE_HSOLVER_(cg|dav|cg_float|dav_float)$" \
  --output-on-failure

Result:

100% tests passed, 0 tests failed out of 4

Ran parallel tests:

ctest --test-dir /tmp/abacus-diago-mpi-build \
  -R "^MODULE_HSOLVER_(cg_parallel|dav_parallel)$" \
  --output-on-failure

Result:

100% tests passed, 0 tests failed out of 2

Also checked patch formatting:

git diff --check

Result: passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant