Skip to content

Commit 398915e

Browse files
committed
Refactor: runner() of esolver_ks
1 parent 7da86cd commit 398915e

File tree

7 files changed

+310
-376
lines changed

7 files changed

+310
-376
lines changed

source/module_esolver/esolver_ks.cpp

Lines changed: 176 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,60 @@ void ESolver_KS<T, Device>::hamilt2density(const int istep, const int iter, cons
379379
ModuleBase::timer::tick(this->classname, "hamilt2density");
380380
}
381381

382+
template <typename T, typename Device>
383+
void ESolver_KS<T, Device>::diag(const int istep, const int iter, const double ethr)
384+
{
385+
// 7) use Hamiltonian to obtain charge density
386+
this->hamilt2density(istep, iter, diag_ethr);
387+
388+
// 8) for MPI: STOGROUP? need to rewrite
389+
//<Temporary> It may be changed when more clever parallel algorithm is
390+
// put forward.
391+
// When parallel algorithm for bands are adopted. Density will only be
392+
// treated in the first group.
393+
//(Different ranks should have abtained the same, but small differences
394+
// always exist in practice.)
395+
// Maybe in the future, density and wavefunctions should use different
396+
// parallel algorithms, in which they do not occupy all processors, for
397+
// example wavefunctions uses 20 processors while density uses 10.
398+
if (GlobalV::MY_STOGROUP == 0)
399+
{
400+
// double drho = this->estate.caldr2();
401+
// EState should be used after it is constructed.
402+
403+
drho = p_chgmix->get_drho(pelec->charge, PARAM.inp.nelec);
404+
hsolver_error = 0.0;
405+
if (iter == 1)
406+
{
407+
hsolver_error
408+
= hsolver::cal_hsolve_error(PARAM.inp.basis_type, PARAM.inp.esolver_type, diag_ethr, PARAM.inp.nelec);
409+
410+
// The error of HSolver is larger than drho,
411+
// so a more precise HSolver should be executed.
412+
if (hsolver_error > drho)
413+
{
414+
diag_ethr = hsolver::reset_diag_ethr(GlobalV::ofs_running,
415+
PARAM.inp.basis_type,
416+
PARAM.inp.esolver_type,
417+
PARAM.inp.precision,
418+
hsolver_error,
419+
drho,
420+
diag_ethr,
421+
PARAM.inp.nelec);
422+
423+
this->hamilt2density(istep, iter, diag_ethr);
424+
425+
drho = p_chgmix->get_drho(pelec->charge, PARAM.inp.nelec);
426+
427+
hsolver_error = hsolver::cal_hsolve_error(PARAM.inp.basis_type,
428+
PARAM.inp.esolver_type,
429+
diag_ethr,
430+
PARAM.inp.nelec);
431+
}
432+
}
433+
}
434+
}
435+
382436
//------------------------------------------------------------------------------
383437
//! the 7th function of ESolver_KS: run
384438
//! mohan add 2024-05-11
@@ -418,7 +472,6 @@ void ESolver_KS<T, Device>::runner(const int istep, UnitCell& ucell)
418472

419473
ModuleBase::GlobalFunc::DONE(GlobalV::ofs_running, "INIT SCF");
420474

421-
bool firstscf = true;
422475
this->conv_esolver = false;
423476
this->niter = this->maxniter;
424477

@@ -431,145 +484,7 @@ void ESolver_KS<T, Device>::runner(const int istep, UnitCell& ucell)
431484
// 6) initialization of SCF iterations
432485
this->iter_init(istep, iter);
433486

