Skip to content

Commit fd76546

Browse files
Feature: a new mixing method for magnetic calculations (#3226)
* improved implementation of kerker preconditioner * fix bug in charge_mixing_test * make corresponding changes in Documentation after PR#3133 * extra add * new mixing method for nspin=2 * add some comment for gg=0 * nspin2 mixing method for pw * remove autoset and set default * fix charge_mixing_test & add some documentation of mixing_beta_mag/mixing_gg0_mag * use old mixing to support double_grid * fix fatal error in CI * recover Autotest.sh * 108 * 108 * revert 101_PW_15_lowz * revert 107_PW_OK * revert 186_PW_KG_100 * revert 186_PW_SKG_10D10S * revert 201_NO_15_f_pseudopots * revert 201_NO_KP_DJ_CF_CS_GaAs * revert 204_NO_KP_AFM * revert 207_NO_KP_OHS_SPIN4 * revert 207_NO_KP_OTdH * revert 207_NO_OK * revert 220_NO_KP_MD_wfc_out * revert 101_PW_15_pseudopots_LibxcLDA * Autotest.sh * fix bug in deepks_tests * fix bugs in io_input_test * update ref of 260 and 360 * do not use renormalize_rho in pw calculations * set mixing_gg0=0.0 for 601_TD_DFT tests * change mixing_type=plain to broyden * add two_beta to replace NSPIN in mixing class * add UnitTests of inner_product_recip_new1/2 & kerker_recip_new
1 parent 9af48f8 commit fd76546

File tree

64 files changed

+1090
-78
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+1090
-78
lines changed

docs/advanced/input_files/input-main.md

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -964,15 +964,21 @@ calculations.
964964
- **Type**: Real
965965
- **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.
966966
We recommend the following options:
967-
- **-10.0**: Program will auto set `mixing_beta` and `mixing_gg0` before charge mixing method starts.
968-
- Default values of metal system (bandgap <= 1.0 eV) are `mixing_beta=0.2` and `mixing_gg0=1.0`;
969-
- Default values of other systems (bandgap > 1.0eV) are `mixing_beta=0.7` and `mixing_gg0=1.0`.
967+
- **0.8**: `nspin=1`
968+
- **0.4**: `nspin=2`
969+
- **0.2**: `nspin=4`
970970
- **0**: keep charge density unchanged, usually used for restarting with `init_chg=file` or testing.
971971
- **0.1 or less**: if convergence of SCF calculation is difficult to reach, please try `0 < mixing_beta < 0.1`.
972972

973-
Note: For low-dimensional large systems, the setup of `mixing_beta=0.1`, `mixing_ndim=20`, and `mixing_gg0=1.5` usually works well.
973+
Note: For low-dimensional large systems, the setup of `mixing_beta=0.1`, `mixing_ndim=20`, and `mixing_gg0=1.0` usually works well.
974974

975-
- **Default**: -10.0
975+
- **Default**: 0.8 for `nspin=1`, 0.4 for `nspin=2`, 0.2 for `nspin=4`.
976+
977+
### mixing_beta_mag
978+
979+
- **Type**: Real
980+
- **Description**: Mixing parameter of magnetic density.
981+
- **Default**: `4*mixing_beta`
976982

977983
### mixing_ndim
978984

@@ -985,11 +991,18 @@ We recommend the following options:
985991
### mixing_gg0
986992

987993
- **Type**: Real
988-
- **Description**: Whether to perfom Kerker scaling.
994+
- **Description**: Whether to perfom Kerker scaling for charge density.
989995
- **>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`.
990996
- **0**: No Kerker scaling is performed.
991997

992998
For systems that are difficult to converge, particularly metallic systems, enabling Kerker scaling may aid in achieving convergence.
999+
- **Default**: 1.0
1000+
1001+
### mixing_gg0_mag
1002+
1003+
- **Type**: Real
1004+
- **Description**: Whether to perfom Kerker preconditioner of magnetic density.
1005+
Note: we do not recommand to open Kerker preconditioner of magnetic density unless the system is too hard to converge.
9931006
- **Default**: 0.0
9941007

9951008
### mixing_tau

source/module_base/global_variable.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,9 @@ std::string of_kernel_file = "WTkernel.txt";
248248
std::string MIXING_MODE = "broyden";
249249
double MIXING_BETA = 0.7;
250250
int MIXING_NDIM = 8;
251-
double MIXING_GG0 = 0.0;
251+
double MIXING_GG0 = 1.00;
252+
double MIXING_BETA_MAG = 1.6;
253+
double MIXING_GG0_MAG = 1.00;
252254
bool MIXING_TAU = 0;
253255

254256
//==========================================================

source/module_base/global_variable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,8 @@ extern double MIXING_BETA;
278278
extern int MIXING_NDIM;
279279
extern double MIXING_GG0;
280280
extern bool MIXING_TAU;
281+
extern double MIXING_BETA_MAG;
282+
extern double MIXING_GG0_MAG;
281283

282284
//==========================================================
283285
// device flags added by denghui

source/module_base/module_mixing/broyden_mixing.h

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "module_base/memory.h"
77
#include "module_base/timer.h"
88
#include "module_base/tool_title.h"
9+
#include "module_base/global_variable.h"
910

1011
namespace Base_Mixing
1112
{
@@ -36,6 +37,14 @@ class Broyden_Mixing : public Mixing
3637
this->mixing_beta = mixing_beta;
3738
this->coef = std::vector<double>(mixing_ndim + 1);
3839
this->beta = ModuleBase::matrix(mixing_ndim, mixing_ndim, true);
40+
if (GlobalV::NSPIN == 1 || GlobalV::NSPIN == 4)
41+
{
42+
this->two_beta = 0;
43+
}
44+
else if (GlobalV::NSPIN == 2)
45+
{
46+
this->two_beta = 1;
47+
}
3948
}
4049
virtual ~Broyden_Mixing() override
4150
{
@@ -125,21 +134,43 @@ class Broyden_Mixing : public Mixing
125134
{
126135
F_tmp[i] = data_out[i] - data_in[i];
127136
}
128-
129137
// get screened F
130138
if (screen != nullptr)
131139
screen(F_tmp.data());
132-
133140
// container::Tensor data = data_in + mixing_beta * F;
134141
std::vector<FPTYPE> data(length);
142+
// mix density and magnetic density sperately
143+
if (this->two_beta == 0)
144+
{
145+
// rho_tot
135146
#ifdef _OPENMP
136147
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
137148
#endif
138-
for (int i = 0; i < length; ++i)
139-
{
140-
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
149+
for (int i = 0; i < length; ++i)
150+
{
151+
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
152+
}
141153
}
154+
else if (this->two_beta == 1)
155+
{
156+
// rho_tot
157+
#ifdef _OPENMP
158+
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
159+
#endif
160+
for (int i = 0; i < length / 2; ++i)
161+
{
162+
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
163+
}
164+
// magnetism
165+
#ifdef _OPENMP
166+
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
167+
#endif
168+
for (int i = length / 2; i < length; ++i)
169+
{
170+
data[i] = data_in[i] + GlobalV::MIXING_BETA_MAG * F_tmp[i];
171+
}
142172

173+
}
143174
mdata.push(data.data());
144175

145176
if (!need_calcoef)
@@ -312,6 +343,8 @@ class Broyden_Mixing : public Mixing
312343
}
313344
// the number of calculated dF
314345
int ndim_cal_dF = 0;
346+
// if we should considere two beta
347+
int two_beta = 0;
315348
};
316349
} // namespace Base_Mixing
317350
#endif

source/module_base/module_mixing/plain_mixing.h

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "module_base/memory.h"
55
#include "module_base/timer.h"
66
#include "module_base/tool_title.h"
7+
#include "module_base/global_variable.h"
78

89
namespace Base_Mixing
910
{
@@ -19,6 +20,14 @@ class Plain_Mixing : public Mixing
1920
this->mixing_beta = mixing_beta;
2021
this->data_ndim = 1;
2122
this->coef = std::vector<double>(1, 1.0);
23+
if (GlobalV::NSPIN == 1 || GlobalV::NSPIN == 4)
24+
{
25+
this->two_beta = 0;
26+
}
27+
else if (GlobalV::NSPIN == 2)
28+
{
29+
this->two_beta = 1;
30+
}
2231
}
2332
virtual ~Plain_Mixing() override{};
2433

@@ -108,16 +117,43 @@ class Plain_Mixing : public Mixing
108117

109118
// container::Tensor data = data_in + mixing_beta * F;
110119
std::vector<FPTYPE> data(length);
120+
if (this->two_beta == 0)
121+
{
122+
// rho_tot
111123
#ifdef _OPENMP
112124
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
113125
#endif
114-
for (int i = 0; i < length; ++i)
126+
for (int i = 0; i < length; ++i)
127+
{
128+
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
129+
}
130+
}
131+
else if (this->two_beta == 1)
115132
{
116-
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
133+
// rho_tot
134+
#ifdef _OPENMP
135+
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
136+
#endif
137+
for (int i = 0; i < length / 2; ++i)
138+
{
139+
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
140+
}
141+
// magnetism
142+
#ifdef _OPENMP
143+
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
144+
#endif
145+
for (int i = length / 2; i < length; ++i)
146+
{
147+
data[i] = data_in[i] + GlobalV::MIXING_BETA_MAG * F_tmp[i];
148+
}
149+
117150
}
118151

119152
mdata.push(data.data());
120153
};
154+
155+
// if we should considere two beta
156+
int two_beta = 0;
121157
};
122158
} // namespace Base_Mixing
123159
#endif

source/module_base/module_mixing/pulay_mixing.h

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "module_base/memory.h"
77
#include "module_base/timer.h"
88
#include "module_base/tool_title.h"
9+
#include "module_base/global_variable.h"
910

1011
namespace Base_Mixing
1112
{
@@ -30,6 +31,14 @@ class Pulay_Mixing : public Mixing
3031
this->mixing_beta = mixing_beta;
3132
this->coef = std::vector<double>(mixing_ndim);
3233
this->beta = ModuleBase::matrix(mixing_ndim, mixing_ndim, true);
34+
if (GlobalV::NSPIN == 1 || GlobalV::NSPIN == 4)
35+
{
36+
this->two_beta = 0;
37+
}
38+
else if (GlobalV::NSPIN == 2)
39+
{
40+
this->two_beta = 1;
41+
}
3342
}
3443
virtual ~Pulay_Mixing() override
3544
{
@@ -124,12 +133,36 @@ class Pulay_Mixing : public Mixing
124133

125134
// container::Tensor data = data_in + mixing_beta * F;
126135
std::vector<FPTYPE> data(length);
136+
if (this->two_beta == 0)
137+
{
138+
// rho_tot
127139
#ifdef _OPENMP
128140
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
129141
#endif
130-
for (int i = 0; i < length; ++i)
142+
for (int i = 0; i < length; ++i)
143+
{
144+
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
145+
}
146+
}
147+
else if (this->two_beta == 1)
131148
{
132-
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
149+
// rho_tot
150+
#ifdef _OPENMP
151+
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
152+
#endif
153+
for (int i = 0; i < length / 2; ++i)
154+
{
155+
data[i] = data_in[i] + this->mixing_beta * F_tmp[i];
156+
}
157+
// magnetism
158+
#ifdef _OPENMP
159+
#pragma omp parallel for schedule(static, 4096 / sizeof(FPTYPE))
160+
#endif
161+
for (int i = length / 2; i < length; ++i)
162+
{
163+
data[i] = data_in[i] + GlobalV::MIXING_BETA_MAG * F_tmp[i];
164+
}
165+
133166
}
134167

135168
mdata.push(data.data());
@@ -275,6 +308,8 @@ class Pulay_Mixing : public Mixing
275308
int mixing_ndim = -1;
276309
// start index for F
277310
int start_F = 0;
311+
// if we should considere two beta
312+
int two_beta = 0;
278313
};
279314
} // namespace Base_Mixing
280315
#endif

0 commit comments

Comments
 (0)