Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/advanced/input_files/input-main.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
- [cell\_factor](#cell_factor)
- [dm\_to\_rho](#dm_to_rho)
- [chg\_extrap](#chg_extrap)
- [wfc\_extrap](#wfc_extrap)
- [nb2d](#nb2d)
- [cal\_symm\_repr](#cal_symm_repr)
- [Input files](#input-files)
Expand Down Expand Up @@ -850,6 +851,21 @@
- **Description**: Charge extrapolation method for MD and relaxation calculations.
- **Default**: default

### wfc_extrap

- **Type**: String
- **Description**: Wavefunction extrapolation method for LCAO calculations.

- none: Disable wavefunction-based extrapolation and use chg_extrap instead.
- use_prev_wf: Restore the previous converged ionic-step wavefunctions,
reorthonormalize their occupied subspace in the current AO metric, and rebuild rho.

The first ionic step uses the normal init_wfc/init_chg initialization because no
history exists yet. From the second ionic step onward, the selected WFN method
must succeed; ABACUS does not silently fall back to charge-density extrapolation.
This option is currently limited to Gamma-only LCAO calculations.
- **Default**: none

### nb2d

- **Type**: Integer
Expand Down
17 changes: 17 additions & 0 deletions docs/parameters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,23 @@ parameters:
default_value: default
unit: ""
availability: ""
- name: wfc_extrap
category: System variables
type: String
description: |
Wavefunction extrapolation method for LCAO calculations.

* none: Disable wavefunction-based extrapolation and use chg_extrap instead.
* use_prev_wf: Restore the previous converged ionic-step wavefunctions,
reorthonormalize their occupied subspace in the current AO metric, and rebuild rho.

The first ionic step uses the normal init_wfc/init_chg initialization because no
history exists yet. From the second ionic step onward, the selected WFN method
must succeed; ABACUS does not silently fall back to charge-density extrapolation.
This option is currently limited to Gamma-only LCAO calculations.
default_value: none
unit: ""
availability: ""
- name: ecutwfc
category: Plane wave related variables
type: Real
Expand Down
2 changes: 2 additions & 0 deletions source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,8 @@ if(ENABLE_LCAO)
${ABACUS_BIN_NAME}
PRIVATE
hamilt_lcao
operator_ks_lcao
lcao_extrap
tddft
orb
gint
Expand Down
17 changes: 13 additions & 4 deletions source/source_esolver/esolver_fp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ void ESolver_FP::before_all_runners(BaseCell& basecell, const Input_para& inp)
this->sf.set(this->pw_rhod, inp.nbspline);

//! 4) init charge extrapolation
this->CE.Init_CE(inp.nspin, ucell.nat, this->pw_rhod->nrxx, inp.chg_extrap);
this->use_wfc_extrapolation_ = inp.wfc_extrap != "none";
this->CE.Init_CE(inp.nspin, ucell.nat, this->pw_rhod->nrxx,
this->use_wfc_extrapolation_ ? "none" : inp.chg_extrap);

//! 5) symmetry analysis should be performed every time the cell is changed
if (ModuleSymmetry::Symmetry::symm_flag == 1)
Expand Down Expand Up @@ -180,9 +182,16 @@ void ESolver_FP::before_scf(UnitCell& ucell, const int istep)
// charge extrapolation
if (ucell.ionic_position_updated)
{
this->CE.update_all_dis(ucell);
this->CE.extrapolate_charge(&this->Pgrid, ucell, &this->chr, &this->sf,
GlobalV::ofs_running, GlobalV::ofs_warning);
if (this->use_wfc_extrapolation_)
{
this->sf.setup(&ucell, this->Pgrid, this->pw_rhod);
}
else
{
this->CE.update_all_dis(ucell);
this->CE.extrapolate_charge(&this->Pgrid, ucell, &this->chr, &this->sf,
GlobalV::ofs_running, GlobalV::ofs_warning);
}
}

//! Evaluate the vdW correction once for this ionic configuration.
Expand Down
1 change: 1 addition & 0 deletions source/source_esolver/esolver_fp.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ class ESolver_FP : public ESolver

//! charge extrapolation method
Charge_Extra CE;
bool use_wfc_extrapolation_ = false;

//! solvent model
surchem solvent;
Expand Down
22 changes: 17 additions & 5 deletions source/source_esolver/esolver_ks_lcao.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "esolver_ks_lcao.h"
#include "source_base/global_function.h"
#include "source_base/module_external/blacs_connector.h"
#include "source_cell/module_neighbor/sltk_atom_arrange.h"
#include "source_estate/elecstate_tools.h"
Expand Down Expand Up @@ -27,6 +28,7 @@
#include "source_lcao/LCAO_set.h" // mohan add 20251111
#include "source_psi/setup_psi.h" // use Setup_Psi for deallocate_psi


namespace ModuleESolver
{

Expand Down Expand Up @@ -199,12 +201,17 @@ void ESolver_KS_LCAO<TK, TR>::before_scf(UnitCell& ucell, const int istep)
this->chr, PARAM.inp.ks_solver);
}
}
else if(PARAM.inp.esolver_type!="tddft")//if not, use the DMR calculated from last step
else if(PARAM.inp.esolver_type!="tddft")//initialize DMR from WFN history if required
{
// 13.1.2) two cases are considered:
// 1. DMK in DensityMatrix is not empty (istep > 0), then DMR is initialized by DMK
// 2. DMK in DensityMatrix is empty (istep == 0), then DMR is initialized by zeros
this->dmat.dm->cal_DMR();
if (this->use_wfc_extrapolation_)
{
this->wf_history_lcao_.initialize_gamma_density(
*hamilt_lcao, this->pv, *(this->psi), this->pelec->wg, *(this->dmat.dm), this->chr);
}
else
{
this->dmat.dm->cal_DMR();
}
}
// 13.2) init_scf, should be before_scf? mohan add 2025-03-10
elecstate::init_scf(ucell, this->Pgrid, this->sf.strucFac, this->locpp.numeric,
Expand Down Expand Up @@ -570,6 +577,11 @@ void ESolver_KS_LCAO<TK, TR>::after_scf(UnitCell& ucell, const int istep, const
this->rdmft_solver, this->deepks, this->exx_nao,
this->conv_esolver, this->scf_nmax_flag, istep);

if (conv_esolver && this->psi != nullptr && this->use_wfc_extrapolation_)
{
this->wf_history_lcao_.update_after_scf(istep, *(this->psi), this->pelec->wg);
}

//! 3) Clean up RA, which is used to serach for adjacent atoms
if (!PARAM.inp.cal_force && !PARAM.inp.cal_stress)
{
Expand Down
3 changes: 3 additions & 0 deletions source/source_esolver/esolver_ks_lcao.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "source_lcao/setup_exx.h" // for exx, mohan add 20251008
#include "source_lcao/module_rdmft/rdmft.h" // rdmft
#include "source_lcao/setup_dm.h" // mohan add 2025-10-30
#include "source_lcao/module_extrap/wf_history_lcao.h"

#include <memory>

Expand Down Expand Up @@ -81,6 +82,8 @@ class ESolver_KS_LCAO : public ESolver_KS
//! Add density matrix class, mohan add 2025-10-30
LCAO_domain::Setup_DM<TK> dmat;

ModuleExtrap::WfHistoryLCAO<TK> wf_history_lcao_;


// For deepks method, mohan add 2025-10-08
Setup_DeePKS<TK> deepks;
Expand Down
1 change: 1 addition & 0 deletions source/source_io/module_parameter/input_parameter.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct Input_para
std::string init_chg = "atomic"; ///< "file","atomic"
bool dm_to_rho = false; ///< read density matrix from npz format and calculate charge density
std::string chg_extrap = "default"; ///< xiaohui modify 2015-02-01
std::string wfc_extrap = "none"; ///< wavefunction extrapolation method for LCAO calculations
bool init_vel = false; ///< read velocity from STRU or not liuyu 2021-07-14

std::string input_file = "INPUT"; ///< input file name
Expand Down
44 changes: 44 additions & 0 deletions source/source_io/module_parameter/read_input_item_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,50 @@ Available options are:
};
this->add_item(item);
}
{
Input_Item item("wfc_extrap");
item.annotation = "none; use_prev_wf";
item.category = "System variables";
item.type = "String";
item.description = R"(Wavefunction extrapolation method for LCAO calculations.

* none: Disable wavefunction-based extrapolation and use chg_extrap instead.
* use_prev_wf: Restore the previous converged ionic-step wavefunctions,
reorthonormalize their occupied subspace in the current AO metric, and rebuild rho.

The first ionic step uses the normal init_wfc/init_chg initialization because no
history exists yet. From the second ionic step onward, the selected WFN method
must succeed; ABACUS does not silently fall back to charge-density extrapolation.
This option is currently limited to Gamma-only LCAO calculations.)";
item.default_value = "none";
read_sync_string(input.wfc_extrap);
item.check_value = [](const Input_Item& item, const Parameter& para) {
if (para.input.wfc_extrap != "none" && para.input.wfc_extrap != "use_prev_wf")
{
ModuleBase::WARNING_QUIT("ReadInput", "wfc_extrap should be none or use_prev_wf");
}
if (para.input.wfc_extrap == "use_prev_wf")
{
if (para.input.basis_type != "lcao")
{
ModuleBase::WARNING_QUIT("ReadInput", "WFN-based extrapolation is available only for LCAO");
}
if (!para.input.gamma_only)
{
ModuleBase::WARNING_QUIT("ReadInput", "WFN-based extrapolation is not implemented for k-points");
}
if (para.input.esolver_type == "tddft")
{
ModuleBase::WARNING_QUIT("ReadInput", "WFN-based extrapolation is not implemented for tddft");
}
if (para.input.nspin == 4)
{
ModuleBase::WARNING_QUIT("ReadInput", "WFN-based extrapolation is not implemented for nspin = 4");
}
}
};
this->add_item(item);
}
{
Input_Item item("ecutwfc");
item.annotation = "energy cutoff for wave functions";
Expand Down
1 change: 1 addition & 0 deletions source/source_io/test/read_input_ptest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ TEST_F(InputParaTest, ParaRead)
EXPECT_EQ(param.inp.mem_saver, 0);
EXPECT_EQ(param.inp.init_chg, "atomic");
EXPECT_EQ(param.inp.chg_extrap, "atomic");
EXPECT_EQ(param.inp.wfc_extrap, "use_prev_wf");
EXPECT_EQ(param.inp.out_freq_elec, 50);
EXPECT_EQ(param.inp.out_freq_ion, 0);
EXPECT_EQ(param.inp.out_freq_td, 0);
Expand Down
1 change: 1 addition & 0 deletions source/source_io/test/support/INPUT
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ scf_thr_type 2 #type of the criterion of scf_thr, 1: reci drho
init_wfc atomic #start wave functions are from 'atomic', 'atomic+random', 'random' or 'file'
init_chg atomic #start charge is from 'atomic' or file
chg_extrap atomic #atomic; first-order; second-order; dm:coefficients of SIA
wfc_extrap use_prev_wf #Gamma-only LCAO wavefunction initialization
out_chg 0 #>0 output charge density for selected electron steps
out_pot 2 #output realspace potential
out_wfc_pw 0 #output wave functions
Expand Down
37 changes: 7 additions & 30 deletions source/source_lcao/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,32 +5,9 @@ add_subdirectory(module_deltaspin)

if(ENABLE_LCAO)
add_subdirectory(module_operator_lcao)
list(APPEND objects
add_subdirectory(module_extrap)
set(hamilt_lcao_sources
hamilt_lcao.cpp
module_operator_lcao/operator_lcao.cpp
module_operator_lcao/veff_lcao.cpp
module_operator_lcao/veff_dh.cpp
module_operator_lcao/meta_lcao.cpp
module_operator_lcao/op_dftu_lcao.cpp
module_operator_lcao/deepks_lcao.cpp
module_operator_lcao/op_exx_lcao.cpp
module_operator_lcao/overlap.cpp
module_operator_lcao/overlap_fs.cpp
module_operator_lcao/ekinetic.cpp
module_operator_lcao/ekinetic_fs.cpp
module_operator_lcao/ekinetic_dh.cpp
module_operator_lcao/nonlocal.cpp
module_operator_lcao/nonlocal_dh.cpp
module_operator_lcao/nonlocal_fs.cpp
module_operator_lcao/td_ekinetic_lcao.cpp
module_operator_lcao/td_nonlocal_lcao.cpp
module_operator_lcao/td_pot_hybrid.cpp
module_operator_lcao/td_pot_hybrid_fs.cpp
module_operator_lcao/dspin_lcao.cpp
module_operator_lcao/dspin_fs.cpp
module_operator_lcao/dftu_lcao.cpp
module_operator_lcao/dftu_fs.cpp
module_operator_lcao/operator_fs_utils.cpp
dftu_lcao.cpp
pulay_fs_center2.cpp
FORCE_STRESS.cpp
Expand All @@ -44,9 +21,9 @@ if(ENABLE_LCAO)
spar_st.cpp
spar_u.cpp
LCAO_set.cpp
LCAO_set_fs.cpp
LCAO_set_st.cpp
LCAO_nl_mu.cpp
LCAO_set_fs.cpp
LCAO_set_st.cpp
LCAO_nl_mu.cpp
LCAO_set_zero.cpp
LCAO_allocate.cpp
LCAO_set_mat2d.cpp
Expand All @@ -56,7 +33,7 @@ if(ENABLE_LCAO)
setup_deepks.cpp
setup_dm.cpp
rho_tau_lcao.cpp
record_adj.cpp
record_adj.cpp
center2_orb.cpp
center2_orb-orb11.cpp
center2_orb-orb21.cpp
Expand All @@ -67,7 +44,7 @@ if(ENABLE_LCAO)
add_library(
hamilt_lcao
OBJECT
${objects}
${hamilt_lcao_sources}
)

if(ENABLE_COVERAGE)
Expand Down
15 changes: 15 additions & 0 deletions source/source_lcao/module_extrap/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
add_library(
lcao_extrap
OBJECT
wf_history_lcao.cpp
wf_orthonormalize_lcao.cpp
wf_density_init_lcao.cpp
)

if(BUILD_TESTING)
add_subdirectory(test)
endif()

if(ENABLE_COVERAGE)
add_coverage(lcao_extrap)
endif()
9 changes: 9 additions & 0 deletions source/source_lcao/module_extrap/test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
AddTest(
TARGET MODULE_LCAO_extrap_test
LIBS parameter ${math_libs} psi base device
SOURCES
wf_extrap_test.cpp
../wf_history_lcao.cpp
../wf_orthonormalize_lcao.cpp
${ABACUS_SOURCE_DIR}/source_basis/module_ao/parallel_orbitals.cpp
)
Loading
Loading