Skip to content

Commit 840f0d5

Browse files
jinzx10kirk0830WHUweiqingzhou
authored
Fix: various matrix elements calculations in orbital generation (#3940)
* jy-jy two-center integration * change index set to vector * more accurate algorithm for jy-jy & unit fix * enable non-LCAO build * fix * initialize local variables * change the usage of ucell in Numerical_Basis from GlobalC to function arguments * clean up function interface * various bug fixed * fix unit test * add const qualifiers --------- Co-authored-by: kirk0830 <[email protected]> Co-authored-by: wqzhou <[email protected]>
1 parent 1a10cfc commit 840f0d5

11 files changed

+475
-113
lines changed

source/Makefile.Objects

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ OBJS_IO=input.o\
429429
dos_nao.o\
430430
numerical_descriptor.o\
431431
numerical_basis.o\
432+
numerical_basis_jyjy.o\
432433
output.o\
433434
print_info.o\
434435
read_cube.o\

source/module_esolver/esolver_ks_pw.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1314,7 +1314,7 @@ void ESolver_KS_PW<T, Device>::after_all_runners(void)
13141314
if(INPUT.bessel_nao_rcuts.size() == 1)
13151315
{
13161316
Numerical_Basis numerical_basis;
1317-
numerical_basis.output_overlap(this->psi[0], this->sf, this->kv, this->pw_wfc);
1317+
numerical_basis.output_overlap(this->psi[0], this->sf, this->kv, this->pw_wfc, GlobalC::ucell);
13181318
}
13191319
else
13201320
{
@@ -1339,7 +1339,7 @@ void ESolver_KS_PW<T, Device>::after_all_runners(void)
13391339
Will be refactored in the future.
13401340
*/
13411341
Numerical_Basis numerical_basis;
1342-
numerical_basis.output_overlap(this->psi[0], this->sf, this->kv, this->pw_wfc);
1342+
numerical_basis.output_overlap(this->psi[0], this->sf, this->kv, this->pw_wfc, GlobalC::ucell);
13431343
std::string old_fname_header = winput::spillage_outdir
13441344
+ "/"
13451345
+ "orb_matrix.";

source/module_io/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ list(APPEND objects
88
nscf_band.cpp
99
write_istate_info.cpp
1010
numerical_basis.cpp
11+
numerical_basis_jyjy.cpp
1112
numerical_descriptor.cpp
1213
output.cpp
1314
print_info.cpp

source/module_io/bessel_basis.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ double Bessel_Basis::Polynomial_Interpolation2
9999
const double x3 = 3.0 - x0;
100100
const double y=
101101
this->TableOne(l, ie, iq) * x1 * x2 * x3 / 6.0 +
102-
this->TableOne(l, ie, iq) * x0 * x2 * x3 / 2.0 -
103-
this->TableOne(l, ie, iq) * x1 * x0 * x3 / 2.0 +
104-
this->TableOne(l, ie, iq) * x1 * x2 * x0 / 6.0 ;
102+
this->TableOne(l, ie, iq+1) * x0 * x2 * x3 / 2.0 -
103+
this->TableOne(l, ie, iq+2) * x1 * x0 * x3 / 2.0 +
104+
this->TableOne(l, ie, iq+3) * x1 * x2 * x0 / 6.0 ;
105105
return y;
106106
}
107107

@@ -117,9 +117,9 @@ double Bessel_Basis::Polynomial_Interpolation(
117117
const double x3 = 3.0 - x0;
118118
const double y=
119119
this->Faln(it, l, ic, iq) * x1 * x2 * x3 / 6.0 +
120-
this->Faln(it, l, ic, iq) * x0 * x2 * x3 / 2.0 -
121-
this->Faln(it, l, ic, iq) * x1 * x0 * x3 / 2.0 +
122-
this->Faln(it, l, ic, iq) * x1 * x2 * x0 / 6.0 ;
120+
this->Faln(it, l, ic, iq+1) * x0 * x2 * x3 / 2.0 -
121+
this->Faln(it, l, ic, iq+2) * x1 * x0 * x3 / 2.0 +
122+
this->Faln(it, l, ic, iq+3) * x1 * x2 * x0 / 6.0 ;
123123
return y;
124124
}
125125

source/module_io/numerical_basis.cpp

Lines changed: 140 additions & 88 deletions
Large diffs are not rendered by default.

source/module_io/numerical_basis.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,49 +29,58 @@ class Numerical_Basis
2929
Numerical_Basis();
3030
~Numerical_Basis();
3131

32-
void start_from_file_k(const int& ik, ModuleBase::ComplexMatrix& psi, const Structure_Factor& sf, const ModulePW::PW_Basis_K* wfcpw);
33-
void output_overlap(const psi::Psi<std::complex<double>>& psi, const Structure_Factor& sf, const K_Vectors& kv, const ModulePW::PW_Basis_K* wfcpw);
34-
32+
void start_from_file_k(const int& ik, ModuleBase::ComplexMatrix& psi, const Structure_Factor& sf, const ModulePW::PW_Basis_K* wfcpw, const UnitCell& ucell);
33+
void output_overlap(const psi::Psi<std::complex<double>>& psi, const Structure_Factor& sf, const K_Vectors& kv, const ModulePW::PW_Basis_K* wfcpw, const UnitCell& ucell);
3534

3635
private:
3736
bool init_label = false;
3837

3938
Bessel_Basis bessel_basis;
4039

4140
std::vector<ModuleBase::IntArray> mu_index;
42-
static std::vector<ModuleBase::IntArray> init_mu_index(void);
41+
static std::vector<ModuleBase::IntArray> init_mu_index(const UnitCell& ucell);
4342

4443
void numerical_atomic_wfc(const int& ik,
4544
const ModulePW::PW_Basis_K* wfcpw,
4645
ModuleBase::ComplexMatrix& psi,
47-
const Structure_Factor& sf);
46+
const Structure_Factor& sf,
47+
const UnitCell& ucell);
4848

4949
ModuleBase::ComplexArray cal_overlap_Q(const int& ik,
5050
const int& np,
5151
const ModulePW::PW_Basis_K* wfcpw,
5252
const psi::Psi<std::complex<double>>& psi,
5353
const double derivative_order,
54-
const Structure_Factor& sf) const;
54+
const Structure_Factor& sf,
55+
const UnitCell& ucell) const;
5556