434-
// 7) use Hamiltonian to obtain charge density
435-
this->hamilt2density(istep, iter, diag_ethr);
436-
437-
// 8) for MPI: STOGROUP? need to rewrite
438-
//<Temporary> It may be changed when more clever parallel algorithm is
439-
// put forward.
440-
// When parallel algorithm for bands are adopted. Density will only be
441-
// treated in the first group.
442-
//(Different ranks should have abtained the same, but small differences
443-
// always exist in practice.)
444-
// Maybe in the future, density and wavefunctions should use different
445-
// parallel algorithms, in which they do not occupy all processors, for
446-
// example wavefunctions uses 20 processors while density uses 10.
447-
if (GlobalV::MY_STOGROUP == 0)
448-
{
449-
// double drho = this->estate.caldr2();
450-
// EState should be used after it is constructed.
451-
452-
drho = p_chgmix->get_drho(pelec->charge, PARAM.inp.nelec);
453-
double hsolver_error = 0.0;
454-
if (firstscf)
455-
{
456-
firstscf = false;
457-
hsolver_error = hsolver::cal_hsolve_error(PARAM.inp.basis_type,
458-
PARAM.inp.esolver_type,
459-
diag_ethr,
460-
PARAM.inp.nelec);
461-
462-
// The error of HSolver is larger than drho,
463-
// so a more precise HSolver should be executed.
464-
if (hsolver_error > drho)
465-
{
466-
diag_ethr = hsolver::reset_diag_ethr(GlobalV::ofs_running,
467-
PARAM.inp.basis_type,
468-
PARAM.inp.esolver_type,
469-
PARAM.inp.precision,
470-
hsolver_error,
471-
drho,
472-
diag_ethr,
473-
PARAM.inp.nelec);
474-
475-
this->hamilt2density(istep, iter, diag_ethr);
476-
477-
drho = p_chgmix->get_drho(pelec->charge, PARAM.inp.nelec);
478-
479-
hsolver_error = hsolver::cal_hsolve_error(PARAM.inp.basis_type,
480-
PARAM.inp.esolver_type,
481-
diag_ethr,
482-
PARAM.inp.nelec);
483-
}
484-
}
485-
// mixing will restart at this->p_chgmix->mixing_restart steps
486-
if (drho <= PARAM.inp.mixing_restart && PARAM.inp.mixing_restart > 0.0
487-
&& this->p_chgmix->mixing_restart_step > iter)
488-
{
489-
this->p_chgmix->mixing_restart_step = iter + 1;
490-
}
491-
492-
if (PARAM.inp.scf_os_stop) // if oscillation is detected, SCF will stop
493-
{
494-
this->oscillate_esolver = this->p_chgmix->if_scf_oscillate(iter, drho, PARAM.inp.scf_os_ndim, PARAM.inp.scf_os_thr);
495-
}
496-
497-
// drho will be 0 at this->p_chgmix->mixing_restart step, which is
498-
// not ground state
499-
bool not_restart_step = !(iter == this->p_chgmix->mixing_restart_step && PARAM.inp.mixing_restart > 0.0);
500-
// SCF will continue if U is not converged for uramping calculation
501-
bool is_U_converged = true;
502-
// to avoid unnecessary dependence on dft+u, refactor is needed
503-
#ifdef __LCAO
504-
if (PARAM.inp.dft_plus_u)
505-
{
506-
is_U_converged = GlobalC::dftu.u_converged();
507-
}
508-
#endif
509-
510-
this->conv_esolver = (drho < this->scf_thr && not_restart_step && is_U_converged);
511-
512-
// add energy threshold for SCF convergence
513-
if (this->scf_ene_thr > 0.0)
514-
{
515-
// calculate energy of output charge density
516-
this->update_pot(istep, iter);
517-
this->pelec->cal_energies(2); // 2 means Kohn-Sham functional
518-
// now, etot_old is the energy of input density, while etot is the energy of output density
519-
this->pelec->f_en.etot_delta = this->pelec->f_en.etot - this->pelec->f_en.etot_old;
520-
// output etot_delta
521-
GlobalV::ofs_running << " DeltaE_womix = " << this->pelec->f_en.etot_delta * ModuleBase::Ry_to_eV << " eV" << std::endl;
522-
if (iter > 1 && this->conv_esolver == 1) // only check when density is converged
523-
{
524-
// update the convergence flag
525-
this->conv_esolver
526-
= (std::abs(this->pelec->f_en.etot_delta * ModuleBase::Ry_to_eV) < this->scf_ene_thr);
527-
}
528-
}
529-
530-
// If drho < hsolver_error in the first iter or drho < scf_thr, we
531-
// do not change rho.
532-
if (drho < hsolver_error || this->conv_esolver)
533-
{
534-
if (drho < hsolver_error)
535-
{
536-
GlobalV::ofs_warning << " drho < hsolver_error, keep "
537-
"charge density unchanged."
538-
<< std::endl;
539-
}
540-
}
541-
else
542-
{
543-
//----------charge mixing---------------
544-
// mixing will restart after this->p_chgmix->mixing_restart
545-
// steps
546-
if (PARAM.inp.mixing_restart > 0 && iter == this->p_chgmix->mixing_restart_step - 1
547-
&& drho <= PARAM.inp.mixing_restart)
548-
{
549-
// do not mix charge density
550-
}
551-
else
552-
{
553-
p_chgmix->mix_rho(pelec->charge); // update chr->rho by mixing
554-
}
555-
if (PARAM.inp.scf_thr_type == 2)
556-
{
557-
pelec->charge->renormalize_rho(); // renormalize rho in R-space would
558-
// induce a error in K-space
559-
}
560-
//----------charge mixing done-----------
561-
}
562-
}
563-
#ifdef __MPI
564-
MPI_Bcast(&drho, 1, MPI_DOUBLE, 0, PARAPW_WORLD);
565-
MPI_Bcast(&this->conv_esolver, 1, MPI_DOUBLE, 0, PARAPW_WORLD);
566-
MPI_Bcast(pelec->charge->rho[0], this->pw_rhod->nrxx, MPI_DOUBLE, 0, PARAPW_WORLD);
567-
#endif
568-
569-
// 9) update potential
570-
// Hamilt should be used after it is constructed.
571-
// this->phamilt->update(conv_esolver);
572-
this->update_pot(istep, iter);
487+
this->diag(istep, iter, diag_ethr);
573488

