Skip to content

Commit 68f5c60

Browse files
Critsium-xyclaude
andcommitted
Refactor: inject solver config into HSolver/PEXSI instead of reading PARAM
Group C of the source_hsolver PARAM removal: the parameters that were read from the PARAM global mid-algorithm are now injected through constructors, following the existing explicit-scalar style of the HSolverPW / HSolverLCAO constructors. HSolverPW gains nbands, diago_smooth_ethr, pw_diag_ndim, diag_subspace and nb2d. Note that PARAM.inp.nbands (the global band count used by bpcg's init_iter) is deliberately kept distinct from psi.get_nbands(), which is the local count under band parallelism. HSolverPW_SDFT gains ks_run, all_ks_run and bndpar, and forwards the five new base-class values. HSolverLIP gains use_uspp. HSolverLCAO gains kpar_lcao, plus nlocal and nelec for the pexsi branch. PEXSI chain: the two reads in module_pexsi/pexsi_solver.cpp could not simply be lifted to its caller, because DiagoPexsi did not have nelec either, so the whole chain is threaded in one go: - PEXSI_Solver::prepare() takes nlocal and nelec and stores them, alongside the nb / nrow / ncol it already received. - DiagoPexsi's constructor takes nspin, nlocal and nelec. The nspin == 4 -> single-density-matrix collapse was computed identically in the constructor and the destructor; it is now stored once as nspin_dm, which also removes the destructor's dependency on PARAM still holding the same nspin. - HSolverLCAO passes its solve()-argument nspin plus the injected nlocal and nelec down to DiagoPexsi. Two incidental fixes in code that had to be touched anyway: - DiagoPexsi::diag() declared a std::vector<double> eigen(nlocal) that was never used; removed. This was the only nlocal read in that function. - The constructor read pexsi_mu through this->ps before ps was assigned. It is a static member so this happened to work, but it is UB on a null unique_ptr; it now reads pexsi::PEXSI_Solver::pexsi_mu directly. Also fixes a pre-existing bug in test_hsolver_pw.cpp: the HSolverPW fixture passed an extra `false` after method_in, so every argument from nspin_in onwards was shifted by one (nspin_in received use_uspp, diag_thr_in received PW_DIAG_NMAX, need_subspace_in received PW_DIAG_THR, and so on). Adding the new parameters made the call fail to compile, which surfaced it. The affected tests only construct the object or exercise the early npw_total < nbands guard, so no assertion depended on the shifted values. PARAM occurrences in source_hsolver production code: 83 -> 60. Remaining are the six dense LCAO diagonalizers sharing nlocal/nbands (group D) and DiagoIterAssist's basis_type/calculation switches (group E). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 3e64d44 commit 68f5c60

22 files changed

Lines changed: 169 additions & 62 deletions

source/source_esolver/esolver_ks_lcao.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -434,7 +434,11 @@ void ESolver_KS_LCAO<TK, TR>::hamilt2rho_single(UnitCell& ucell, int istep, int
434434
// 3) run Hsolver
435435
if (!skip_solve)
436436
{
437-
hsolver::HSolverLCAO<TK> hsolver_lcao_obj(&(this->pv), PARAM.inp.ks_solver);
437+
hsolver::HSolverLCAO<TK> hsolver_lcao_obj(&(this->pv),
438+
PARAM.inp.ks_solver,
439+
PARAM.globalv.kpar_lcao,
440+
PARAM.globalv.nlocal,
441+
PARAM.inp.nelec);
438442
hsolver_lcao_obj.solve(static_cast<hamilt::Hamilt<TK>*>(this->p_hamilt), this->psi[0], this->pelec, *this->dmat.dm,
439443
this->chr, PARAM.inp.nspin, skip_charge);
440444
}

source/source_esolver/esolver_ks_lcao_tddft.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,11 @@ void ESolver_KS_LCAO_TDDFT<TR, Device>::hamilt2rho_single(UnitCell& ucell,
329329
if (this->psi != nullptr)
330330
{
331331
bool skip_charge = PARAM.inp.calculation == "nscf" ? true : false;
332-
hsolver::HSolverLCAO<std::complex<double>> hsolver_lcao_obj(&this->pv, PARAM.inp.ks_solver);
332+
hsolver::HSolverLCAO<std::complex<double>> hsolver_lcao_obj(&this->pv,
333+
PARAM.inp.ks_solver,
334+
PARAM.globalv.kpar_lcao,
335+
PARAM.globalv.nlocal,
336+
PARAM.inp.nelec);
333337
hsolver_lcao_obj.solve(static_cast<hamilt::Hamilt<std::complex<double>>*>(this->p_hamilt),
334338
this->psi[0],
335339
this->pelec,

source/source_esolver/esolver_ks_lcaopw.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ namespace ModuleESolver
133133
hsolver::DiagoIterAssist<T>::PW_DIAG_NMAX = PARAM.inp.pw_diag_nmax;
134134
bool skip_charge = PARAM.inp.calculation == "nscf" ? true : false;
135135

136-
hsolver::HSolverLIP<T> hsolver_lip_obj(this->pw_wfc);
136+
hsolver::HSolverLIP<T> hsolver_lip_obj(this->pw_wfc, PARAM.globalv.use_uspp);
137137
hsolver_lip_obj.solve(static_cast<hamilt::Hamilt<T>*>(this->p_hamilt), *this->stp.template get_psi_t<T, base_device::DEVICE_CPU>(), this->pelec,
138138
*this->psi_local, skip_charge,ucell.tpiba,ucell.nat);
139139

source/source_esolver/esolver_ks_pw.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ void ESolver_KS_PW<T, Device>::hamilt2rho_single(UnitCell& ucell, const int iste
222222
hsolver::DiagoIterAssist<T, Device>::PW_DIAG_NMAX,
223223
hsolver::DiagoIterAssist<T, Device>::PW_DIAG_THR,
224224
hsolver::DiagoIterAssist<T, Device>::need_subspace,
225+
PARAM.inp.nbands,
226+
PARAM.inp.diago_smooth_ethr,
227+
PARAM.inp.pw_diag_ndim,
228+
PARAM.inp.diag_subspace,
229+
PARAM.inp.nb2d,
225230
PARAM.inp.use_k_continuity);
226231

227232
hsolver_pw_obj.solve(static_cast<hamilt::Hamilt<T, Device>*>(this->p_hamilt), *this->stp.template get_psi_t<T, Device>(), this->pelec, this->pelec->ekb.c,

source/source_esolver/esolver_sdft_pw.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,15 @@ void ESolver_SDFT_PW<T, Device>::hamilt2rho_single(UnitCell& ucell, int istep, i
163163
hsolver::DiagoIterAssist<T, Device>::SCF_ITER,
164164
hsolver::DiagoIterAssist<T, Device>::PW_DIAG_NMAX,
165165
hsolver::DiagoIterAssist<T, Device>::PW_DIAG_THR,
166-
hsolver::DiagoIterAssist<T, Device>::need_subspace);
166+
hsolver::DiagoIterAssist<T, Device>::need_subspace,
167+
PARAM.inp.nbands,
168+
PARAM.inp.diago_smooth_ethr,
169+
PARAM.inp.pw_diag_ndim,
170+
PARAM.inp.diag_subspace,
171+
PARAM.inp.nb2d,
172+
PARAM.globalv.ks_run,
173+
PARAM.globalv.all_ks_run,
174+
PARAM.inp.bndpar);
167175

168176
hsolver_pw_sdft_obj.solve(ucell,
169177
static_cast<hamilt::Hamilt<T, Device>*>(this->p_hamilt),

source/source_hsolver/diago_pexsi.cpp

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#include <mpi.h>
22
#include <complex>
3-
#include "source_io/module_parameter/parameter.h"
43
#include <memory>
54
#ifdef __PEXSI
65
#include "diago_pexsi.h"
@@ -19,25 +18,27 @@ template <typename T>
1918
std::vector<double> DiagoPexsi<T>::mu_buffer;
2019

2120
template <typename T>
22-
DiagoPexsi<T>::DiagoPexsi(const Parallel_Orbitals* ParaV_in)
21+
DiagoPexsi<T>::DiagoPexsi(const Parallel_Orbitals* ParaV_in,
22+
const int nspin_in,
23+
const int nlocal_in,
24+
const double nelec_in)
2325
{
24-
int nspin = PARAM.inp.nspin;
25-
if (PARAM.inp.nspin == 4)
26-
{
27-
nspin = 1;
28-
}
29-
mu_buffer.resize(nspin);
30-
for (int i = 0; i < nspin; i++)
26+
this->nspin_dm = (nspin_in == 4) ? 1 : nspin_in;
27+
this->nlocal = nlocal_in;
28+
this->nelec = nelec_in;
29+
30+
mu_buffer.resize(this->nspin_dm);
31+
for (int i = 0; i < this->nspin_dm; i++)
3132
{
32-
mu_buffer[i] = this->ps->pexsi_mu;
33+
mu_buffer[i] = pexsi::PEXSI_Solver::pexsi_mu;
3334
}
3435

3536
this->ParaV = ParaV_in;
3637
this->ps = std::make_unique<pexsi::PEXSI_Solver>();
3738

38-
this->DM.resize(nspin);
39-
this->EDM.resize(nspin);
40-
for (int i = 0; i < nspin; i++)
39+
this->DM.resize(this->nspin_dm);
40+
this->EDM.resize(this->nspin_dm);
41+
for (int i = 0; i < this->nspin_dm; i++)
4142
{
4243
this->DM[i] = new T[ParaV->nrow * ParaV->ncol];
4344
this->EDM[i] = new T[ParaV->nrow * ParaV->ncol];
@@ -48,12 +49,7 @@ DiagoPexsi<T>::DiagoPexsi(const Parallel_Orbitals* ParaV_in)
4849
template <typename T>
4950
DiagoPexsi<T>::~DiagoPexsi()
5051
{
51-
int nspin = PARAM.inp.nspin;
52-
if (PARAM.inp.nspin == 4)
53-
{
54-
nspin = 1;
55-
}
56-
for (int i = 0; i < nspin; i++)
52+
for (int i = 0; i < this->nspin_dm; i++)
5753
{
5854
delete[] this->DM[i];
5955
delete[] this->EDM[i];
@@ -67,12 +63,13 @@ void DiagoPexsi<double>::diag(hamilt::Hamilt<double>* phm_in, psi::Psi<double>&
6763
ModuleBase::TITLE("DiagoPEXSI", "diag");
6864
matd h_mat, s_mat;
6965
phm_in->matrix(h_mat, s_mat);
70-
std::vector<double> eigen(PARAM.globalv.nlocal, 0.0);
7166
int ik = psi.get_current_k();
7267
this->ps->prepare(this->ParaV->blacs_ctxt,
7368
this->ParaV->nb,
7469
this->ParaV->nrow,
7570
this->ParaV->ncol,
71+
this->nlocal,
72+
this->nelec,
7673
h_mat.p,
7774
s_mat.p,
7875
DM[ik],

source/source_hsolver/diago_pexsi.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class DiagoPexsi
1919
static std::vector<double> mu_buffer;
2020

2121
public:
22-
DiagoPexsi(const Parallel_Orbitals* ParaV_in);
22+
DiagoPexsi(const Parallel_Orbitals* ParaV_in, const int nspin_in, const int nlocal_in, const double nelec_in);
2323
void diag(hamilt::Hamilt<T>* phm_in, psi::Psi<T>& psi, Real* eigenvalue_in);
2424
const Parallel_Orbitals* ParaV = nullptr;
2525
std::vector<T*> DM;
@@ -29,6 +29,14 @@ class DiagoPexsi
2929
double totalFreeEnergy;
3030
std::unique_ptr<pexsi::PEXSI_Solver> ps;
3131
~DiagoPexsi();
32+
33+
private:
34+
/// number of density matrices to keep: nspin, except that nspin == 4 is
35+
/// treated as a single (spinor) density matrix
36+
int nspin_dm = 1;
37+
/// global dimension of the NAO Hamiltonian
38+
int nlocal = 0;
39+
double nelec = 0.0;
3240
};
3341
} // namespace hsolver
3442

source/source_hsolver/hsolver_lcao.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "source_estate/module_dm/cal_dm_psi.h"
3434
#include "source_estate/module_dm/density_matrix.h"
3535
#include "source_hsolver/parallel_k2d.h"
36-
#include "source_io/module_parameter/parameter.h"
3736

3837
namespace hsolver
3938
{
@@ -59,13 +58,13 @@ void HSolverLCAO<TK, Device>::solve(hamilt::Hamilt<TK>* pHamilt,
5958
this->parakSolve_cusolver(pHamilt, psi, pes);
6059
}else
6160
#endif
62-
if (PARAM.globalv.kpar_lcao > 1
61+
if (this->kpar_lcao > 1
6362
&& (this->method == "genelpa" || this->method == "elpa" || this->method == "scalapack_gvx" || this->method == "lapack"))
6463
{
65-
this->parakSolve(pHamilt, psi, pes, PARAM.globalv.kpar_lcao, nspin);
64+
this->parakSolve(pHamilt, psi, pes, this->kpar_lcao, nspin);
6665
} else
6766
#endif
68-
if (PARAM.globalv.kpar_lcao == 1)
67+
if (this->kpar_lcao == 1)
6968
{
7069
/// Loop over k points for solve Hamiltonian to eigenpairs(eigenvalues and eigenvectors).
7170
for (int ik = 0; ik < psi.get_nk(); ++ik)
@@ -113,7 +112,7 @@ void HSolverLCAO<TK, Device>::solve(hamilt::Hamilt<TK>* pHamilt,
113112
else if (this->method == "pexsi")
114113
{
115114
#ifdef __PEXSI // other purification methods should follow this routine
116-
DiagoPexsi<TK> pe(ParaV);
115+
DiagoPexsi<TK> pe(ParaV, nspin, this->nlocal, this->nelec);
117116
for (int ik = 0; ik < psi.get_nk(); ++ik)
118117
{
119118
/// update H(k) for each k point

source/source_hsolver/hsolver_lcao.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ template <typename TK, typename Device = base_device::DEVICE_CPU>
1515
class HSolverLCAO
1616
{
1717
public:
18-
HSolverLCAO(const Parallel_Orbitals* ParaV_in, std::string method_in) : ParaV(ParaV_in), method(method_in) {};
18+
HSolverLCAO(const Parallel_Orbitals* ParaV_in,
19+
const std::string method_in,
20+
const int kpar_lcao_in,
21+
const int nlocal_in,
22+
const double nelec_in)
23+
: ParaV(ParaV_in), method(method_in), kpar_lcao(kpar_lcao_in), nlocal(nlocal_in), nelec(nelec_in) {};
1924

2025
void solve(hamilt::Hamilt<TK>* pHamilt,
2126
psi::Psi<TK>& psi,
@@ -40,8 +45,12 @@ class HSolverLCAO
4045
elecstate::ElecState* pes);
4146

4247
const Parallel_Orbitals* ParaV = nullptr;
43-
48+
4449
const std::string method;
50+
51+
const int kpar_lcao; // number of pools for LCAO diagonalization
52+
const int nlocal; // global dimension of the NAO Hamiltonian, only used by the pexsi branch
53+
const double nelec; // total number of electrons, only used by the pexsi branch
4554
};
4655

4756
} // namespace hsolver

source/source_hsolver/hsolver_lcaopw.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
#include "source_estate/elecstate_pw.h"
88
#include "source_pw/module_pwdft/hamilt_pw.h"
99
#include "source_hsolver/diago_iter_assist.h"
10-
#include "source_io/module_parameter/parameter.h"
1110
#include "source_estate/elecstate_tools.h"
1211
#include "source_hamilt/module_xc/exx_info.h"
1312

@@ -106,7 +105,7 @@ void HSolverLIP<T>::solve(hamilt::Hamilt<T>* pHamilt, // ESolver_KS_PW::p_hamilt
106105
elecstate::calEBand(pes->ekb,pes->wg,pes->f_en);
107106
if (skip_charge)
108107
{
109-
if (PARAM.globalv.use_uspp)
108+
if (this->use_uspp)
110109
{
111110
reinterpret_cast<elecstate::ElecStatePW<T>*>(pes)->cal_becsum(psi);
112111
}

0 commit comments

Comments
 (0)