Skip to content

Commit 2c7ebf0

Browse files
authored
Refactor: Refine ELF Output for Noncollinear Spin (nspin=4) (deepmodeling#6914)
* Fix: Remove the warning for cal_elf in NSPIN=4 case * Refactor: Update the calculation of ELF for NSPIN=4 case. * Doc: Update the documentation of out_elf * Test: Add an integrate test `tests/03_NAO_multik/63_NO_KP_out_elf` for out_elf with NSPIN=4 * Fix: Update the annotation of write_elf * Fix: Enhance the stability of write_elf for spin=2 case * Test: update 63_NO_KP_out_elf * Test: Reduce the cell length of 63_NO_KP_out_elf
1 parent f02f239 commit 2c7ebf0

10 files changed

Lines changed: 383 additions & 47 deletions

File tree

docs/advanced/input_files/input-main.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2133,12 +2133,12 @@ These variables are used to control the output of properties.
21332133
- **Availability**: Only for Kohn-Sham DFT and Orbital Free DFT.
21342134
- **Description**: Whether to output the electron localization function (ELF) in the folder `OUT.${suffix}`. The files are named as
21352135
- nspin = 1:
2136-
- ELF.cube: ${\rm{ELF}} = \frac{1}{1+\chi^2}$, $\chi = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i}|^2} - \frac{|\nabla\rho|^2}{8\rho}}{\frac{3}{10}(3\pi^2)^{2/3}\rho^{5/3}}$;
2136+
- elf.cube: ${\rm{ELF}} = \frac{1}{1+\chi^2}$, $\chi = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i}|^2} - \frac{|\nabla\rho|^2}{8\rho}}{\frac{3}{10}(3\pi^2)^{2/3}\rho^{5/3}}$;
21372137
- nspin = 2:
2138-
- ELF_SPIN1.cube, ELF_SPIN2.cube: ${\rm{ELF}}_\sigma = \frac{1}{1+\chi_\sigma^2}$, $\chi_\sigma = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i,\sigma}|^2} - \frac{|\nabla\rho_\sigma|^2}{8\rho_\sigma}}{\frac{3}{10}(6\pi^2)^{2/3}\rho_\sigma^{5/3}}$;
2139-
- ELF.cube: ${\rm{ELF}} = \frac{1}{1+\chi^2}$, $\chi = \frac{\frac{1}{2}\sum_{i,\sigma}{f_i |\nabla\psi_{i,\sigma}|^2} - \sum_{\sigma}{\frac{|\nabla\rho_\sigma|^2}{8\rho_\sigma}}}{\sum_{\sigma}{\frac{3}{10}(6\pi^2)^{2/3}\rho_\sigma^{5/3}}}$;
2138+
- elf1.cube, elf2.cube: ${\rm{ELF}}_\sigma = \frac{1}{1+\chi_\sigma^2}$, $\chi_\sigma = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i,\sigma}|^2} - \frac{|\nabla\rho_\sigma|^2}{8\rho_\sigma}}{\frac{3}{10}(6\pi^2)^{2/3}\rho_\sigma^{5/3}}$;
2139+
- elf.cube: ${\rm{ELF}} = \frac{1}{1+\chi^2}$, $\chi = \frac{\frac{1}{2}\sum_{i,\sigma}{f_i |\nabla\psi_{i,\sigma}|^2} - \sum_{\sigma}{\frac{|\nabla\rho_\sigma|^2}{8\rho_\sigma}}}{\sum_{\sigma}{\frac{3}{10}(6\pi^2)^{2/3}\rho_\sigma^{5/3}}}$;
21402140
- nspin = 4 (noncollinear):
2141-
- ELF0.cube, ELF1.cube, ELF2.cube, ELF3.cube: ELF for each Pauli matrix component. Component 0 represents the total charge density, while components 1-3 represent the magnetization in x, y, and z directions respectively. Each component is calculated as ${\rm{ELF}}_i = \frac{1}{1+\chi_i^2}$, where $\chi_i = \frac{\tau_i - \tau_{vW,i}}{\tau_{TF,i}}$, with $\tau_i$ being the kinetic energy density, $\tau_{vW,i} = \frac{1}{2}|\nabla\sqrt{\rho_i}|^2$ the von Weizsäcker kinetic energy density, and $\tau_{TF,i} = \frac{3}{10}(3\pi^2)^{2/3}\rho_i^{5/3}$ the Thomas-Fermi kinetic energy density.
2141+
- elf.cube: ELF for total charge density, ${\rm{ELF}} = \frac{1}{1+\chi^2}$, $\chi = \frac{\frac{1}{2}\sum_{i}{f_i |\nabla\psi_{i}|^2} - \frac{|\nabla\rho|^2}{8\rho}}{\frac{3}{10}(3\pi^2)^{2/3}\rho^{5/3}}$
21422142