574489
// 10) finish scf iterations
575490
this->iter_finish(istep, iter);
@@ -635,13 +550,134 @@ void ESolver_KS<T, Device>::iter_init(const int istep, const int iter)
635550
PARAM.inp.nbands,
636551
esolver_KS_ne);
637552
}
553+
554+
// 1) save input rho
555+
this->pelec->charge->save_rho_before_sum_band();
638556
}
639557

640558
template <typename T, typename Device>
641559
void ESolver_KS<T, Device>::iter_finish(const int istep, int& iter)
642560
{
561+
if (PARAM.inp.out_bandgap)
562+
{
563+
if (!PARAM.globalv.two_fermi)
564+
{
565+
this->pelec->cal_bandgap();
566+
}
567+
else
568+
{
569+
this->pelec->cal_bandgap_updw();
570+
}
571+
}
572+
573+
for (int ik = 0; ik < this->kv.get_nks(); ++ik)
574+
{
575+
this->pelec->print_band(ik, PARAM.inp.printe, iter);
576+
}
577+
578+
// compute magnetization, only for LSDA(spin==2)
579+
GlobalC::ucell.magnet.compute_magnetization(this->pelec->charge->nrxx,
580+
this->pelec->charge->nxyz,
581+
this->pelec->charge->rho,
582+
this->pelec->nelec_spin.data());
583+
584+
if (GlobalV::MY_STOGROUP == 0)
585+
{
586+
// mixing will restart at this->p_chgmix->mixing_restart steps
587+
if (drho <= PARAM.inp.mixing_restart && PARAM.inp.mixing_restart > 0.0
588+
&& this->p_chgmix->mixing_restart_step > iter)
589+
{
590+
this->p_chgmix->mixing_restart_step = iter + 1;
591+
}
592+
593+
if (PARAM.inp.scf_os_stop) // if oscillation is detected, SCF will stop
594+
{
595+
this->oscillate_esolver
596+
= this->p_chgmix->if_scf_oscillate(iter, drho, PARAM.inp.scf_os_ndim, PARAM.inp.scf_os_thr);
597+
}
598+
599+
// drho will be 0 at this->p_chgmix->mixing_restart step, which is
600+
// not ground state
601+
bool not_restart_step = !(iter == this->p_chgmix->mixing_restart_step && PARAM.inp.mixing_restart > 0.0);
602+
// SCF will continue if U is not converged for uramping calculation
603+
bool is_U_converged = true;
604+
// to avoid unnecessary dependence on dft+u, refactor is needed
605+
#ifdef __LCAO
606+
if (PARAM.inp.dft_plus_u)
607+
{
608+
is_U_converged = GlobalC::dftu.u_converged();
609+
}
610+
#endif
611+
612+
this->conv_esolver = (drho < this->scf_thr && not_restart_step && is_U_converged);
613+
614+
// add energy threshold for SCF convergence
615+
if (this->scf_ene_thr > 0.0)
616+
{
617+
// calculate energy of output charge density
618+
this->update_pot(istep, iter);
619+
this->pelec->cal_energies(2); // 2 means Kohn-Sham functional
620+
// now, etot_old is the energy of input density, while etot is the energy of output density
621+
this->pelec->f_en.etot_delta = this->pelec->f_en.etot - this->pelec->f_en.etot_old;
622+
// output etot_delta
623+
GlobalV::ofs_running << " DeltaE_womix = " << this->pelec->f_en.etot_delta * ModuleBase::Ry_to_eV << " eV"
624+
<< std::endl;
625+
if (iter > 1 && this->conv_esolver == 1) // only check when density is converged
626+
{
627+
// update the convergence flag
628+
this->conv_esolver
629+
= (std::abs(this->pelec->f_en.etot_delta * ModuleBase::Ry_to_eV) < this->scf_ene_thr);
630+
}
631+
}
632+
633+
// If drho < hsolver_error in the first iter or drho < scf_thr, we
634+
// do not change rho.
635+
if (drho < hsolver_error || this->conv_esolver)
636+
{
637+
if (drho < hsolver_error)
638+
{
639+
GlobalV::ofs_warning << " drho < hsolver_error, keep "
640+
"charge density unchanged."
641+
<< std::endl;
642+
}
643+
}
644+
else
645+
{
646+
//----------charge mixing---------------
647+
// mixing will restart after this->p_chgmix->mixing_restart
648+
// steps
649+
if (PARAM.inp.mixing_restart > 0 && iter == this->p_chgmix->mixing_restart_step - 1
650+
&& drho <= PARAM.inp.mixing_restart)
651+
{
652+
// do not mix charge density
653+
}
654+
else
655+
{
656+
p_chgmix->mix_rho(pelec->charge); // update chr->rho by mixing
657+
}
658+
if (PARAM.inp.scf_thr_type == 2)
659+
{
660+
pelec->charge->renormalize_rho(); // renormalize rho in R-space would
661+
// induce a error in K-space
662+
}
663+
//----------charge mixing done-----------
664+
}
665+
}
666+
667+
#ifdef __MPI
668+
MPI_Bcast(&drho, 1, MPI_DOUBLE, 0, PARAPW_WORLD);
669+
MPI_Bcast(&this->conv_esolver, 1, MPI_DOUBLE, 0, PARAPW_WORLD);
670+
MPI_Bcast(pelec->charge->rho[0], this->pw_rhod->nrxx, MPI_DOUBLE, 0, PARAPW_WORLD);
671+
#endif
672+
673+
// update potential
674+
// Hamilt should be used after it is constructed.
675+
// this->phamilt->update(conv_esolver);
676+
this->update_pot(istep, iter);
677+
643678
// 1 means Harris-Foulkes functional
644679
// 2 means Kohn-Sham functional
680+
this->pelec->cal_energies(1);
645681
this->pelec->cal_energies(2);
646682

647683
if (iter == 1)

source/module_esolver/esolver_ks.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,15 @@ class ESolver_KS : public ESolver_FP
4646
//! Something to do after hamilt2density function in each iter loop.
4747
virtual void iter_finish(const int istep, int& iter);
4848

49-
// calculate electron density from a specific Hamiltonian
49+
// calculate electron density from a specific Hamiltonian with ethr
5050
virtual void hamilt2density(const int istep, const int iter, const double ethr);
5151

5252
// calculate electron states from a specific Hamiltonian
5353
virtual void hamilt2estates(const double ethr) {};
5454

55+
// calculate electron density from a specific Hamiltonian
56+
void diag(const int istep, const int iter, const double ethr);
57+
5558
//! Something to do after SCF iterations when SCF is converged or comes to the max iter step.
5659
virtual void after_scf(const int istep) override;
5760

@@ -82,6 +85,7 @@ class ESolver_KS : public ESolver_FP
8285
double scf_thr; // scf density threshold
8386
double scf_ene_thr; // scf energy threshold
8487
double drho; // the difference between rho_in (before HSolver) and rho_out (After HSolver)
88+
double hsolver_error; // the error of HSolver
8589
int maxniter; // maximum iter steps for scf
8690
int niter; // iter steps actually used in scf
8791
int out_freq_elec; // frequency for output

0 commit comments

Comments
 (0)