Skip to content

Commit 923b697

Browse files
authored
Fix: refactor of ESolver_KS_PW::init_after_vc with new psi initializer (#3031)
* add re-initialization after vcrelax * append annotations in esolver_ks_pw * correct esolver_ks_pw.cpp oops, I deleted two lines by mistake, sorry! * improve line coverage of psi_initializer * remove newly added unittests, will re-design later * refactor psi_initializer, add unit tests, add integrated tests, update documents * update docs * eliminate warning about forgetting to add override keyword * fix compile bug from rename pseudo_nc to pseudo * mock the full UnitCell, undefined reference will not see anymore * delete redefinition of parameter and functions * Update input-main.md according to suggestion from Tianqi
1 parent 6c2f68b commit 923b697

37 files changed

+1549
-599
lines changed

docs/advanced/input_files/input-main.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
- [kpar](#kpar)
1313
- [bndpar](#bndpar)
1414
- [latname](#latname)
15+
- [psi\_initializer](#psi_initializer)
1516
- [init\_wfc](#init_wfc)
1617
- [init\_chg](#init_chg)
1718
- [init\_vel](#init_vel)
@@ -463,16 +464,32 @@ These variables are used to control general system parameters.
463464
- triclinic: triclinic (14)
464465
- **Default**: none
465466

467+
### psi_initializer
468+
469+
- **Type**: Integer
470+
- **Description**: enable the experimental feature psi_initializer, to support use numerical atomic orbitals initialize wavefunction (`basis_type pw` case).
471+
472+
NOTE: this feature is not well-implemented for `nspin 4` case (closed presently), and cannot use with `calculation nscf`/`esolver_type sdft` cases.
473+
Available options are:
474+
- 0: disable psi_initializer
475+
- 1: enable psi_initializer
476+
- **Default**: 0
477+
466478
### init_wfc
467479

468480
- **Type**: String
469481
- **Description**: Only useful for plane wave basis only now. It is the name of the starting wave functions. In the future. we should also make this variable available for localized orbitals set.
470482

471483
Available options are:
484+
472485
- atomic: from atomic pseudo wave functions. If they are not enough, other wave functions are initialized with random numbers.
473486
- atomic+random: add small random numbers on atomic pseudo-wavefunctions
474487
- file: from file
475488
- random: random numbers
489+
490+
with `psi_initializer 1`, two more options are supported:
491+
- nao: from numerical atomic orbitals. If they are not enough, other wave functions are initialized with random numbers.
492+
- nao+random: add small random numbers on numerical atomic orbitals
476493
- **Default**: atomic
477494

478495
### init_chg

source/module_esolver/esolver_ks_pw.cpp

Lines changed: 117 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -211,43 +211,7 @@ void ESolver_KS_PW<T, Device>::Init(Input& inp, UnitCell& ucell)
211211
}
212212
if (GlobalV::psi_initializer)
213213
{
214-
if(GlobalV::init_wfc == "atomic")
215-
{
216-
this->psi_init = new psi_initializer_atomic(&(this->sf), this->pw_wfc);
217-
// there are things only need to calculate once
218-
//this->psi_init->set_pseudopot_files(GlobalC::ucell.pseudo_fn);
219-
// not parallelized function, but we have GlobalC now,
220-
// in the future once GlobalC is removed, we will parallelize this function
221-
this->psi_init->cal_ovlp_pswfcjlq();
222-
}
223-
else if(GlobalV::init_wfc == "random")
224-
{
225-
this->psi_init = new psi_initializer_random(&(this->sf), this->pw_wfc);
226-
}
227-
else if(GlobalV::init_wfc == "nao")
228-
{
229-
this->psi_init = new psi_initializer_nao(&(this->sf), this->pw_wfc);
230-
// there are things only need to calculate once
231-
this->psi_init->set_orbital_files(GlobalC::ucell.orbital_fn);
232-
this->psi_init->cal_ovlp_flzjlq();
233-
}
234-
else if(GlobalV::init_wfc == "atomic+random")
235-
{
236-
this->psi_init = new psi_initializer_atomic_random(&(this->sf), this->pw_wfc);
237-
// there are things only need to calculate once
238-
//this->psi_init->set_pseudopot_files(GlobalC::ucell.pseudo_fn);
239-
// not parallelized function, but we have GlobalC now,
240-
// in the future once GlobalC is removed, we will parallelize this function
241-
this->psi_init->cal_ovlp_pswfcjlq();
242-
}
243-
else if(GlobalV::init_wfc == "nao+random")
244-
{
245-
this->psi_init = new psi_initializer_nao_random(&(this->sf), this->pw_wfc);
246-
// there are things only need to calculate once
247-
this->psi_init->set_orbital_files(GlobalC::ucell.orbital_fn);
248-
this->psi_init->cal_ovlp_flzjlq();
249-
}
250-
else ModuleBase::WARNING_QUIT("ESolver_KS_LCAO::init", "for new psi initializer, init_wfc type not supported");
214+
this->allocate_psi_init();
251215
}
252216
// temporary
253217
this->Init_GlobalC(inp, ucell);
@@ -316,8 +280,23 @@ void ESolver_KS_PW<T, Device>::init_after_vc(Input& inp, UnitCell& ucell)
316280
this->pw_wfc->nz);
317281
this->pw_wfc->initparameters(false, INPUT.ecutwfc, this->kv.nks, this->kv.kvec_d.data());
318282
this->pw_wfc->collect_local_pw(inp.erf_ecut, inp.erf_height, inp.erf_sigma);
319-
this->wf.init_after_vc(this->kv.nks);
320-
this->wf.init_at_1(&this->sf);
283+
if(GlobalV::psi_initializer)
284+
{
285+
if(GlobalV::init_wfc.substr(0, 3) == "nao")
286+
{
287+
this->psi_init->cal_ovlp_flzjlq(); // for nao, we recalculate the overlap matrix between flz and jlq
288+
}
289+
else if(GlobalV::init_wfc.substr(0, 6) == "atomic")
290+
{
291+
this->psi_init->cal_ovlp_pswfcjlq(); // for atomic, we recalculate the overlap matrix between pswfc and jlq
292+
}
293+
// for psig is not read-only, its value will be overwritten in initialize_psi(), dont need delete and reallocate
294+
}
295+
else
296+
{
297+
this->wf.init_after_vc(this->kv.nks); // reallocate wanf2, the planewave expansion of lcao
298+
this->wf.init_at_1(&this->sf); // re-calculate tab_at, the overlap matrix between atomic pswfc and jlq
299+
}
321300
}
322301

323302
#ifdef USE_PAW
@@ -401,7 +380,22 @@ void ESolver_KS_PW<T, Device>::beforescf(int istep)
401380
*/
402381
if(GlobalV::psi_initializer)
403382
{
404-
this->initialize_psi();
383+
/*
384+
beforescf function will be called everytime before scf. However, once atomic coordinates changed,
385+
structure factor will change, therefore all atomwise properties will change. So we need to reinitialize
386+
psi every time before scf. But for random wavefunction, we dont, because random wavefunction is not
387+
related to atomic coordinates.
388+
389+
What the old strategy does is only to initialize for once...
390+
*/
391+
if(GlobalV::init_wfc == "random")
392+
{
393+
if(istep == 0) this->initialize_psi();
394+
}
395+
else
396+
{
397+
this->initialize_psi();
398+
}
405399
}
406400
}
407401

@@ -465,6 +459,89 @@ void ESolver_KS_PW<T, Device>::eachiterinit(const int istep, const int iter)
465459
}
466460
}
467461

462+
template <typename T, typename Device>
463+
void ESolver_KS_PW<T, Device>::allocate_psi_init()
464+
{
465+
if(this->psi_init != nullptr)
466+
{
467+
delete this->psi_init;
468+
this->psi_init = nullptr;
469+
}
470+
if((GlobalV::init_wfc.substr(0, 6) == "atomic")&&(GlobalC::ucell.natomwfc == 0))
471+
{
472+
GlobalV::init_wfc = "random";
473+
std::cout << " WARNING: atomic pseudowavefunction is required but there is NOT ANY, set to random automatically." << std::endl;
474+
#ifdef __MPI
475+
this->psi_init = new psi_initializer_random(&(this->sf), this->pw_wfc, &(GlobalC::ucell), &(GlobalC::Pkpoints), INPUT.pw_seed);
476+
#else
477+
this->psi_init = new psi_initializer_random(&(this->sf), this->pw_wfc, &(GlobalC::ucell), INPUT.pw_seed);
478+
#endif
479+
this->psi_init->initialize_only_once();
480+
}
481+
else
482+
{
483+
if(GlobalV::init_wfc == "atomic")
484+
{
485+
#ifdef __MPI
486+
this->psi_init = new psi_initializer_atomic(&(this->sf), this->pw_wfc, &(GlobalC::ucell), &(GlobalC::Pkpoints), INPUT.pw_seed);
487+
#else
488+
this->psi_init = new psi_initializer_atomic(&(this->sf), this->pw_wfc, &(GlobalC::ucell), INPUT.pw_seed);
489+
#endif
490+
this->psi_init->initialize_only_once(&(GlobalC::ppcell));
491+
this->psi_init->cal_ovlp_pswfcjlq();
492+
}
493+
else if(GlobalV::init_wfc == "random")
494+
{
495+
#ifdef __MPI
496+
this->psi_init = new psi_initializer_random(&(this->sf), this->pw_wfc, &(GlobalC::ucell), &(GlobalC::Pkpoints), INPUT.pw_seed);
497+
#else
498+
this->psi_init = new psi_initializer_random(&(this->sf), this->pw_wfc, &(GlobalC::ucell), INPUT.pw_seed);
499+
#endif
500+
this->psi_init->initialize_only_once();
501+
}
502+
else if(GlobalV::init_wfc == "nao")
503+
{
504+
if(GlobalV::NSPIN == 4)
505+
{
506+
ModuleBase::WARNING_QUIT("ESolver_KS_PW::allocate_psi_init", "for nao, soc this not safely implemented yet. To use it now, comment out this line.");
507+
}
508+
#ifdef __MPI
509+
this->psi_init = new psi_initializer_nao(&(this->sf), this->pw_wfc, &(GlobalC::ucell), &(GlobalC::Pkpoints), INPUT.pw_seed);
510+
#else
511+
this->psi_init = new psi_initializer_nao(&(this->sf), this->pw_wfc, &(GlobalC::ucell), INPUT.pw_seed);
512+
#endif
513+
this->psi_init->set_orbital_files(GlobalC::ucell.orbital_fn);
514+
this->psi_init->initialize_only_once();
515+
this->psi_init->cal_ovlp_flzjlq();
516+
}
517+
else if(GlobalV::init_wfc == "atomic+random")
518+
{
519+
#ifdef __MPI
520+
this->psi_init = new psi_initializer_atomic_random(&(this->sf), this->pw_wfc, &(GlobalC::ucell), &(GlobalC::Pkpoints), INPUT.pw_seed);
521+
#else
522+
this->psi_init = new psi_initializer_atomic_random(&(this->sf), this->pw_wfc, &(GlobalC::ucell), INPUT.pw_seed);
523+
#endif
524+
this->psi_init->initialize_only_once(&(GlobalC::ppcell));
525+
this->psi_init->cal_ovlp_pswfcjlq();
526+
}
527+
else if(GlobalV::init_wfc == "nao+random")
528+
{
529+
if(GlobalV::NSPIN == 4)
530+
{
531+
ModuleBase::WARNING_QUIT("ESolver_KS_PW::allocate_psi_init", "for nao, soc this not safely implemented yet. To use it now, comment out this line.");
532+
}
533+
#ifdef __MPI
534+
this->psi_init = new psi_initializer_nao_random(&(this->sf), this->pw_wfc, &(GlobalC::ucell), &(GlobalC::Pkpoints), INPUT.pw_seed);
535+
#else
536+
this->psi_init = new psi_initializer_nao_random(&(this->sf), this->pw_wfc, &(GlobalC::ucell), INPUT.pw_seed);
537+
#endif
538+
this->psi_init->set_orbital_files(GlobalC::ucell.orbital_fn);
539+
this->psi_init->initialize_only_once();
540+
this->psi_init->cal_ovlp_flzjlq();
541+
}
542+
else ModuleBase::WARNING_QUIT("ESolver_KS_PW::allocate_psi_init", "for new psi initializer, init_wfc type not supported");
543+
}
544+
}
468545
/*
469546
Although ESolver_KS_PW supports template, but in this function it has no relationship with
470547
heterogeneous calculation, so all templates function are specialized to double

source/module_esolver/esolver_ks_pw.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ namespace ModuleESolver
8383
void Init_GlobalC(Input& inp, UnitCell& cell);
8484
//calculate conductivities from j-j correlation function
8585
void calcondw(const int nt,const double dt, const double fwhmin, const double wcut, const double dw_in, double *ct11, double *ct12, double *ct22);
86-
86+
/// @brief allocate psi_init the new psi_initializer
87+
void allocate_psi_init();
88+
/// @brief initialize psi
8789
void initialize_psi();
8890
private:
8991
psi_initializer* psi_init = nullptr;

source/module_psi/CMakeLists.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,4 @@ endif()
2323
if (BUILD_TESTING)
2424
add_subdirectory(kernels/test)
2525
add_subdirectory(test)
26-
27-
add_compile_definitions(PSI_INITIALIZER_TEST)
2826
endif()

0 commit comments

Comments
 (0)