21432143
The second integer controls the precision of the kinetic energy density output, if not given, will use `3` as default. For purpose restarting from this file and other high-precision involved calculation, recommend to use `10`.
21442144

source/source_io/read_input_item_output.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,6 @@ void ReadInput::item_output()
564564
{
565565
ModuleBase::WARNING_QUIT("ReadInput", "ELF is only aviailable for ksdft and ofdft");
566566
}
567-
if (para.input.out_elf[0] > 0 && para.input.nspin == 4)
568-
{
569-
ModuleBase::WARNING_QUIT("ReadInput", "ELF is not aviailable for nspin = 4");
570-
}
571567
};
572568
sync_intvec(input.out_elf, 2, 0);
573569
this->add_item(item);

source/source_io/write_elf.cpp

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,20 @@ void write_elf(
1818
const UnitCell* ucell_,
1919
const int& precision)
2020
{
21-
std::vector<std::vector<double>> elf(nspin, std::vector<double>(rho_basis->nrxx, 0.));
21+
// For nspin = 4, we only calculate the total ELF using the rho_total and tau_total,
22+
// containing in the first channel of rho and tau.
23+
// What's more, we have not introduced the U(1) and SU(2) gauge invariance corrections
24+
// proposed by Desmarais J K, Vignale G, Bencheikh K, et al. Physical Review Letters, 2024, 133(13): 136401,
25+
// where the current density is also included in the ELF calculation.
26+
27+
int nspin_eff = (nspin == 4) ? 1 : nspin;
28+
29+
std::vector<std::vector<double>> elf(nspin_eff, std::vector<double>(rho_basis->nrxx, 0.));
2230
// 1) calculate the kinetic energy density of vW KEDF
23-
std::vector<std::vector<double>> tau_vw(nspin, std::vector<double>(rho_basis->nrxx, 0.));
31+
std::vector<std::vector<double>> tau_vw(nspin_eff, std::vector<double>(rho_basis->nrxx, 0.));
2432
std::vector<double> phi(rho_basis->nrxx, 0.); // phi = sqrt(rho)
2533

26-
for (int is = 0; is < nspin; ++is)
34+
for (int is = 0; is < nspin_eff; ++is)
2735
{
2836
for (int ir = 0; ir < rho_basis->nrxx; ++ir)
2937
{
@@ -54,37 +62,34 @@ void write_elf(
5462
}
5563

5664
// 2) calculate the kinetic energy density of TF KEDF
57-
std::vector<std::vector<double>> tau_TF(nspin, std::vector<double>(rho_basis->nrxx, 0.));
65+
std::vector<std::vector<double>> tau_TF(nspin_eff, std::vector<double>(rho_basis->nrxx, 0.));
5866
const double c_tf
5967
= 3.0 / 10.0 * std::pow(3 * std::pow(M_PI, 2.0), 2.0 / 3.0)
6068
* 2.0; // 10/3*(3*pi^2)^{2/3}, multiply by 2 to convert unit from Hartree to Ry, finally in Ry*Bohr^(-2)
61-
if (nspin == 1)
69+
if (nspin == 1 || nspin == 4)
6270
{
6371
for (int ir = 0; ir < rho_basis->nrxx; ++ir)
6472
{
65-
tau_TF[0][ir] = c_tf * std::pow(rho[0][ir], 5.0 / 3.0);
66-
}
67-
}
68-
else if (nspin == 2)
69-
{
70-
for (int is = 0; is < nspin; ++is)
71-
{
72-
for (int ir = 0; ir < rho_basis->nrxx; ++ir)
73+
if (rho[0][ir] > 0.0)
7374
{
74-
tau_TF[is][ir] = 0.5 * c_tf * std::pow(2.0 * rho[is][ir], 5.0 / 3.0);
75+
tau_TF[0][ir] = c_tf * std::pow(rho[0][ir], 5.0 / 3.0);
76+
}
77+
else
78+
{
79+
tau_TF[0][ir] = 0.0;
7580
}
7681
}
7782
}
78-
else if (nspin == 4)
83+
else if (nspin == 2)
7984
{
85+
// the spin-scaling law: tau_TF[rho_up, rho_dn] = 1/2 * (tau_TF[2*rho_up] + tau_TF[2*rho_dn])
8086
for (int is = 0; is < nspin; ++is)
8187
{
8288
for (int ir = 0; ir < rho_basis->nrxx; ++ir)
8389
{
84-
// Handle negative densities for numerical stability
8590
if (rho[is][ir] > 0.0)
8691
{
87-
tau_TF[is][ir] = c_tf * std::pow(rho[is][ir], 5.0 / 3.0);
92+
tau_TF[is][ir] = 0.5 * c_tf * std::pow(2.0 * rho[is][ir], 5.0 / 3.0);
8893
}
8994
else
9095
{
@@ -96,7 +101,7 @@ void write_elf(
96101

97102
// 3) calculate the enhancement factor F = (tau_KS - tau_vw) / tau_TF, and then ELF = 1 / (1 + F^2)
98103
double eps = 1.0e-5; // suppress the numerical instability in LCAO (Ref: Acta Phys. -Chim. Sin. 2011, 27(12), 2786-2792. doi: 10.3866/PKU.WHXB20112786)
99-
for (int is = 0; is < nspin; ++is)
104+
for (int is = 0; is < nspin_eff; ++is)
100105
{
101106
for (int ir = 0; ir < rho_basis->nrxx; ++ir)
102107
{
@@ -116,7 +121,7 @@ void write_elf(
116121
double ef_tmp = 0.0;
117122
int out_fermi = 0;
118123

119-
if (nspin == 1)
124+
if (nspin == 1 || nspin == 4)
120125
{
121126
std::string fn = out_dir + "/elf.cube";
122127

@@ -174,25 +179,5 @@ void write_elf(
174179
precision,
175180
out_fermi);
176181
}
177-
else if (nspin == 4)
178-
{
179-
for (int is = 0; is < nspin; ++is)
180-
{
181-
std::string fn = out_dir + "/elf" + std::to_string(is) + ".cube";
182-
183-
int ispin = is;
184-
185-
ModuleIO::write_vdata_palgrid(pgrid,
186-
elf[is].data(),
187-
ispin,
188-
nspin,
189-
istep_in,
190-
fn,
191-
ef_tmp,
192-
ucell_,
193-
precision,
194-
out_fermi);
195-
}
196-
}
197182
}
198183
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
INPUT_PARAMETERS
2+
#Parameters (1.General)
3+
suffix autotest
4+
calculation scf
5+
6+
nbands 20
7+
pseudo_dir ../../PP_ORB
8+
orbital_dir ../../PP_ORB
9+
10+
#Parameters (2.Iteration)
11+
ecutwfc 5
12+
scf_thr 1e-7
13+
scf_nmax 100
14+
15+
nspin 4
16+
#Parameters (3.Basis)
17+
basis_type lcao
18+
19+
#Parameters (4.Smearing)
20+
smearing_method gauss
21+
smearing_sigma 0.002
22+
23+
#Parameters (5.Mixing)
24+
mixing_type plain
25+
mixing_beta 0.7
26+
mixing_gg0 0.0
27+
28+
out_elf 1
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
K_POINTS
2+
0
3+
Gamma
4+
2 1 1 0 0 0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test out_elf for nspin=4
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
ATOMIC_SPECIES
2+
C 12.0 C_ONCV_PBE-1.0.upf
3+
4+
NUMERICAL_ORBITAL
5+
C_gga_8au_100Ry_2s2p1d.orb
6+
7+
LATTICE_CONSTANT
8+
1.89035917
9+
10+
LATTICE_VECTORS
11+
4.0 0.0 0.0 #latvec3
12+
0.0 4.0 0.0
13+
0.0 0.0 4.0
14+
15+
ATOMIC_POSITIONS
16+
Direct
17+
18+
C #label
19+
0 #magnetism
20+
1 #number of atoms
21+
0.0 0.0000000000000000 0.0000000000000000 1 1 1
22+

0 commit comments

Comments
 (0)