57+
// computed in the plane-wave basis
5658
ModuleBase::ComplexArray cal_overlap_Sq(const int& ik,
5759
const int& np,
5860
const double derivative_order,
5961
const Structure_Factor& sf,
60-
const ModulePW::PW_Basis_K* wfcpw) const;
62+
const ModulePW::PW_Basis_K* wfcpw,
63+
const UnitCell& ucell) const;
6164

6265
static ModuleBase::matrix cal_overlap_V(const ModulePW::PW_Basis_K* wfcpw,
6366
const psi::Psi<std::complex<double>>& psi,
6467
const double derivative_order,
65-
const K_Vectors& kv);
68+
const K_Vectors& kv,
69+
const double tpiba);
6670

67-
ModuleBase::realArray cal_flq(const int ik, const std::vector<ModuleBase::Vector3<double>> &gk) const;
71+
// gk should be in the atomic unit (Bohr)
72+
ModuleBase::realArray cal_flq(const std::vector<ModuleBase::Vector3<double>> &gk,
73+
const int ucell_lmax) const;
6874

69-
static ModuleBase::matrix cal_ylm(const std::vector<ModuleBase::Vector3<double>> &gk);
75+
// Ylm does not depend on the magnitude so unit is not important
76+
static ModuleBase::matrix cal_ylm(const std::vector<ModuleBase::Vector3<double>> &gk,
77+
const int ucell_lmax);
7078

79+
// gk and the returned gpow are both in the atomic unit (Bohr)
7180
static std::vector<double> cal_gpow(const std::vector<ModuleBase::Vector3<double>> &gk,
7281
const double derivative_order);
7382

74-
static void output_info(std::ofstream& ofs, const Bessel_Basis& bessel_basis, const K_Vectors& kv);
83+
static void output_info(std::ofstream& ofs, const Bessel_Basis& bessel_basis, const K_Vectors& kv, const UnitCell& ucell);
7584

