Skip to content

Commit dbe2898

Browse files
committed
Refactor WFN extrapolation into module_extrap
1 parent d4fd81f commit dbe2898

3 files changed

Lines changed: 136 additions & 86 deletions

File tree

source/source_esolver/esolver_ks_lcao.cpp

Lines changed: 10 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@
1919
#endif
2020
#include "source_lcao/module_rdmft/rdmft.h"
2121
#include "source_lcao/module_extrap/wf_history_lcao.h"
22-
#include "source_lcao/module_operator_lcao/operator_lcao.h" // build overlap SR before WFN reorthonormalization
2322
#include "source_estate/module_charge/chgmixing.h" // use charge mixing, mohan add 20251006
2423
#include "source_estate/module_dm/init_dm.h" // init dm from electronic wave functions
25-
#include "source_estate/module_dm/cal_dm_psi.h" // rebuild DMK from extrapolated WFN
2624
#include "source_io/module_ctrl/ctrl_runner_lcao.h" // use ctrl_runner_lcao()
2725
#include "source_io/module_ctrl/ctrl_iter_lcao.h" // use ctrl_iter_lcao()
2826
#include "source_io/module_ctrl/ctrl_scf_lcao.h" // use ctrl_scf_lcao()
@@ -31,10 +29,6 @@
3129
#include "source_lcao/LCAO_set.h" // mohan add 20251111
3230
#include "source_psi/setup_psi.h" // use Setup_Psi for deallocate_psi
3331

34-
#include <iomanip>
35-
#include <sstream>
36-
#include <string>
37-
#include <type_traits>
3832

