From 1e0be3aafa38f1abd89a22e74e8da2f011cc5455 Mon Sep 17 00:00:00 2001 From: weiqingzhou Date: Wed, 1 Nov 2023 16:51:37 +0800 Subject: [PATCH 1/4] improved implementation of kerker preconditioner --- .../module_charge/charge_mixing.cpp | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/source/module_elecstate/module_charge/charge_mixing.cpp b/source/module_elecstate/module_charge/charge_mixing.cpp index 12d8acc4b7..ff92610355 100755 --- a/source/module_elecstate/module_charge/charge_mixing.cpp +++ b/source/module_elecstate/module_charge/charge_mixing.cpp @@ -108,15 +108,9 @@ void Charge_Mixing::auto_set(const double& bandgap_in, const UnitCell& ucell_) } } } - // auto set kerker mixing for trans metal system - if (has_trans_metal) - { - this->mixing_gg0 = 1.5; - } - else - { - this->mixing_gg0 = 0.0; - } + // auto set kerker mixing_gg0 = 1.0 as default + this->mixing_gg0 = 1.0; + GlobalV::ofs_running << " Autoset mixing_gg0 to " << this->mixing_gg0 << std::endl; GlobalV::ofs_running << "-------------------------------------" << std::endl; // auto set for inhomogeneous system @@ -362,7 +356,7 @@ void Charge_Mixing::mix_rho(Charge* chr) void Charge_Mixing::Kerker_screen_recip(std::complex* drhog) { - if (this->mixing_gg0 <= 0.0) + if (this->mixing_gg0 <= 0.0 || this->mixing_beta <= 0.1) return; const double fac = this->mixing_gg0; const double gg0 = std::pow(fac * 0.529177 / GlobalC::ucell.tpiba, 2); @@ -374,7 +368,7 @@ void Charge_Mixing::Kerker_screen_recip(std::complex* drhog) for (int ig = 0; ig < this->rhopw->npw; ++ig) { double gg = this->rhopw->gg[ig]; - double filter_g = std::max(gg / (gg + gg0), 0.1); + double filter_g = std::max(gg / (gg + gg0), 0.1 / this->mixing_beta); drhog[is * this->rhopw->npw + ig] *= filter_g; } } @@ -383,7 +377,7 @@ void Charge_Mixing::Kerker_screen_recip(std::complex* drhog) void Charge_Mixing::Kerker_screen_real(double* drhor) { - if (this->mixing_gg0 <= 0.0) + if (this->mixing_gg0 <= 0.0 || this->mixing_beta <= 0.1) return; std::vector> drhog(this->rhopw->npw * GlobalV::NSPIN); std::vector drhor_filter(this->rhopw->nrxx * GlobalV::NSPIN); @@ -405,7 +399,7 @@ void Charge_Mixing::Kerker_screen_real(double* drhor) for (int ig = 0; ig < this->rhopw->npw; ig++) { double gg = this->rhopw->gg[ig]; - double filter_g = std::max(gg / (gg + gg0), 0.1); + double filter_g = std::max(gg / (gg + gg0), 0.1 / this->mixing_beta); drhog[is * this->rhopw->npw + ig] *= (1 - filter_g); } } From bf442fa546687f934174662e5e09cc1ce29bbc1a Mon Sep 17 00:00:00 2001 From: weiqingzhou Date: Thu, 2 Nov 2023 10:30:26 +0800 Subject: [PATCH 2/4] fix bug in charge_mixing_test --- source/module_elecstate/test/charge_mixing_test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/module_elecstate/test/charge_mixing_test.cpp b/source/module_elecstate/test/charge_mixing_test.cpp index fdde781018..9906c11c6b 100644 --- a/source/module_elecstate/test/charge_mixing_test.cpp +++ b/source/module_elecstate/test/charge_mixing_test.cpp @@ -148,20 +148,20 @@ TEST_F(ChargeMixingTest, AutoSetTest) CMtest.auto_set(0.0, GlobalC::ucell); EXPECT_EQ(CMtest.mixing_beta, 0.2); EXPECT_EQ(CMtest.mixing->mixing_beta, 0.2); - EXPECT_EQ(CMtest.mixing_gg0, 0.0); + EXPECT_EQ(CMtest.mixing_gg0, 1.0); CMtest.need_auto_set(); CMtest.auto_set(1.0, GlobalC::ucell); EXPECT_EQ(CMtest.mixing_beta, 0.7); EXPECT_EQ(CMtest.mixing->mixing_beta, 0.7); - EXPECT_EQ(CMtest.mixing_gg0, 0.0); + EXPECT_EQ(CMtest.mixing_gg0, 1.0); GlobalC::ucell.atoms = new Atom[1]; GlobalC::ucell.ntype = 1; GlobalC::ucell.atoms[0].ncpp.psd = "Sc"; CMtest.need_auto_set(); CMtest.auto_set(1.0, GlobalC::ucell); - EXPECT_EQ(CMtest.mixing_gg0, 1.5); + EXPECT_EQ(CMtest.mixing_gg0, 1.0); } TEST_F(ChargeMixingTest, KerkerScreenRecipTest) @@ -194,7 +194,7 @@ TEST_F(ChargeMixingTest, KerkerScreenRecipTest) { std::complex ration = drhog[i] / drhog_old[i]; double gg = this->pw_basis.gg[i]; - double ration_ref = std::max(gg / (gg + gg0), 0.1); + double ration_ref = std::max(gg / (gg + gg0), 0.1 / CMtest.mixing_beta); EXPECT_NEAR(ration.real(), ration_ref, 1e-10); EXPECT_NEAR(ration.imag(), 0, 1e-10); } From 7b3bf2d3302a084aed8612fb133119624e87b402 Mon Sep 17 00:00:00 2001 From: weiqingzhou Date: Thu, 2 Nov 2023 16:32:13 +0800 Subject: [PATCH 3/4] make corresponding changes in Documentation after PR#3133 --- docs/advanced/input_files/input-main.md | 7 +++---- docs/advanced/scf/converge.md | 2 +- docs/community/faq.md | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md index e1afbcf061..0f55ffd858 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -929,9 +929,8 @@ calculations. - **Description**: In general, the formula of charge mixing can be written as $\rho_{new} = \rho_{old} + \beta * \rho_{update}$, where $\rho_{new}$ represents the new charge density after charge mixing, $\rho_{old}$ represents the charge density in previous step, $\rho_{update}$ is obtained through various mixing methods, and $\beta$ is set by the parameter `mixing_beta`. A lower value of 'mixing_beta' results in less influence of $\rho_{update}$ on $\rho_{new}$, making the self-consistent field (SCF) calculation more stable. However, it may require more steps to achieve convergence. We recommend the following options: - **-10.0**: Program will auto set `mixing_beta` and `mixing_gg0` before charge mixing method starts. - - Default values of transition metal system are `mixing_beta=0.2` and `mixing_gg0=1.5`; - - Default values of metal system (bandgap <= 1.0 eV) are `mixing_beta=0.2` and `mixing_gg0=0.0`; - - Default values of other systems (bandgap > 1.0eV) are `mixing_beta=0.7` and `mixing_gg0=0.0`. + - Default values of metal system (bandgap <= 1.0 eV) are `mixing_beta=0.2` and `mixing_gg0=1.0`; + - Default values of other systems (bandgap > 1.0eV) are `mixing_beta=0.7` and `mixing_gg0=1.0`. - **0**: keep charge density unchanged, usually used for restarting with `init_chg=file` or testing. - **0.1 or less**: if convergence of SCF calculation is difficult to reach, please try `0 < mixing_beta < 0.1`. @@ -951,7 +950,7 @@ We recommend the following options: - **Type**: Real - **Description**: Whether to perfom Kerker scaling. - - **>0**: The high frequency wave vectors will be suppressed by multiplying a scaling factor $\frac{k^2}{k^2+gg0^2}$. Setting `mixing_gg0 = 1.5` is normally a good starting point. + - **>0**: The high frequency wave vectors will be suppressed by multiplying a scaling factor $\frac{k^2}{k^2+gg0^2}$. Setting `mixing_gg0 = 1.0` is normally a good starting point. - **0**: No Kerker scaling is performed. For systems that are difficult to converge, particularly metallic systems, enabling Kerker scaling may aid in achieving convergence. diff --git a/docs/advanced/scf/converge.md b/docs/advanced/scf/converge.md index d068784ff2..d78b69ad37 100644 --- a/docs/advanced/scf/converge.md +++ b/docs/advanced/scf/converge.md @@ -8,7 +8,7 @@ By mixing the electron density with that obtained from previous steps, numerical For each of the mixing types, we also provide variables for controlling relevant parameters, including `mixing_beta`, `mixing_ndim`, and `mixing_gg0`. -The default choice is `broyden`, which should work fine in most cases. If convergence issue arises in metallic systems, inclusion of Kerker preconditioning may be helpful, which can be achieved by setting [mixing_gg0](../input_files/input-main.md#mixing_gg0) to be a positive number. For the default broyden method, a choice of 1.5 might be a good start. +The default choice is `broyden`, which should work fine in most cases. If convergence issue arises in metallic systems, inclusion of Kerker preconditioning may be helpful, which can be achieved by setting [mixing_gg0](../input_files/input-main.md#mixing_gg0) to be a positive number. For the default broyden method, a choice of 1.0 might be a good start. A large `mixing_beta` means a larger change in electron density for each SCF step. For well-behaved systems, a larger `mixing_beta` leads to faster convergence. However, for some difficult cases, a smaller `mixing_beta` is preferred to avoid numerical instabilities. diff --git a/docs/community/faq.md b/docs/community/faq.md index 4d3c7e8848..8daadb6492 100644 --- a/docs/community/faq.md +++ b/docs/community/faq.md @@ -70,7 +70,7 @@ This is usually caused by overloading of CPUs' memory without specifying thread **2. My relaxation failed. How to deal with it?** -This is usually caused by the difficulty in converging charge density. Reducing charge mixing coefficient (`mixing_beta`) might help. For large systems up to hundreds of atoms, it is suggested to choose the Kerker mixing method by setting parameter "mixing_gg0" as "1.5". +This is usually caused by the difficulty in converging charge density. Reducing charge mixing coefficient (`mixing_beta`) might help. For large systems up to hundreds of atoms, it is suggested to choose the Kerker mixing method by setting parameter "mixing_gg0" as "1.0". Sometimes, loose convergence threshold of charge density (parameter "scf_thr") will cause atomic forces not correctly enough, please set it at most "1e-7" for relaxation calculation. From d94421f6cc455d225d203086eceddaece30992bd Mon Sep 17 00:00:00 2001 From: weiqingzhou Date: Thu, 2 Nov 2023 16:46:20 +0800 Subject: [PATCH 4/4] extra add --- docs/advanced/input_files/input-main.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/advanced/input_files/input-main.md b/docs/advanced/input_files/input-main.md index 0f55ffd858..4988a2d4b4 100644 --- a/docs/advanced/input_files/input-main.md +++ b/docs/advanced/input_files/input-main.md @@ -950,7 +950,7 @@ We recommend the following options: - **Type**: Real - **Description**: Whether to perfom Kerker scaling. - - **>0**: The high frequency wave vectors will be suppressed by multiplying a scaling factor $\frac{k^2}{k^2+gg0^2}$. Setting `mixing_gg0 = 1.0` is normally a good starting point. + - **>0**: The high frequency wave vectors will be suppressed by multiplying a scaling factor $\frac{k^2}{k^2+gg0^2}$. Setting `mixing_gg0 = 1.0` is normally a good starting point. Kerker preconditioner will be automatically turned off if `mixing_beta <= 0.1`. - **0**: No Kerker scaling is performed. For systems that are difficult to converge, particularly metallic systems, enabling Kerker scaling may aid in achieving convergence.