7685
static void output_k(std::ofstream& ofs, const K_Vectors& kv);
7786

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include "module_io/numerical_basis_jyjy.h"
2+
#include "module_basis/module_nao/two_center_integrator.h"
3+
4+
namespace NumericalBasis
5+
{
6+
#ifdef __LCAO
7+
using index_t = std::tuple<int, int, int, int>;
8+
9+
std::vector<index_t> indexgen(const std::vector<int>& natom,
10+
const std::vector<int>& lmax)
11+
{
12+
#ifdef __DEBUG
13+
assert(natom.size() == lmax.size());
14+
#endif
15+
std::vector<index_t> index;
16+
for (size_t itype = 0; itype < natom.size(); ++itype)
17+
{
18+
for (int iatom = 0; iatom < natom[itype]; ++iatom)
19+
{
20+
for (int l = 0; l <= lmax[itype]; ++l)
21+
{
22+
for (int M = 0; M < 2*l+1; ++M)
23+
{
24+
// convert the "abacus M" to the conventional m
25+
const int m = (M % 2 == 0) ? -M/2 : (M+1)/2;
26+
index.emplace_back(itype, iatom, l, m);
27+
}
28+
}
29+
}
30+
}
31+
return index;
32+
}
33+
34+
35+
ModuleBase::ComplexArray cal_overlap_Sq(
36+
const char type,
37+
const int lmax,
38+
const int nbes,
39+
const double rcut,
40+
const std::vector<std::vector<ModuleBase::Vector3<double>>>& R,
41+
const std::vector<index_t>& mu_index
42+
)
43+
{
44+
// allocate output array
45+
const int nlocal = mu_index.size();
46+
ModuleBase::ComplexArray overlap_Sq(nlocal, nlocal, nbes, nbes);
47+
overlap_Sq.zero_out();
48+
49+
// build a RadialCollection of spherical Bessel functions
50+
const double dr = 0.005; // grid spacing for SphbesRadials; smaller for higher precision
51+
RadialCollection orb;
52+
orb.build(lmax, nbes, rcut, 0.0, dr);
53+
54+
ModuleBase::SphericalBesselTransformer sbt;
55+
orb.set_transformer(sbt);
56+
57+
const double rmax = orb.rcut_max() * 2.0;
58+
const int nr = static_cast<int>(rmax / dr) + 1;
59+
60+
orb.set_uniform_grid(true, nr, rmax, 'i', true);
61+
62+
// build the two-center integrator
63+
TwoCenterIntegrator intor;
64+
intor.tabulate(orb, orb, type, nr, rmax);
65+
66+
// traverse the vector of composite index (itype, iatom, l, m)
67+
int t1 = 0, a1 = 0, l1 = 0, m1 = 0;
68+
int t2 = 0, a2 = 0, l2 = 0, m2 = 0;
69+
for (auto it1 = mu_index.cbegin(); it1 != mu_index.cend(); ++it1)
70+
{
71+
std::tie(t1, a1, l1, m1) = *it1;
72+
for (auto it2 = mu_index.cbegin(); it2 != mu_index.cend(); ++it2)
73+
{
74+
std::tie(t2, a2, l2, m2) = *it2;
75+
ModuleBase::Vector3<double> dR = R[t2][a2] - R[t1][a1];
76+
for (int zeta1 = 0; zeta1 < nbes; ++zeta1)
77+
{
78+
for (int zeta2 = 0; zeta2 < nbes; ++zeta2)
79+
{
80+
double elem = 0.0;
81+
intor.calculate(t1, l1, zeta1, m1,
82+
t2, l2, zeta2, m2,
83+
dR, &elem);
84+
overlap_Sq(it1 - mu_index.begin(),
85+
it2 - mu_index.begin(),
86+
zeta1, zeta2) = elem;
87+
}
88+
}
89+
}
90+
}
91+
92+
return overlap_Sq;
93+
}
94+
#endif
95+
96+
} // end of namespace NumericalBasis
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef NUMERICAL_BASIS_JYJY_H
2+
#define NUMERICAL_BASIS_JYJY_H
3+
4+
#include <tuple>
5+
#include <vector>
6+
#include "module_base/vector3.h"
7+
#include "module_base/complexarray.h"
8+
9+
namespace NumericalBasis
10+
{
11+
std::vector<std::tuple<int, int, int, int>> indexgen(const std::vector<int>& natom,
12+
const std::vector<int>& lmax);
13+
14+
/**
15+
* @brief <jy|op|jy> overlap matrix (two-center integration)
16+
*
17+
*
18+
* @param[in] type 'S' (op = 1) or 'T' (kinetic, op = -\nabla^2)
19+
* @param[in] lmax maximum angular momentum
20+
* @param[in] nbes number of Bessel functions
21+
* @param[in] rcut cutoff radius
22+
* @param[in] sigma smoothing parameter
23+
* @param[in] tau_cart atomic positions (in Bohr)
24+
* @param[in] mu_index composite index
25+
*
26+
*/
27+
ModuleBase::ComplexArray cal_overlap_Sq(
28+
const char type, // 'S' or 'T'
29+
const int lmax,
30+
const int nbes,
31+
const double rcut,
32+
const std::vector<std::vector<ModuleBase::Vector3<double>>>& tau_cart,
33+
const std::vector<std::tuple<int, int, int, int>>& mu_index
34+
);
35+
36+
}
37+
38+
#endif