3933
namespace ModuleESolver
4034
{
@@ -215,86 +209,17 @@ void ESolver_KS_LCAO<TK, TR>::before_scf(UnitCell& ucell, const int istep)
215209
}
216210
else if(PARAM.inp.esolver_type!="tddft")//initialize DMR from WFN history if required
217211
{
218-
if (std::is_same<TK, double>::value)
212+
if (this->wf_history_lcao_ != nullptr)
219213
{
220-
if (this->wf_history_lcao_ != nullptr)
221-
{
222-
// The newly-created HamiltLCAO has allocated S(R), but the actual
223-
// overlap values are normally filled later by updateHk() inside the
224-
// eigensolver. WFN extrapolation needs S before entering SCF, so build
225-
// only the overlap real-space matrix here and then fold it to S(Gamma).
226-
auto* lcao_op = dynamic_cast<hamilt::OperatorLCAO<TK, TR>*>(hamilt_lcao->getOperator());
227-
if (lcao_op == nullptr)
228-
{
229-
ModuleBase::WARNING_QUIT("ESolver_KS_LCAO::before_scf",
230-
"Failed to access the LCAO operator chain for WFN extrapolation.");
231-
}
232-
ModuleBase::timer::start("WFN_Extrap", "prepare_overlap");
233-
lcao_op->contributeHR();
234-
// Refresh the current Gamma-only overlap matrix before reusing the previous WFN.
235-
// The layout must follow the active LCAO solver because the WFN orthonormalizer
236-
// assembles distributed local blocks using the same column/row-major convention.
237-
const int sk_layout =
238-
ModuleBase::GlobalFunc::IS_COLUMN_MAJOR_KS_SOLVER(PARAM.inp.ks_solver) ? 1 : 0;
239-
hamilt_lcao->updateSk(0, sk_layout);
240-
ModuleBase::timer::end("WFN_Extrap", "prepare_overlap");
241-
242-
ModuleBase::timer::start("WFN_Extrap", "apply");
243-
const ModuleExtrap::WfExtrapApplyResult wfc_result
244-
= this->wf_history_lcao_->try_use_prev_wf_gamma(hamilt_lcao->getSk(),
245-
this->pv,
246-
*(this->psi),
247-
this->pelec->wg);
248-
ModuleBase::timer::end("WFN_Extrap", "apply");
249-
if (wfc_result.ok())
250-
{
251-
ModuleBase::timer::start("WFN_Extrap", "rebuild_density");
252-
elecstate::cal_dm_psi(this->dmat.dm->get_paraV_pointer(),
253-
this->pelec->wg,
254-
*(this->psi),
255-
*(this->dmat.dm));
256-
this->dmat.dm->cal_DMR();
257-
LCAO_domain::dm2rho(this->dmat.dm->get_DMR_vector(), PARAM.inp.nspin, &this->chr);
258-
ModuleBase::timer::end("WFN_Extrap", "rebuild_density");
259-
initialized_by_wfc_extrap = true;
260-
261-
GlobalV::ofs_running << " WFN extrapolation: use_prev_wf from ionic step "
262-
<< wfc_result.snapshot_istep
263-
<< ", active bands = " << wfc_result.nactive_bands
264-
<< ", max |C^T S C - I| = "
265-
<< wfc_result.max_orthonormality_deviation << std::endl;
266-
}
267-
else
268-
{
269-
std::ostringstream oss;
270-
oss << std::scientific << std::setprecision(16);
271-
oss << "WFN extrapolation failed with status: "
272-
<< ModuleExtrap::to_string(wfc_result.status) << "\n\n"
273-
<< " snapshot_istep=" << wfc_result.snapshot_istep << "\n"
274-
<< " failed_state=" << wfc_result.failed_state << "\n"
275-
<< " failed_pivot_index=" << wfc_result.failed_pivot_index << "\n"
276-
<< " failed_pivot=" << wfc_result.failed_pivot << "\n"
277-
<< " nstate=" << wfc_result.nstate << "\n"
278-
<< " nbands=" << wfc_result.nbands << "\n"
279-
<< " nbasis=" << wfc_result.nbasis << "\n"
280-
<< " min_metric_diag=" << wfc_result.min_metric_diag << "\n"
281-
<< " max_metric_diag=" << wfc_result.max_metric_diag << "\n"
282-
<< " max_metric_abs=" << wfc_result.max_metric_abs << "\n"
283-
<< " max_metric_asymmetry=" << wfc_result.max_metric_asymmetry << "\n"
284-
<< " max_orthonormality_deviation="
285-
<< wfc_result.max_orthonormality_deviation << "\n";
286-
const std::string message = oss.str();
287-
ModuleBase::WARNING_QUIT("ESolver_KS_LCAO::before_scf", message);
288-
}
289-
}
290-
}
291-
else
292-
{
293-
if (this->wf_history_lcao_ != nullptr)
294-
{
295-
ModuleBase::WARNING_QUIT("ESolver_KS_LCAO::before_scf",
296-
"WFN extrapolation is currently supported only for the real Gamma-only NAO path.");
297-
}
214+
initialized_by_wfc_extrap = this->wf_history_lcao_->initialize_gamma_density(
215+
*hamilt_lcao,
216+
this->pv,
217+
*(this->psi),
218+
this->pelec->wg,
219+
*(this->dmat.dm),
220+
this->chr,
221+
PARAM.inp.nspin,
222+
PARAM.inp.ks_solver);
298223
}
299224

300225
if (!initialized_by_wfc_extrap)

source/source_lcao/module_extrap/wf_history_lcao.cpp

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,48 @@
11
#include "source_lcao/module_extrap/wf_history_lcao.h"
22

33
#include "source_lcao/module_extrap/wf_orthonormalize_lcao.h"
4+
#include "source_base/global_function.h"
5+
#include "source_base/global_variable.h"
46
#include "source_base/timer.h"
7+
#include "source_base/tool_quit.h"
8+
#include "source_estate/module_dm/cal_dm_psi.h"
9+
#include "source_lcao/hamilt_lcao.h"
10+
#include "source_lcao/module_operator_lcao/operator_lcao.h"
11+
#include "source_lcao/rho_tau_lcao.h"
512

613
#include <algorithm>
714
#include <complex>
8-
#include <type_traits>
15+
#include <iomanip>
16+
#include <sstream>
917

1018
namespace ModuleExtrap
1119
{
1220

21+
namespace
22+
{
23+
24+
std::string wfc_extrapolation_failure_message(const WfExtrapApplyResult& result)
25+
{
26+
std::ostringstream oss;
27+
oss << std::scientific << std::setprecision(16);
28+
oss << "WFN extrapolation failed with status: " << to_string(result.status) << "\n\n"
29+
<< " snapshot_istep=" << result.snapshot_istep << "\n"
30+
<< " failed_state=" << result.failed_state << "\n"
31+
<< " failed_pivot_index=" << result.failed_pivot_index << "\n"
32+
<< " failed_pivot=" << result.failed_pivot << "\n"
33+
<< " nstate=" << result.nstate << "\n"
34+
<< " nbands=" << result.nbands << "\n"
35+
<< " nbasis=" << result.nbasis << "\n"
36+
<< " min_metric_diag=" << result.min_metric_diag << "\n"
37+
<< " max_metric_diag=" << result.max_metric_diag << "\n"
38+
<< " max_metric_abs=" << result.max_metric_abs << "\n"
39+
<< " max_metric_asymmetry=" << result.max_metric_asymmetry << "\n"
40+
<< " max_orthonormality_deviation=" << result.max_orthonormality_deviation << "\n";
41+
return oss.str();
42+
}
43+
44+
} // namespace
45+
1346
template <typename TK>
1447
WfHistoryLCAO<TK>::WfHistoryLCAO(const WfcExtrapMethod method, const std::size_t max_depth)
1548
: method_(method), max_depth_(std::max<std::size_t>(max_depth, 1))
@@ -196,6 +229,71 @@ WfExtrapApplyResult WfHistoryLCAO<double>::try_use_prev_wf_gamma(const double* c
196229
return result;
197230
}
198231

232+
template <typename TK>
233+
bool WfHistoryLCAO<TK>::initialize_gamma_density(hamilt::Hamilt<TK>&,
234+
const Parallel_Orbitals&,
235+
psi::Psi<TK>&,
236+
const ModuleBase::matrix&,
237+
elecstate::DensityMatrix<TK, double>&,
238+
Charge&,
239+
const int,
240+
const std::string&)
241+
{
242+
ModuleBase::WARNING_QUIT("WfHistoryLCAO::initialize_gamma_density",
243+
"WFN extrapolation is currently supported only for the real Gamma-only NAO path.");
244+
}
245+
246+
template <>
247+
bool WfHistoryLCAO<double>::initialize_gamma_density(hamilt::Hamilt<double>& hamiltonian,
248+
const Parallel_Orbitals& pv,
249+
psi::Psi<double>& psi,
250+
const ModuleBase::matrix& wg_now,
251+
elecstate::DensityMatrix<double, double>& dmat,
252+
Charge& charge,
253+
const int nspin,
254+
const std::string& ks_solver)
255+
{
256+
auto* hamilt_lcao = dynamic_cast<hamilt::HamiltLCAO<double, double>*>(&hamiltonian);
257+
if (hamilt_lcao == nullptr)
258+
{
259+
ModuleBase::WARNING_QUIT("WfHistoryLCAO::initialize_gamma_density",
260+
"Failed to access the Gamma-only LCAO Hamiltonian for WFN extrapolation.");
261+
}
262+
263+
auto* lcao_op = dynamic_cast<hamilt::OperatorLCAO<double, double>*>(hamilt_lcao->getOperator());
264+
if (lcao_op == nullptr)
265+
{
266+
ModuleBase::WARNING_QUIT("WfHistoryLCAO::initialize_gamma_density",
267+
"Failed to access the LCAO operator chain for WFN extrapolation.");
268+
}
269+
270+
ModuleBase::timer::start("WFN_Extrap", "prepare_overlap");
271+
lcao_op->contributeHR();
272+
const int sk_layout = ModuleBase::GlobalFunc::IS_COLUMN_MAJOR_KS_SOLVER(ks_solver) ? 1 : 0;
273+
hamilt_lcao->updateSk(0, sk_layout);
274+
ModuleBase::timer::end("WFN_Extrap", "prepare_overlap");
275+
276+
ModuleBase::timer::start("WFN_Extrap", "apply");
277+
const WfExtrapApplyResult result = this->try_use_prev_wf_gamma(hamilt_lcao->getSk(), pv, psi, wg_now);
278+
ModuleBase::timer::end("WFN_Extrap", "apply");
279+
if (!result.ok())
280+
{
281+
ModuleBase::WARNING_QUIT("WfHistoryLCAO::initialize_gamma_density",
282+
wfc_extrapolation_failure_message(result));
283+
}
284+
285+
ModuleBase::timer::start("WFN_Extrap", "rebuild_density");
286+
elecstate::cal_dm_psi(dmat.get_paraV_pointer(), wg_now, psi, dmat);
287+
dmat.cal_DMR();
288+
LCAO_domain::dm2rho(dmat.get_DMR_vector(), nspin, &charge);
289+
ModuleBase::timer::end("WFN_Extrap", "rebuild_density");
290+
291+
GlobalV::ofs_running << " WFN extrapolation: use_prev_wf from ionic step " << result.snapshot_istep
292+
<< ", active bands = " << result.nactive_bands
293+
<< ", max |C^T S C - I| = " << result.max_orthonormality_deviation << std::endl;
294+
return true;
295+
}
296+
199297
template <typename TK>
200298
void WfHistoryLCAO<TK>::prune_history()
201299
{

source/source_lcao/module_extrap/wf_history_lcao.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,19 @@
44
#include "source_lcao/module_extrap/wf_extrap_method.h"
55
#include "source_lcao/module_extrap/wf_snapshot_lcao.h"
66
#include "source_basis/module_ao/parallel_orbitals.h"
7+
#include "source_hamilt/hamilt.h"
78

89
#include <cstddef>
910
#include <deque>
11+
#include <string>
12+
13+
namespace elecstate
14+
{
15+
template <typename TK, typename TR>
16+
class DensityMatrix;
17+
}
18+
19+
class Charge;
1020

1121
namespace ModuleExtrap
1222
{
@@ -79,6 +89,23 @@ class WfHistoryLCAO
7989
double pivot_threshold = 1.0e-14,
8090
double check_tolerance = 1.0e-8);
8191

92+
/**
93+
* Initialize the Gamma-only charge density from the latest WFN snapshot.
94+
*
95+
* The real Gamma-only implementation prepares the current overlap, restores
96+
* and reorthonormalizes the previous WFN, and rebuilds DMK, DMR, and rho.
97+
* Unsupported paths terminate with a clear diagnostic rather than silently
98+
* falling back to charge-density extrapolation.
99+
*/
100+
bool initialize_gamma_density(hamilt::Hamilt<TK>& hamiltonian,
101+
const Parallel_Orbitals& pv,
102+
psi::Psi<TK>& psi,
103+
const ModuleBase::matrix& wg_now,
104+
elecstate::DensityMatrix<TK, double>& dmat,
105+
Charge& charge,
106+
int nspin,
107+
const std::string& ks_solver);
108+
82109
private:
83110
void prune_history();
84111

0 commit comments

Comments
 (0)