source/module_io/test/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,3 +173,9 @@ add_test(NAME read_wfc_pw_test_parallel
173173
COMMAND mpirun -np 4 ./read_wfc_pw_test
174174
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
175175
)
176+
177+
AddTest(
178+
TARGET numerical_basis_test
179+
LIBS base ${math_libs} device numerical_atomic_orbitals container orb
180+
SOURCES numerical_basis_test.cpp ../numerical_basis_jyjy.cpp
181+
)

source/module_io/test/bessel_basis_test.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -484,9 +484,9 @@ TEST_F(TestBesselBasis, PolynomialInterpolation2Test) {
484484
i_Lmax, d_dr, d_dk
485485
);
486486
double d_yExpected = vvv_d_TableOne[0][0][i_position]*d_x1*d_x2*d_x3/6.0+
487-
vvv_d_TableOne[0][0][i_position]*d_x0*d_x2*d_x3/2.0-
488-
vvv_d_TableOne[0][0][i_position]*d_x1*d_x0*d_x3/2.0+
489-
vvv_d_TableOne[0][0][i_position]*d_x1*d_x2*d_x0/6.0;
487+
vvv_d_TableOne[0][0][i_position+1]*d_x0*d_x2*d_x3/2.0-
488+
vvv_d_TableOne[0][0][i_position+2]*d_x1*d_x0*d_x3/2.0+
489+
vvv_d_TableOne[0][0][i_position+3]*d_x1*d_x2*d_x0/6.0;
490490
double d_yTested = besselBasis.Polynomial_Interpolation2(0, 0, d_Gnorm);
491491
EXPECT_NEAR(d_yExpected, d_yTested, 0.01);
492492
}
@@ -552,9 +552,9 @@ TEST_F(TestBesselBasis, PolynomialInterpolationTest) {
552552
"./support/BesselBasis_UnitTest_C4_AtomType0.html", i_Ntype, i_Lmax, 1, i_Nq, vvv_d_TableOne
553553
);
554554
double d_yExpected = vvvv_d_Faln[0][0][0][i_position]*d_x1*d_x2*d_x3/6.0+
555-
vvvv_d_Faln[0][0][0][i_position]*d_x0*d_x2*d_x3/2.0-
556-
vvvv_d_Faln[0][0][0][i_position]*d_x1*d_x0*d_x3/2.0+
557-
vvvv_d_Faln[0][0][0][i_position]*d_x1*d_x2*d_x0/6.0;
555+
vvvv_d_Faln[0][0][0][i_position+1]*d_x0*d_x2*d_x3/2.0-
556+
vvvv_d_Faln[0][0][0][i_position+2]*d_x1*d_x0*d_x3/2.0+
557+
vvvv_d_Faln[0][0][0][i_position+3]*d_x1*d_x2*d_x0/6.0;
558558
double d_yTested = besselBasis.Polynomial_Interpolation(0, 0, 0, d_Gnorm);
559559
EXPECT_NEAR(d_yExpected, d_yTested, 0.01);
560560
}

0 commit comments

Comments
 (0)